(dired-sort-inhibit): New variable.
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
5d335845 2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99, 2000, 2001, 2002
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"
182#include "macros.h"
183#include "disptab.h"
30c566e4 184#include "termhooks.h"
b0a0fbda 185#include "intervals.h"
1c9241f5
KH
186#include "coding.h"
187#include "process.h"
dfcf069d 188#include "region-cache.h"
0ef75e87 189#include "fontset.h"
dfcf069d 190
6d55d620 191#ifdef HAVE_X_WINDOWS
dfcf069d
AS
192#include "xterm.h"
193#endif
a75dfea0
AI
194#ifdef WINDOWSNT
195#include "w32term.h"
196#endif
e0f712ba 197#ifdef MAC_OS
1a578e9b
AC
198#include "macterm.h"
199#endif
a2889657 200
5f5c8ee5
GM
201#define INFINITY 10000000
202
e0f712ba 203#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
2e621225 204extern void set_frame_menubar P_ ((struct frame *f, int, int));
cd6dfed6 205extern int pending_menu_activation;
76412d64
RS
206#endif
207
a2889657
JB
208extern int interrupt_input;
209extern int command_loop_level;
210
b6436d4e
RS
211extern int minibuffer_auto_raise;
212
c4628384 213extern Lisp_Object Qface;
fec8f23e 214extern Lisp_Object Qmode_line, Qmode_line_inactive, Qheader_line;
c4628384 215
399164b4
KH
216extern Lisp_Object Voverriding_local_map;
217extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 218extern Lisp_Object Qmenu_item;
399164b4 219
d46fb96a 220Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 221Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 222Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 223Lisp_Object Qinhibit_point_motion_hooks;
0fcf414f 224Lisp_Object QCeval, Qwhen, QCfile, QCdata, QCpropertize;
5f5c8ee5 225Lisp_Object Qfontified;
6422c1d7 226Lisp_Object Qgrow_only;
869fb12c 227Lisp_Object Qinhibit_eval_during_redisplay;
b384d6f8 228Lisp_Object Qbuffer_position, Qposition, Qobject;
5f5c8ee5 229
cfe03a41
KS
230/* Cursor shapes */
231Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
232
c53a1624
RS
233Lisp_Object Qrisky_local_variable;
234
7033d6df
RS
235/* Holds the list (error). */
236Lisp_Object list_of_error;
237
5f5c8ee5
GM
238/* Functions called to fontify regions of text. */
239
240Lisp_Object Vfontification_functions;
241Lisp_Object Qfontification_functions;
242
e037b9ec 243/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
244 over them. */
245
e037b9ec 246int auto_raise_tool_bar_buttons_p;
5f5c8ee5 247
e037b9ec 248/* Margin around tool bar buttons in pixels. */
5f5c8ee5 249
35a41507 250Lisp_Object Vtool_bar_button_margin;
5f5c8ee5 251
e037b9ec 252/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 253
31ade731 254EMACS_INT tool_bar_button_relief;
5f5c8ee5 255
e037b9ec 256/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
257 items are visible, and no blank lines remain. */
258
e037b9ec 259int auto_resize_tool_bars_p;
399164b4 260
735c094c
KH
261/* Non-nil means don't actually do any redisplay. */
262
263Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
264
30a3f61c
GM
265/* Non-zero means Lisp evaluation during redisplay is inhibited. */
266
869fb12c 267int inhibit_eval_during_redisplay;
30a3f61c 268
5f5c8ee5
GM
269/* Names of text properties relevant for redisplay. */
270
a7e27ef7 271Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
4b41cebb 272extern Lisp_Object Qface, Qinvisible, Qwidth;
5f5c8ee5
GM
273
274/* Symbols used in text property values. */
275
276Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
a7e27ef7 277Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
f3751a65 278Lisp_Object Qmargin;
a7e27ef7 279extern Lisp_Object Qheight;
5f5c8ee5 280
8f897821 281/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 282
8f897821 283Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5
GM
284
285/* Name of the face used to highlight trailing whitespace. */
286
287Lisp_Object Qtrailing_whitespace;
288
289/* The symbol `image' which is the car of the lists used to represent
290 images in Lisp. */
291
292Lisp_Object Qimage;
293
294/* Non-zero means print newline to stdout before next mini-buffer
295 message. */
a2889657
JB
296
297int noninteractive_need_newline;
298
5f5c8ee5 299/* Non-zero means print newline to message log before next message. */
f88eb0b6 300
3c6595e0 301static int message_log_need_newline;
f88eb0b6 302
b14bc55e
RS
303/* Three markers that message_dolog uses.
304 It could allocate them itself, but that causes trouble
305 in handling memory-full errors. */
306static Lisp_Object message_dolog_marker1;
307static Lisp_Object message_dolog_marker2;
308static Lisp_Object message_dolog_marker3;
5f5c8ee5
GM
309\f
310/* The buffer position of the first character appearing entirely or
311 partially on the line of the selected window which contains the
312 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
313 redisplay optimization in redisplay_internal. */
a2889657 314
5f5c8ee5 315static struct text_pos this_line_start_pos;
a2889657 316
5f5c8ee5
GM
317/* Number of characters past the end of the line above, including the
318 terminating newline. */
319
320static struct text_pos this_line_end_pos;
321
322/* The vertical positions and the height of this line. */
a2889657 323
a2889657 324static int this_line_vpos;
5f5c8ee5
GM
325static int this_line_y;
326static int this_line_pixel_height;
327
328/* X position at which this display line starts. Usually zero;
329 negative if first character is partially visible. */
330
331static int this_line_start_x;
a2889657 332
5f5c8ee5 333/* Buffer that this_line_.* variables are referring to. */
a2889657 334
a2889657
JB
335static struct buffer *this_line_buffer;
336
5f5c8ee5
GM
337/* Nonzero means truncate lines in all windows less wide than the
338 frame. */
a2889657 339
a2889657
JB
340int truncate_partial_width_windows;
341
7bbe686f 342/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 343
7bbe686f 344int unibyte_display_via_language_environment;
2311178e 345
5f5c8ee5
GM
346/* Nonzero means we have more than one non-mini-buffer-only frame.
347 Not guaranteed to be accurate except while parsing
348 frame-title-format. */
7bbe686f 349
d39b6696
KH
350int multiple_frames;
351
a2889657
JB
352Lisp_Object Vglobal_mode_string;
353
354/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 355
a2889657
JB
356Lisp_Object Voverlay_arrow_position;
357
5f5c8ee5
GM
358/* String to display for the arrow. Only used on terminal frames. */
359
a2889657
JB
360Lisp_Object Voverlay_arrow_string;
361
5f5c8ee5
GM
362/* Values of those variables at last redisplay. However, if
363 Voverlay_arrow_position is a marker, last_arrow_position is its
364 numerical position. */
365
d45de95b
RS
366static Lisp_Object last_arrow_position, last_arrow_string;
367
5f5c8ee5
GM
368/* Like mode-line-format, but for the title bar on a visible frame. */
369
d39b6696
KH
370Lisp_Object Vframe_title_format;
371
5f5c8ee5
GM
372/* Like mode-line-format, but for the title bar on an iconified frame. */
373
d39b6696
KH
374Lisp_Object Vicon_title_format;
375
08b610e4
RS
376/* List of functions to call when a window's size changes. These
377 functions get one arg, a frame on which one or more windows' sizes
378 have changed. */
5f5c8ee5 379
08b610e4
RS
380static Lisp_Object Vwindow_size_change_functions;
381
0bca8940 382Lisp_Object Qmenu_bar_update_hook, Vmenu_bar_update_hook;
cf074754 383
a2889657 384/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 385
5f5c8ee5 386static int overlay_arrow_seen;
ca26e1c8 387
fba9ce76 388/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 389
5f5c8ee5
GM
390int highlight_nonselected_windows;
391
392/* If cursor motion alone moves point off frame, try scrolling this
393 many lines up or down if that will bring it back. */
394
31ade731 395static EMACS_INT scroll_step;
a2889657 396
4b41cebb 397/* Nonzero means scroll just far enough to bring point back on the
5f5c8ee5
GM
398 screen, when appropriate. */
399
31ade731 400static EMACS_INT scroll_conservatively;
0789adb2 401
5f5c8ee5
GM
402/* Recenter the window whenever point gets within this many lines of
403 the top or bottom of the window. This value is translated into a
404 pixel value by multiplying it with CANON_Y_UNIT, which means that
405 there is really a fixed pixel height scroll margin. */
406
31ade731 407EMACS_INT scroll_margin;
9afd2168 408
5f5c8ee5
GM
409/* Number of windows showing the buffer of the selected window (or
410 another buffer with the same base buffer). keyboard.c refers to
411 this. */
a2889657 412
a2889657
JB
413int buffer_shared;
414
5f5c8ee5 415/* Vector containing glyphs for an ellipsis `...'. */
a2889657 416
5f5c8ee5 417static Lisp_Object default_invis_vector[3];
a2889657 418
1862a24e
MB
419/* Zero means display the mode-line/header-line/menu-bar in the default face
420 (this slightly odd definition is for compatibility with previous versions
421 of emacs), non-zero means display them using their respective faces.
422
423 This variable is deprecated. */
a2889657 424
a2889657
JB
425int mode_line_inverse_video;
426
5f5c8ee5
GM
427/* Prompt to display in front of the mini-buffer contents. */
428
8c5b6a0a 429Lisp_Object minibuf_prompt;
a2889657 430
5f5c8ee5
GM
431/* Width of current mini-buffer prompt. Only set after display_line
432 of the line that contains the prompt. */
433
a2889657 434int minibuf_prompt_width;
5f5c8ee5 435
5f5c8ee5
GM
436/* This is the window where the echo area message was displayed. It
437 is always a mini-buffer window, but it may not be the same window
438 currently active as a mini-buffer. */
439
73af359d
RS
440Lisp_Object echo_area_window;
441
c6e89d6c
GM
442/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
443 pushes the current message and the value of
444 message_enable_multibyte on the stack, the function restore_message
445 pops the stack and displays MESSAGE again. */
446
447Lisp_Object Vmessage_stack;
448
a3788d53
RS
449/* Nonzero means multibyte characters were enabled when the echo area
450 message was specified. */
5f5c8ee5 451
a3788d53
RS
452int message_enable_multibyte;
453
4b41cebb 454/* Nonzero if we should redraw the mode lines on the next redisplay. */
5f5c8ee5 455
a2889657
JB
456int update_mode_lines;
457
5f5c8ee5 458/* Nonzero if window sizes or contents have changed since last
4b41cebb 459 redisplay that finished. */
5f5c8ee5 460
a2889657
JB
461int windows_or_buffers_changed;
462
5fb96e96
RS
463/* Nonzero means a frame's cursor type has been changed. */
464
465int cursor_type_changed;
466
5f5c8ee5
GM
467/* Nonzero after display_mode_line if %l was used and it displayed a
468 line number. */
469
aa6d10fa
RS
470int line_number_displayed;
471
472/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 473
090703f4 474Lisp_Object Vline_number_display_limit;
5992c4f7 475
4b41cebb 476/* Line width to consider when repositioning for line number display. */
5d121aec 477
31ade731 478static EMACS_INT line_number_display_limit_width;
5d121aec 479
5f5c8ee5
GM
480/* Number of lines to keep in the message log buffer. t means
481 infinite. nil means don't log at all. */
482
5992c4f7 483Lisp_Object Vmessage_log_max;
d45de95b 484
6a94510a
GM
485/* The name of the *Messages* buffer, a string. */
486
487static Lisp_Object Vmessages_buffer_name;
488
c6e89d6c
GM
489/* Current, index 0, and last displayed echo area message. Either
490 buffers from echo_buffers, or nil to indicate no message. */
491
492Lisp_Object echo_area_buffer[2];
493
494/* The buffers referenced from echo_area_buffer. */
495
496static Lisp_Object echo_buffer[2];
497
498/* A vector saved used in with_area_buffer to reduce consing. */
499
500static Lisp_Object Vwith_echo_area_save_vector;
501
502/* Non-zero means display_echo_area should display the last echo area
503 message again. Set by redisplay_preserve_echo_area. */
504
505static int display_last_displayed_message_p;
506
507/* Nonzero if echo area is being used by print; zero if being used by
508 message. */
509
510int message_buf_print;
511
e1477f43
GM
512/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
513
514Lisp_Object Qinhibit_menubar_update;
515int inhibit_menubar_update;
516
9142dd5b
GM
517/* Maximum height for resizing mini-windows. Either a float
518 specifying a fraction of the available height, or an integer
519 specifying a number of lines. */
c6e89d6c 520
ad4f174e
GM
521Lisp_Object Vmax_mini_window_height;
522
523/* Non-zero means messages should be displayed with truncated
524 lines instead of being continued. */
525
526int message_truncate_lines;
527Lisp_Object Qmessage_truncate_lines;
c6e89d6c 528
6e019995
GM
529/* Set to 1 in clear_message to make redisplay_internal aware
530 of an emptied echo area. */
531
532static int message_cleared_p;
533
d6d26ed3
GM
534/* Non-zero means we want a hollow cursor in windows that are not
535 selected. Zero means there's no cursor in such windows. */
536
cfe03a41 537Lisp_Object Vcursor_in_non_selected_windows;
af79bccb 538Lisp_Object Qcursor_in_non_selected_windows;
d6d26ed3 539
cfe03a41
KS
540/* How to blink the default frame cursor off. */
541Lisp_Object Vblink_cursor_alist;
542
5f5c8ee5
GM
543/* A scratch glyph row with contents used for generating truncation
544 glyphs. Also used in direct_output_for_insert. */
12adba34 545
5f5c8ee5
GM
546#define MAX_SCRATCH_GLYPHS 100
547struct glyph_row scratch_glyph_row;
548static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 549
5f5c8ee5
GM
550/* Ascent and height of the last line processed by move_it_to. */
551
552static int last_max_ascent, last_height;
553
21fdfb65
GM
554/* Non-zero if there's a help-echo in the echo area. */
555
556int help_echo_showing_p;
557
04612a64
GM
558/* If >= 0, computed, exact values of mode-line and header-line height
559 to use in the macros CURRENT_MODE_LINE_HEIGHT and
560 CURRENT_HEADER_LINE_HEIGHT. */
561
562int current_mode_line_height, current_header_line_height;
563
5f5c8ee5 564/* The maximum distance to look ahead for text properties. Values
2311178e 565 that are too small let us call compute_char_face and similar
5f5c8ee5
GM
566 functions too often which is expensive. Values that are too large
567 let us call compute_char_face and alike too often because we
568 might not be interested in text properties that far away. */
569
570#define TEXT_PROP_DISTANCE_LIMIT 100
571
47589c8c
GM
572#if GLYPH_DEBUG
573
76cb5e06
GM
574/* Variables to turn off display optimizations from Lisp. */
575
576int inhibit_try_window_id, inhibit_try_window_reusing;
577int inhibit_try_cursor_movement;
578
5f5c8ee5
GM
579/* Non-zero means print traces of redisplay if compiled with
580 GLYPH_DEBUG != 0. */
581
5f5c8ee5 582int trace_redisplay_p;
47589c8c 583
546a4f00 584#endif /* GLYPH_DEBUG */
47589c8c 585
546a4f00
AI
586#ifdef DEBUG_TRACE_MOVE
587/* Non-zero means trace with TRACE_MOVE to stderr. */
47589c8c
GM
588int trace_move;
589
47589c8c
GM
590#define TRACE_MOVE(x) if (trace_move) fprintf x; else (void) 0
591#else
91c3f500 592#define TRACE_MOVE(x) (void) 0
5f5c8ee5 593#endif
2311178e 594
d475bcb8
GM
595/* Non-zero means automatically scroll windows horizontally to make
596 point visible. */
597
598int automatic_hscrolling_p;
599
1df7e8f0
EZ
600/* How close to the margin can point get before the window is scrolled
601 horizontally. */
5d335845 602EMACS_INT hscroll_margin;
1df7e8f0
EZ
603
604/* How much to scroll horizontally when point is inside the above margin. */
e76d28d5 605Lisp_Object Vhscroll_step;
1df7e8f0 606
e00daaa0
GM
607/* A list of symbols, one for each supported image type. */
608
609Lisp_Object Vimage_types;
610
6422c1d7 611/* The variable `resize-mini-windows'. If nil, don't resize
67526daf 612 mini-windows. If t, always resize them to fit the text they
6422c1d7
GM
613 display. If `grow-only', let mini-windows grow only until they
614 become empty. */
615
616Lisp_Object Vresize_mini_windows;
617
82a7ab23
RS
618/* Buffer being redisplayed -- for redisplay_window_error. */
619
620struct buffer *displayed_buffer;
621
5f5c8ee5
GM
622/* Value returned from text property handlers (see below). */
623
624enum prop_handled
3c6595e0 625{
5f5c8ee5
GM
626 HANDLED_NORMALLY,
627 HANDLED_RECOMPUTE_PROPS,
628 HANDLED_OVERLAY_STRING_CONSUMED,
629 HANDLED_RETURN
630};
3c6595e0 631
5f5c8ee5
GM
632/* A description of text properties that redisplay is interested
633 in. */
3c6595e0 634
5f5c8ee5
GM
635struct props
636{
637 /* The name of the property. */
638 Lisp_Object *name;
90adcf20 639
5f5c8ee5
GM
640 /* A unique index for the property. */
641 enum prop_idx idx;
642
643 /* A handler function called to set up iterator IT from the property
644 at IT's current position. Value is used to steer handle_stop. */
645 enum prop_handled (*handler) P_ ((struct it *it));
646};
647
648static enum prop_handled handle_face_prop P_ ((struct it *));
649static enum prop_handled handle_invisible_prop P_ ((struct it *));
650static enum prop_handled handle_display_prop P_ ((struct it *));
260a86a0 651static enum prop_handled handle_composition_prop P_ ((struct it *));
5f5c8ee5
GM
652static enum prop_handled handle_overlay_change P_ ((struct it *));
653static enum prop_handled handle_fontified_prop P_ ((struct it *));
654
655/* Properties handled by iterators. */
656
657static struct props it_props[] =
5992c4f7 658{
5f5c8ee5
GM
659 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
660 /* Handle `face' before `display' because some sub-properties of
661 `display' need to know the face. */
662 {&Qface, FACE_PROP_IDX, handle_face_prop},
663 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
664 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
260a86a0 665 {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
5f5c8ee5
GM
666 {NULL, 0, NULL}
667};
5992c4f7 668
5f5c8ee5
GM
669/* Value is the position described by X. If X is a marker, value is
670 the marker_position of X. Otherwise, value is X. */
12adba34 671
5f5c8ee5 672#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 673
5f5c8ee5 674/* Enumeration returned by some move_it_.* functions internally. */
12adba34 675
5f5c8ee5
GM
676enum move_it_result
677{
678 /* Not used. Undefined value. */
679 MOVE_UNDEFINED,
bab29e15 680
5f5c8ee5
GM
681 /* Move ended at the requested buffer position or ZV. */
682 MOVE_POS_MATCH_OR_ZV,
bab29e15 683
5f5c8ee5
GM
684 /* Move ended at the requested X pixel position. */
685 MOVE_X_REACHED,
12adba34 686
5f5c8ee5
GM
687 /* Move within a line ended at the end of a line that must be
688 continued. */
689 MOVE_LINE_CONTINUED,
2311178e 690
5f5c8ee5
GM
691 /* Move within a line ended at the end of a line that would
692 be displayed truncated. */
693 MOVE_LINE_TRUNCATED,
ff6c30e5 694
5f5c8ee5
GM
695 /* Move within a line ended at a line end. */
696 MOVE_NEWLINE_OR_CR
697};
12adba34 698
1987b083
RS
699/* This counter is used to clear the face cache every once in a while
700 in redisplay_internal. It is incremented for each redisplay.
701 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
702 cleared. */
703
704#define CLEAR_FACE_CACHE_COUNT 500
705static int clear_face_cache_count;
706
707/* Record the previous terminal frame we displayed. */
708
709static struct frame *previous_terminal_frame;
710
711/* Non-zero while redisplay_internal is in progress. */
712
713int redisplaying_p;
714
26683087
RS
715/* Non-zero means don't free realized faces. Bound while freeing
716 realized faces is dangerous because glyph matrices might still
717 reference them. */
1987b083 718
26683087
RS
719int inhibit_free_realized_faces;
720Lisp_Object Qinhibit_free_realized_faces;
ff6c30e5 721
5f5c8ee5
GM
722\f
723/* Function prototypes. */
724
5a08cbaf 725static void setup_for_ellipsis P_ ((struct it *));
43c09969 726static void mark_window_display_accurate_1 P_ ((struct window *, int));
74bd6d65
GM
727static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
728static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
cafafe0b 729static int cursor_row_p P_ ((struct window *, struct glyph_row *));
715e84c9 730static int redisplay_mode_lines P_ ((Lisp_Object, int));
2e621225 731static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
c0a53abb
PJ
732
733#if 0
2e621225 734static int invisible_text_between_p P_ ((struct it *, int, int));
c0a53abb
PJ
735#endif
736
2e621225
GM
737static int next_element_from_ellipsis P_ ((struct it *));
738static void pint2str P_ ((char *, int, int));
739static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
740 struct text_pos));
741static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
742static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
743static void store_frame_title_char P_ ((char));
50f80c2f 744static int store_frame_title P_ ((const unsigned char *, int, int));
2e621225
GM
745static void x_consider_frame_title P_ ((Lisp_Object));
746static void handle_stop P_ ((struct it *));
747static int tool_bar_lines_needed P_ ((struct frame *));
06568bbf 748static int single_display_prop_intangible_p P_ ((Lisp_Object));
5bcfeb49 749static void ensure_echo_area_buffers P_ ((void));
c6e89d6c
GM
750static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
751static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
23a96c77 752static int with_echo_area_buffer P_ ((struct window *, int,
23dd2d97
KR
753 int (*) (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT),
754 EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 755static void clear_garbaged_frames P_ ((void));
23dd2d97
KR
756static int current_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
757static int truncate_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
758static int set_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 759static int display_echo_area P_ ((struct window *));
23dd2d97
KR
760static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
761static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
28514cd9 762static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
50f80c2f 763static int string_char_and_length P_ ((const unsigned char *, int, int *));
5f5c8ee5
GM
764static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
765 struct text_pos));
766static int compute_window_start_on_continuation_line P_ ((struct window *));
116d6f5c 767static Lisp_Object safe_eval_handler P_ ((Lisp_Object));
5f5c8ee5
GM
768static void insert_left_trunc_glyphs P_ ((struct it *));
769static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
770static void extend_face_to_end_of_line P_ ((struct it *));
80c6cb1f 771static int append_space P_ ((struct it *, int));
cb617e7c 772static int make_cursor_line_fully_visible P_ ((struct window *));
31ade731 773static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int));
47589c8c 774static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
5f5c8ee5
GM
775static int trailing_whitespace_p P_ ((int));
776static int message_log_check_duplicate P_ ((int, int, int, int));
5f5c8ee5
GM
777static void push_it P_ ((struct it *));
778static void pop_it P_ ((struct it *));
779static void sync_frame_with_window_matrix_rows P_ ((struct window *));
780static void redisplay_internal P_ ((int));
c6e89d6c 781static int echo_area_display P_ ((int));
5f5c8ee5
GM
782static void redisplay_windows P_ ((Lisp_Object));
783static void redisplay_window P_ ((Lisp_Object, int));
82a7ab23
RS
784static Lisp_Object redisplay_window_error ();
785static Lisp_Object redisplay_window_0 P_ ((Lisp_Object));
786static Lisp_Object redisplay_window_1 P_ ((Lisp_Object));
5f5c8ee5
GM
787static void update_menu_bar P_ ((struct frame *, int));
788static int try_window_reusing_current_matrix P_ ((struct window *));
789static int try_window_id P_ ((struct window *));
790static int display_line P_ ((struct it *));
715e84c9 791static int display_mode_lines P_ ((struct window *));
04612a64 792static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
c53a1624 793static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int));
fec8f23e 794static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object));
72f62cb5 795static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
5f5c8ee5
GM
796static void display_menu_bar P_ ((struct window *));
797static int display_count_lines P_ ((int, int, int, int, int *));
798static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
799 int, int, struct it *, int, int, int, int));
800static void compute_line_metrics P_ ((struct it *));
801static void run_redisplay_end_trigger_hook P_ ((struct it *));
5a08cbaf 802static int get_overlay_strings P_ ((struct it *, int));
5f5c8ee5 803static void next_overlay_string P_ ((struct it *));
5f5c8ee5
GM
804static void reseat P_ ((struct it *, struct text_pos, int));
805static void reseat_1 P_ ((struct it *, struct text_pos, int));
806static void back_to_previous_visible_line_start P_ ((struct it *));
807static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 808static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
809static int next_element_from_display_vector P_ ((struct it *));
810static int next_element_from_string P_ ((struct it *));
811static int next_element_from_c_string P_ ((struct it *));
812static int next_element_from_buffer P_ ((struct it *));
260a86a0 813static int next_element_from_composition P_ ((struct it *));
5f5c8ee5
GM
814static int next_element_from_image P_ ((struct it *));
815static int next_element_from_stretch P_ ((struct it *));
5a08cbaf 816static void load_overlay_strings P_ ((struct it *, int));
47d57b22
GM
817static int init_from_display_pos P_ ((struct it *, struct window *,
818 struct display_pos *));
5f5c8ee5
GM
819static void reseat_to_string P_ ((struct it *, unsigned char *,
820 Lisp_Object, int, int, int, int));
5f5c8ee5
GM
821static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
822 int, int, int));
823void move_it_vertically_backward P_ ((struct it *, int));
824static void init_to_row_start P_ ((struct it *, struct window *,
825 struct glyph_row *));
47d57b22
GM
826static int init_to_row_end P_ ((struct it *, struct window *,
827 struct glyph_row *));
5f5c8ee5 828static void back_to_previous_line_start P_ ((struct it *));
cafafe0b 829static int forward_to_next_line_start P_ ((struct it *, int *));
5f5c8ee5
GM
830static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
831 Lisp_Object, int));
832static struct text_pos string_pos P_ ((int, Lisp_Object));
833static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
834static int number_of_chars P_ ((unsigned char *, int));
835static void compute_stop_pos P_ ((struct it *));
836static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
837 Lisp_Object));
838static int face_before_or_after_it_pos P_ ((struct it *, int));
839static int next_overlay_change P_ ((int));
840static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
a61b7058
GM
841 Lisp_Object, struct text_pos *,
842 int));
06a12811 843static int underlying_face_id P_ ((struct it *));
4bde0ebb
GM
844static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
845 struct window *));
5f5c8ee5
GM
846
847#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
848#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 849
5f5c8ee5 850#ifdef HAVE_WINDOW_SYSTEM
12adba34 851
e037b9ec
GM
852static void update_tool_bar P_ ((struct frame *, int));
853static void build_desired_tool_bar_string P_ ((struct frame *f));
854static int redisplay_tool_bar P_ ((struct frame *));
855static void display_tool_bar_line P_ ((struct it *));
12adba34 856
5f5c8ee5 857#endif /* HAVE_WINDOW_SYSTEM */
12adba34 858
5f5c8ee5
GM
859\f
860/***********************************************************************
861 Window display dimensions
862 ***********************************************************************/
12adba34 863
5f5c8ee5
GM
864/* Return the window-relative maximum y + 1 for glyph rows displaying
865 text in window W. This is the height of W minus the height of a
866 mode line, if any. */
867
868INLINE int
869window_text_bottom_y (w)
870 struct window *w;
871{
872 struct frame *f = XFRAME (w->frame);
873 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
1a578e9b 874
5f5c8ee5
GM
875 if (WINDOW_WANTS_MODELINE_P (w))
876 height -= CURRENT_MODE_LINE_HEIGHT (w);
877 return height;
f88eb0b6
KH
878}
879
f82aff7c 880
5f5c8ee5 881/* Return the pixel width of display area AREA of window W. AREA < 0
b46952ae 882 means return the total width of W, not including fringes to
5f5c8ee5 883 the left and right of the window. */
ff6c30e5 884
5f5c8ee5
GM
885INLINE int
886window_box_width (w, area)
887 struct window *w;
888 int area;
889{
890 struct frame *f = XFRAME (w->frame);
891 int width = XFASTINT (w->width);
2311178e 892
5f5c8ee5 893 if (!w->pseudo_window_p)
ff6c30e5 894 {
b46952ae 895 width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FRINGE_COLS (f);
2311178e 896
5f5c8ee5
GM
897 if (area == TEXT_AREA)
898 {
899 if (INTEGERP (w->left_margin_width))
900 width -= XFASTINT (w->left_margin_width);
901 if (INTEGERP (w->right_margin_width))
902 width -= XFASTINT (w->right_margin_width);
903 }
904 else if (area == LEFT_MARGIN_AREA)
905 width = (INTEGERP (w->left_margin_width)
906 ? XFASTINT (w->left_margin_width) : 0);
907 else if (area == RIGHT_MARGIN_AREA)
908 width = (INTEGERP (w->right_margin_width)
909 ? XFASTINT (w->right_margin_width) : 0);
ff6c30e5 910 }
5f5c8ee5
GM
911
912 return width * CANON_X_UNIT (f);
ff6c30e5 913}
1adc55de 914
1adc55de 915
5f5c8ee5 916/* Return the pixel height of the display area of window W, not
4b41cebb 917 including mode lines of W, if any. */
f88eb0b6 918
5f5c8ee5
GM
919INLINE int
920window_box_height (w)
921 struct window *w;
f88eb0b6 922{
5f5c8ee5
GM
923 struct frame *f = XFRAME (w->frame);
924 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
7ecd4937
GM
925
926 xassert (height >= 0);
2311178e 927
d9c9e99c
MB
928 /* Note: the code below that determines the mode-line/header-line
929 height is essentially the same as that contained in the macro
930 CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
931 the appropriate glyph row has its `mode_line_p' flag set,
932 and if it doesn't, uses estimate_mode_line_height instead. */
933
5f5c8ee5 934 if (WINDOW_WANTS_MODELINE_P (w))
97dff879
MB
935 {
936 struct glyph_row *ml_row
937 = (w->current_matrix && w->current_matrix->rows
938 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
939 : 0);
940 if (ml_row && ml_row->mode_line_p)
941 height -= ml_row->height;
942 else
96d2320f 943 height -= estimate_mode_line_height (f, CURRENT_MODE_LINE_FACE_ID (w));
97dff879 944 }
5f5c8ee5 945
045dee35 946 if (WINDOW_WANTS_HEADER_LINE_P (w))
97dff879
MB
947 {
948 struct glyph_row *hl_row
949 = (w->current_matrix && w->current_matrix->rows
950 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
951 : 0);
952 if (hl_row && hl_row->mode_line_p)
953 height -= hl_row->height;
954 else
955 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
956 }
5f5c8ee5 957
7c75be36
PJ
958 /* With a very small font and a mode-line that's taller than
959 default, we might end up with a negative height. */
960 return max (0, height);
5992c4f7
KH
961}
962
963
5f5c8ee5
GM
964/* Return the frame-relative coordinate of the left edge of display
965 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 966 whole window, to the right of the left fringe of W. */
5992c4f7 967
5f5c8ee5
GM
968INLINE int
969window_box_left (w, area)
970 struct window *w;
971 int area;
90adcf20 972{
5f5c8ee5
GM
973 struct frame *f = XFRAME (w->frame);
974 int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
a3788d53 975
5f5c8ee5 976 if (!w->pseudo_window_p)
90adcf20 977 {
5f5c8ee5 978 x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
b46952ae 979 + FRAME_LEFT_FRINGE_WIDTH (f));
2311178e 980
5f5c8ee5
GM
981 if (area == TEXT_AREA)
982 x += window_box_width (w, LEFT_MARGIN_AREA);
983 else if (area == RIGHT_MARGIN_AREA)
984 x += (window_box_width (w, LEFT_MARGIN_AREA)
985 + window_box_width (w, TEXT_AREA));
90adcf20 986 }
73af359d 987
5f5c8ee5 988 return x;
2311178e 989}
90adcf20 990
b6436d4e 991
5f5c8ee5
GM
992/* Return the frame-relative coordinate of the right edge of display
993 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 994 whole window, to the left of the right fringe of W. */
ded34426 995
5f5c8ee5
GM
996INLINE int
997window_box_right (w, area)
998 struct window *w;
999 int area;
1000{
1001 return window_box_left (w, area) + window_box_width (w, area);
2311178e
TTN
1002}
1003
5f5c8ee5
GM
1004
1005/* Get the bounding box of the display area AREA of window W, without
1006 mode lines, in frame-relative coordinates. AREA < 0 means the
b46952ae 1007 whole window, not including the left and right fringes of
5f5c8ee5
GM
1008 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
1009 coordinates of the upper-left corner of the box. Return in
1010 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
1011
1012INLINE void
1013window_box (w, area, box_x, box_y, box_width, box_height)
1014 struct window *w;
1015 int area;
1016 int *box_x, *box_y, *box_width, *box_height;
1017{
1018 struct frame *f = XFRAME (w->frame);
2311178e 1019
5f5c8ee5
GM
1020 *box_width = window_box_width (w, area);
1021 *box_height = window_box_height (w);
1022 *box_x = window_box_left (w, area);
1023 *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
1024 + XFASTINT (w->top) * CANON_Y_UNIT (f));
045dee35
GM
1025 if (WINDOW_WANTS_HEADER_LINE_P (w))
1026 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
ded34426 1027}
1adc55de 1028
1adc55de 1029
5f5c8ee5 1030/* Get the bounding box of the display area AREA of window W, without
b46952ae
KS
1031 mode lines. AREA < 0 means the whole window, not including the
1032 left and right fringe of the window. Return in *TOP_LEFT_X
5f5c8ee5
GM
1033 and TOP_LEFT_Y the frame-relative pixel coordinates of the
1034 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
1035 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
1036 box. */
ded34426 1037
5f5c8ee5
GM
1038INLINE void
1039window_box_edges (w, area, top_left_x, top_left_y,
1040 bottom_right_x, bottom_right_y)
1041 struct window *w;
1042 int area;
1043 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 1044{
5f5c8ee5
GM
1045 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
1046 bottom_right_y);
1047 *bottom_right_x += *top_left_x;
1048 *bottom_right_y += *top_left_y;
48ae5f0a
KH
1049}
1050
5f5c8ee5
GM
1051
1052\f
1053/***********************************************************************
1054 Utilities
1055 ***********************************************************************/
1056
8b6ea97f
GM
1057/* Return the bottom y-position of the line the iterator IT is in.
1058 This can modify IT's settings. */
1059
1060int
1061line_bottom_y (it)
1062 struct it *it;
1063{
1064 int line_height = it->max_ascent + it->max_descent;
1065 int line_top_y = it->current_y;
2311178e 1066
8b6ea97f
GM
1067 if (line_height == 0)
1068 {
1069 if (last_height)
1070 line_height = last_height;
1071 else if (IT_CHARPOS (*it) < ZV)
1072 {
1073 move_it_by_lines (it, 1, 1);
1074 line_height = (it->max_ascent || it->max_descent
1075 ? it->max_ascent + it->max_descent
1076 : last_height);
1077 }
1078 else
1079 {
1080 struct glyph_row *row = it->glyph_row;
2311178e 1081
8b6ea97f
GM
1082 /* Use the default character height. */
1083 it->glyph_row = NULL;
1084 it->what = IT_CHARACTER;
1085 it->c = ' ';
1086 it->len = 1;
1087 PRODUCE_GLYPHS (it);
1088 line_height = it->ascent + it->descent;
1089 it->glyph_row = row;
1090 }
1091 }
1092
1093 return line_top_y + line_height;
1094}
1095
1096
0db95684
GM
1097/* Return 1 if position CHARPOS is visible in window W. Set *FULLY to
1098 1 if POS is visible and the line containing POS is fully visible.
1099 EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
1100 and header-lines heights. */
3a641a69
GM
1101
1102int
04612a64 1103pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
3a641a69 1104 struct window *w;
04612a64 1105 int charpos, *fully, exact_mode_line_heights_p;
3a641a69
GM
1106{
1107 struct it it;
1108 struct text_pos top;
fcab1954
GM
1109 int visible_p;
1110 struct buffer *old_buffer = NULL;
1111
1112 if (XBUFFER (w->buffer) != current_buffer)
1113 {
1114 old_buffer = current_buffer;
1115 set_buffer_internal_1 (XBUFFER (w->buffer));
1116 }
3a641a69
GM
1117
1118 *fully = visible_p = 0;
1119 SET_TEXT_POS_FROM_MARKER (top, w->start);
2311178e 1120
04612a64
GM
1121 /* Compute exact mode line heights, if requested. */
1122 if (exact_mode_line_heights_p)
1123 {
1124 if (WINDOW_WANTS_MODELINE_P (w))
1125 current_mode_line_height
96d2320f 1126 = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
04612a64 1127 current_buffer->mode_line_format);
2311178e 1128
04612a64
GM
1129 if (WINDOW_WANTS_HEADER_LINE_P (w))
1130 current_header_line_height
1131 = display_mode_line (w, HEADER_LINE_FACE_ID,
1132 current_buffer->header_line_format);
1133 }
3a641a69 1134
04612a64 1135 start_display (&it, w, top);
3a641a69
GM
1136 move_it_to (&it, charpos, 0, it.last_visible_y, -1,
1137 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
a13be207
GM
1138
1139 /* Note that we may overshoot because of invisible text. */
1140 if (IT_CHARPOS (it) >= charpos)
3a641a69 1141 {
8b6ea97f
GM
1142 int top_y = it.current_y;
1143 int bottom_y = line_bottom_y (&it);
fcab1954 1144 int window_top_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
2311178e 1145
8b6ea97f
GM
1146 if (top_y < window_top_y)
1147 visible_p = bottom_y > window_top_y;
1148 else if (top_y < it.last_visible_y)
fcab1954
GM
1149 {
1150 visible_p = 1;
8b6ea97f 1151 *fully = bottom_y <= it.last_visible_y;
fcab1954 1152 }
3a641a69
GM
1153 }
1154 else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
1155 {
1156 move_it_by_lines (&it, 1, 0);
1157 if (charpos < IT_CHARPOS (it))
1158 {
1159 visible_p = 1;
1160 *fully = 0;
1161 }
1162 }
fcab1954
GM
1163
1164 if (old_buffer)
1165 set_buffer_internal_1 (old_buffer);
04612a64
GM
1166
1167 current_header_line_height = current_mode_line_height = -1;
3a641a69
GM
1168 return visible_p;
1169}
1170
1171
4fdb80f2
GM
1172/* Return the next character from STR which is MAXLEN bytes long.
1173 Return in *LEN the length of the character. This is like
1174 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
9ab8560d 1175 we find one, we return a `?', but with the length of the invalid
4fdb80f2
GM
1176 character. */
1177
1178static INLINE int
7a5b8a93 1179string_char_and_length (str, maxlen, len)
50f80c2f 1180 const unsigned char *str;
7a5b8a93 1181 int maxlen, *len;
4fdb80f2
GM
1182{
1183 int c;
1184
1185 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
1186 if (!CHAR_VALID_P (c, 1))
1187 /* We may not change the length here because other places in Emacs
9ab8560d 1188 don't use this function, i.e. they silently accept invalid
4fdb80f2
GM
1189 characters. */
1190 c = '?';
1191
1192 return c;
1193}
1194
1195
1196
5f5c8ee5
GM
1197/* Given a position POS containing a valid character and byte position
1198 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
1199
1200static struct text_pos
1201string_pos_nchars_ahead (pos, string, nchars)
1202 struct text_pos pos;
1203 Lisp_Object string;
1204 int nchars;
0b1005ef 1205{
5f5c8ee5
GM
1206 xassert (STRINGP (string) && nchars >= 0);
1207
1208 if (STRING_MULTIBYTE (string))
1209 {
2051c264 1210 int rest = SBYTES (string) - BYTEPOS (pos);
50f80c2f 1211 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
5f5c8ee5
GM
1212 int len;
1213
1214 while (nchars--)
1215 {
4fdb80f2 1216 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1217 p += len, rest -= len;
1218 xassert (rest >= 0);
1219 CHARPOS (pos) += 1;
1220 BYTEPOS (pos) += len;
1221 }
1222 }
1223 else
1224 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
1225
1226 return pos;
0a9dc68b
RS
1227}
1228
0a9dc68b 1229
5f5c8ee5
GM
1230/* Value is the text position, i.e. character and byte position,
1231 for character position CHARPOS in STRING. */
1232
1233static INLINE struct text_pos
1234string_pos (charpos, string)
1235 int charpos;
0a9dc68b 1236 Lisp_Object string;
0a9dc68b 1237{
5f5c8ee5
GM
1238 struct text_pos pos;
1239 xassert (STRINGP (string));
1240 xassert (charpos >= 0);
1241 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
1242 return pos;
1243}
1244
1245
1246/* Value is a text position, i.e. character and byte position, for
1247 character position CHARPOS in C string S. MULTIBYTE_P non-zero
1248 means recognize multibyte characters. */
1249
1250static struct text_pos
1251c_string_pos (charpos, s, multibyte_p)
1252 int charpos;
1253 unsigned char *s;
1254 int multibyte_p;
1255{
1256 struct text_pos pos;
1257
1258 xassert (s != NULL);
1259 xassert (charpos >= 0);
1260
1261 if (multibyte_p)
0a9dc68b 1262 {
5f5c8ee5
GM
1263 int rest = strlen (s), len;
1264
1265 SET_TEXT_POS (pos, 0, 0);
1266 while (charpos--)
0a9dc68b 1267 {
4fdb80f2 1268 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
1269 s += len, rest -= len;
1270 xassert (rest >= 0);
1271 CHARPOS (pos) += 1;
1272 BYTEPOS (pos) += len;
0a9dc68b
RS
1273 }
1274 }
5f5c8ee5
GM
1275 else
1276 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 1277
5f5c8ee5
GM
1278 return pos;
1279}
0a9dc68b 1280
0a9dc68b 1281
5f5c8ee5
GM
1282/* Value is the number of characters in C string S. MULTIBYTE_P
1283 non-zero means recognize multibyte characters. */
0a9dc68b 1284
5f5c8ee5
GM
1285static int
1286number_of_chars (s, multibyte_p)
1287 unsigned char *s;
1288 int multibyte_p;
1289{
1290 int nchars;
2311178e 1291
5f5c8ee5
GM
1292 if (multibyte_p)
1293 {
1294 int rest = strlen (s), len;
1295 unsigned char *p = (unsigned char *) s;
0a9dc68b 1296
5f5c8ee5
GM
1297 for (nchars = 0; rest > 0; ++nchars)
1298 {
4fdb80f2 1299 string_char_and_length (p, rest, &len);
5f5c8ee5 1300 rest -= len, p += len;
0a9dc68b
RS
1301 }
1302 }
5f5c8ee5
GM
1303 else
1304 nchars = strlen (s);
1305
1306 return nchars;
0b1005ef
KH
1307}
1308
2311178e 1309
5f5c8ee5
GM
1310/* Compute byte position NEWPOS->bytepos corresponding to
1311 NEWPOS->charpos. POS is a known position in string STRING.
1312 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1313
5f5c8ee5
GM
1314static void
1315compute_string_pos (newpos, pos, string)
1316 struct text_pos *newpos, pos;
1317 Lisp_Object string;
76412d64 1318{
5f5c8ee5
GM
1319 xassert (STRINGP (string));
1320 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
2311178e 1321
5f5c8ee5 1322 if (STRING_MULTIBYTE (string))
6fc556fd
KR
1323 *newpos = string_pos_nchars_ahead (pos, string,
1324 CHARPOS (*newpos) - CHARPOS (pos));
5f5c8ee5
GM
1325 else
1326 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1327}
1328
9c74a0dd 1329
5f5c8ee5
GM
1330\f
1331/***********************************************************************
1332 Lisp form evaluation
1333 ***********************************************************************/
1334
116d6f5c 1335/* Error handler for safe_eval and safe_call. */
5f5c8ee5
GM
1336
1337static Lisp_Object
116d6f5c 1338safe_eval_handler (arg)
5f5c8ee5
GM
1339 Lisp_Object arg;
1340{
0dbf9fd2 1341 add_to_log ("Error during redisplay: %s", arg, Qnil);
5f5c8ee5
GM
1342 return Qnil;
1343}
1344
1345
1346/* Evaluate SEXPR and return the result, or nil if something went
2913a9c0 1347 wrong. Prevent redisplay during the evaluation. */
5f5c8ee5 1348
71e5b1b8 1349Lisp_Object
116d6f5c 1350safe_eval (sexpr)
5f5c8ee5
GM
1351 Lisp_Object sexpr;
1352{
5f5c8ee5 1353 Lisp_Object val;
2311178e 1354
30a3f61c
GM
1355 if (inhibit_eval_during_redisplay)
1356 val = Qnil;
1357 else
1358 {
331379bf 1359 int count = SPECPDL_INDEX ();
30a3f61c 1360 struct gcpro gcpro1;
0d8b31c0 1361
30a3f61c
GM
1362 GCPRO1 (sexpr);
1363 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1364 /* Use Qt to ensure debugger does not run,
1365 so there is no possibility of wanting to redisplay. */
1366 val = internal_condition_case_1 (Feval, sexpr, Qt,
30a3f61c
GM
1367 safe_eval_handler);
1368 UNGCPRO;
1369 val = unbind_to (count, val);
1370 }
2311178e 1371
30a3f61c 1372 return val;
0d8b31c0
GM
1373}
1374
1375
1376/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
2913a9c0
GM
1377 Return the result, or nil if something went wrong. Prevent
1378 redisplay during the evaluation. */
0d8b31c0
GM
1379
1380Lisp_Object
116d6f5c 1381safe_call (nargs, args)
0d8b31c0
GM
1382 int nargs;
1383 Lisp_Object *args;
1384{
0d8b31c0 1385 Lisp_Object val;
2311178e 1386
30a3f61c
GM
1387 if (inhibit_eval_during_redisplay)
1388 val = Qnil;
1389 else
1390 {
331379bf 1391 int count = SPECPDL_INDEX ();
30a3f61c 1392 struct gcpro gcpro1;
0d8b31c0 1393
30a3f61c
GM
1394 GCPRO1 (args[0]);
1395 gcpro1.nvars = nargs;
1396 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1397 /* Use Qt to ensure debugger does not run,
1398 so there is no possibility of wanting to redisplay. */
1399 val = internal_condition_case_2 (Ffuncall, nargs, args, Qt,
30a3f61c
GM
1400 safe_eval_handler);
1401 UNGCPRO;
1402 val = unbind_to (count, val);
1403 }
1404
1405 return val;
5f5c8ee5
GM
1406}
1407
1408
116d6f5c
GM
1409/* Call function FN with one argument ARG.
1410 Return the result, or nil if something went wrong. */
1411
1412Lisp_Object
1413safe_call1 (fn, arg)
1414 Lisp_Object fn, arg;
1415{
1416 Lisp_Object args[2];
1417 args[0] = fn;
1418 args[1] = arg;
1419 return safe_call (2, args);
1420}
1421
1422
5f5c8ee5
GM
1423\f
1424/***********************************************************************
1425 Debugging
1426 ***********************************************************************/
1427
1428#if 0
1429
1430/* Define CHECK_IT to perform sanity checks on iterators.
1431 This is for debugging. It is too slow to do unconditionally. */
1432
1433static void
1434check_it (it)
1435 struct it *it;
1436{
1437 if (it->method == next_element_from_string)
a2889657 1438 {
5f5c8ee5
GM
1439 xassert (STRINGP (it->string));
1440 xassert (IT_STRING_CHARPOS (*it) >= 0);
1441 }
1442 else if (it->method == next_element_from_buffer)
1443 {
1444 /* Check that character and byte positions agree. */
1445 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1446 }
73af359d 1447
5f5c8ee5
GM
1448 if (it->dpvec)
1449 xassert (it->current.dpvec_index >= 0);
1450 else
1451 xassert (it->current.dpvec_index < 0);
1452}
1f40cad2 1453
5f5c8ee5
GM
1454#define CHECK_IT(IT) check_it ((IT))
1455
1456#else /* not 0 */
1457
1458#define CHECK_IT(IT) (void) 0
1459
1460#endif /* not 0 */
1461
1462
1463#if GLYPH_DEBUG
1464
1465/* Check that the window end of window W is what we expect it
1466 to be---the last row in the current matrix displaying text. */
1467
1468static void
1469check_window_end (w)
1470 struct window *w;
1471{
1472 if (!MINI_WINDOW_P (w)
1473 && !NILP (w->window_end_valid))
1474 {
1475 struct glyph_row *row;
1476 xassert ((row = MATRIX_ROW (w->current_matrix,
1477 XFASTINT (w->window_end_vpos)),
1478 !row->enabled_p
1479 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1480 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1481 }
1482}
1483
1484#define CHECK_WINDOW_END(W) check_window_end ((W))
1485
1486#else /* not GLYPH_DEBUG */
1487
1488#define CHECK_WINDOW_END(W) (void) 0
1489
1490#endif /* not GLYPH_DEBUG */
1491
1492
1493\f
1494/***********************************************************************
1495 Iterator initialization
1496 ***********************************************************************/
1497
1498/* Initialize IT for displaying current_buffer in window W, starting
1499 at character position CHARPOS. CHARPOS < 0 means that no buffer
1500 position is specified which is useful when the iterator is assigned
1501 a position later. BYTEPOS is the byte position corresponding to
3ebf0ea9 1502 CHARPOS. BYTEPOS < 0 means compute it from CHARPOS.
5f5c8ee5
GM
1503
1504 If ROW is not null, calls to produce_glyphs with IT as parameter
1505 will produce glyphs in that row.
1506
1507 BASE_FACE_ID is the id of a base face to use. It must be one of
96d2320f
KS
1508 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID,
1509 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID for displaying
1510 mode lines, or TOOL_BAR_FACE_ID for displaying the tool-bar.
2311178e 1511
96d2320f
KS
1512 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID,
1513 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID, the iterator
1514 will be initialized to use the corresponding mode line glyph row of
1515 the desired matrix of W. */
5f5c8ee5
GM
1516
1517void
1518init_iterator (it, w, charpos, bytepos, row, base_face_id)
1519 struct it *it;
1520 struct window *w;
1521 int charpos, bytepos;
1522 struct glyph_row *row;
1523 enum face_id base_face_id;
1524{
1525 int highlight_region_p;
5f5c8ee5
GM
1526
1527 /* Some precondition checks. */
1528 xassert (w != NULL && it != NULL);
3b6b6db7
SM
1529 xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
1530 && charpos <= ZV));
5f5c8ee5
GM
1531
1532 /* If face attributes have been changed since the last redisplay,
1533 free realized faces now because they depend on face definitions
7d0393cf 1534 that might have changed. Don't free faces while there might be
1987b083 1535 desired matrices pending which reference these faces. */
26683087 1536 if (face_change_count && !inhibit_free_realized_faces)
5f5c8ee5
GM
1537 {
1538 face_change_count = 0;
1539 free_all_realized_faces (Qnil);
1540 }
1541
1542 /* Use one of the mode line rows of W's desired matrix if
1543 appropriate. */
1544 if (row == NULL)
1545 {
96d2320f
KS
1546 if (base_face_id == MODE_LINE_FACE_ID
1547 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
5f5c8ee5 1548 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
1549 else if (base_face_id == HEADER_LINE_FACE_ID)
1550 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5 1551 }
2311178e 1552
5f5c8ee5
GM
1553 /* Clear IT. */
1554 bzero (it, sizeof *it);
1555 it->current.overlay_string_index = -1;
1556 it->current.dpvec_index = -1;
5f5c8ee5
GM
1557 it->base_face_id = base_face_id;
1558
1559 /* The window in which we iterate over current_buffer: */
1560 XSETWINDOW (it->window, w);
1561 it->w = w;
1562 it->f = XFRAME (w->frame);
1563
d475bcb8
GM
1564 /* Extra space between lines (on window systems only). */
1565 if (base_face_id == DEFAULT_FACE_ID
1566 && FRAME_WINDOW_P (it->f))
1567 {
1568 if (NATNUMP (current_buffer->extra_line_spacing))
1569 it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
1570 else if (it->f->extra_line_spacing > 0)
1571 it->extra_line_spacing = it->f->extra_line_spacing;
1572 }
1573
5f5c8ee5 1574 /* If realized faces have been removed, e.g. because of face
62be9979
GM
1575 attribute changes of named faces, recompute them. When running
1576 in batch mode, the face cache of Vterminal_frame is null. If
1577 we happen to get called, make a dummy face cache. */
9010e6b1
AI
1578 if (
1579#ifndef WINDOWSNT
1580 noninteractive &&
1581#endif
1582 FRAME_FACE_CACHE (it->f) == NULL)
62be9979 1583 init_frame_faces (it->f);
5f5c8ee5
GM
1584 if (FRAME_FACE_CACHE (it->f)->used == 0)
1585 recompute_basic_faces (it->f);
1586
5f5c8ee5
GM
1587 /* Current value of the `space-width', and 'height' properties. */
1588 it->space_width = Qnil;
1589 it->font_height = Qnil;
2311178e 1590
5f5c8ee5
GM
1591 /* Are control characters displayed as `^C'? */
1592 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
1593
1594 /* -1 means everything between a CR and the following line end
1595 is invisible. >0 means lines indented more than this value are
1596 invisible. */
1597 it->selective = (INTEGERP (current_buffer->selective_display)
1598 ? XFASTINT (current_buffer->selective_display)
2311178e 1599 : (!NILP (current_buffer->selective_display)
5f5c8ee5
GM
1600 ? -1 : 0));
1601 it->selective_display_ellipsis_p
1602 = !NILP (current_buffer->selective_display_ellipses);
1603
1604 /* Display table to use. */
1605 it->dp = window_display_table (w);
1606
1607 /* Are multibyte characters enabled in current_buffer? */
1608 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1609
1610 /* Non-zero if we should highlight the region. */
1611 highlight_region_p
3ebf0ea9 1612 = (!NILP (Vtransient_mark_mode)
5f5c8ee5
GM
1613 && !NILP (current_buffer->mark_active)
1614 && XMARKER (current_buffer->mark)->buffer != 0);
1615
1616 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
1617 start and end of a visible region in window IT->w. Set both to
1618 -1 to indicate no region. */
1619 if (highlight_region_p
1620 /* Maybe highlight only in selected window. */
2311178e 1621 && (/* Either show region everywhere. */
5f5c8ee5
GM
1622 highlight_nonselected_windows
1623 /* Or show region in the selected window. */
1624 || w == XWINDOW (selected_window)
1625 /* Or show the region if we are in the mini-buffer and W is
1626 the window the mini-buffer refers to. */
1627 || (MINI_WINDOW_P (XWINDOW (selected_window))
5705966b
KS
1628 && WINDOWP (minibuf_selected_window)
1629 && w == XWINDOW (minibuf_selected_window))))
5f5c8ee5
GM
1630 {
1631 int charpos = marker_position (current_buffer->mark);
1632 it->region_beg_charpos = min (PT, charpos);
1633 it->region_end_charpos = max (PT, charpos);
1634 }
1635 else
1636 it->region_beg_charpos = it->region_end_charpos = -1;
1637
1638 /* Get the position at which the redisplay_end_trigger hook should
1639 be run, if it is to be run at all. */
1640 if (MARKERP (w->redisplay_end_trigger)
1641 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
1642 it->redisplay_end_trigger_charpos
1643 = marker_position (w->redisplay_end_trigger);
1644 else if (INTEGERP (w->redisplay_end_trigger))
1645 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
1646
1647 /* Correct bogus values of tab_width. */
1648 it->tab_width = XINT (current_buffer->tab_width);
1649 if (it->tab_width <= 0 || it->tab_width > 1000)
1650 it->tab_width = 8;
1651
1652 /* Are lines in the display truncated? */
1653 it->truncate_lines_p
1654 = (base_face_id != DEFAULT_FACE_ID
1655 || XINT (it->w->hscroll)
1656 || (truncate_partial_width_windows
1657 && !WINDOW_FULL_WIDTH_P (it->w))
1658 || !NILP (current_buffer->truncate_lines));
1659
1660 /* Get dimensions of truncation and continuation glyphs. These are
b46952ae 1661 displayed as fringe bitmaps under X, so we don't need them for such
5f5c8ee5
GM
1662 frames. */
1663 if (!FRAME_WINDOW_P (it->f))
1664 {
1665 if (it->truncate_lines_p)
1666 {
1667 /* We will need the truncation glyph. */
1668 xassert (it->glyph_row == NULL);
1669 produce_special_glyphs (it, IT_TRUNCATION);
1670 it->truncation_pixel_width = it->pixel_width;
1671 }
1672 else
1673 {
1674 /* We will need the continuation glyph. */
1675 xassert (it->glyph_row == NULL);
1676 produce_special_glyphs (it, IT_CONTINUATION);
1677 it->continuation_pixel_width = it->pixel_width;
1678 }
1679
153c2160 1680 /* Reset these values to zero because the produce_special_glyphs
5f5c8ee5
GM
1681 above has changed them. */
1682 it->pixel_width = it->ascent = it->descent = 0;
312246d1 1683 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
1684 }
1685
1686 /* Set this after getting the dimensions of truncation and
1687 continuation glyphs, so that we don't produce glyphs when calling
1688 produce_special_glyphs, above. */
1689 it->glyph_row = row;
1690 it->area = TEXT_AREA;
1691
1692 /* Get the dimensions of the display area. The display area
1693 consists of the visible window area plus a horizontally scrolled
1694 part to the left of the window. All x-values are relative to the
1695 start of this total display area. */
1696 if (base_face_id != DEFAULT_FACE_ID)
1697 {
1698 /* Mode lines, menu bar in terminal frames. */
1699 it->first_visible_x = 0;
1700 it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
1701 }
1702 else
1703 {
1704 it->first_visible_x
1705 = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
1706 it->last_visible_x = (it->first_visible_x
1707 + window_box_width (w, TEXT_AREA));
1708
1709 /* If we truncate lines, leave room for the truncator glyph(s) at
1710 the right margin. Otherwise, leave room for the continuation
1711 glyph(s). Truncation and continuation glyphs are not inserted
1712 for window-based redisplay. */
1713 if (!FRAME_WINDOW_P (it->f))
1714 {
1715 if (it->truncate_lines_p)
1716 it->last_visible_x -= it->truncation_pixel_width;
1717 else
1718 it->last_visible_x -= it->continuation_pixel_width;
1719 }
1720
045dee35
GM
1721 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
1722 it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
1723 }
1724
1725 /* Leave room for a border glyph. */
1726 if (!FRAME_WINDOW_P (it->f)
1727 && !WINDOW_RIGHTMOST_P (it->w))
1728 it->last_visible_x -= 1;
1729
1730 it->last_visible_y = window_text_bottom_y (w);
1731
1732 /* For mode lines and alike, arrange for the first glyph having a
1733 left box line if the face specifies a box. */
1734 if (base_face_id != DEFAULT_FACE_ID)
1735 {
1736 struct face *face;
2311178e 1737
5f5c8ee5
GM
1738 it->face_id = base_face_id;
1739
1740 /* If we have a boxed mode line, make the first character appear
1741 with a left box line. */
1742 face = FACE_FROM_ID (it->f, base_face_id);
1743 if (face->box != FACE_NO_BOX)
1744 it->start_of_box_run_p = 1;
1745 }
1746
1747 /* If a buffer position was specified, set the iterator there,
1748 getting overlays and face properties from that position. */
3ebf0ea9 1749 if (charpos >= BUF_BEG (current_buffer))
5f5c8ee5
GM
1750 {
1751 it->end_charpos = ZV;
1752 it->face_id = -1;
1753 IT_CHARPOS (*it) = charpos;
2311178e 1754
5f5c8ee5 1755 /* Compute byte position if not specified. */
3ebf0ea9 1756 if (bytepos < charpos)
5f5c8ee5
GM
1757 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
1758 else
1759 IT_BYTEPOS (*it) = bytepos;
1760
1761 /* Compute faces etc. */
1762 reseat (it, it->current.pos, 1);
1763 }
2311178e 1764
5f5c8ee5
GM
1765 CHECK_IT (it);
1766}
1767
1768
1769/* Initialize IT for the display of window W with window start POS. */
1770
1771void
1772start_display (it, w, pos)
1773 struct it *it;
1774 struct window *w;
1775 struct text_pos pos;
1776{
5f5c8ee5 1777 struct glyph_row *row;
045dee35 1778 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
1779
1780 row = w->desired_matrix->rows + first_vpos;
1781 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
17fdcfc8
GM
1782
1783 if (!it->truncate_lines_p)
5f5c8ee5 1784 {
17fdcfc8
GM
1785 int start_at_line_beg_p;
1786 int first_y = it->current_y;
2311178e 1787
17fdcfc8
GM
1788 /* If window start is not at a line start, skip forward to POS to
1789 get the correct continuation lines width. */
1790 start_at_line_beg_p = (CHARPOS (pos) == BEGV
1791 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
1792 if (!start_at_line_beg_p)
5f5c8ee5 1793 {
17fdcfc8
GM
1794 reseat_at_previous_visible_line_start (it);
1795 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
1796
1797 /* If lines are continued, this line may end in the middle
1798 of a multi-glyph character (e.g. a control character
1799 displayed as \003, or in the middle of an overlay
1800 string). In this case move_it_to above will not have
1801 taken us to the start of the continuation line but to the
1802 end of the continued line. */
b28cb6ed 1803 if (it->current_x > 0)
5f5c8ee5 1804 {
b28cb6ed
GM
1805 if (it->current.dpvec_index >= 0
1806 || it->current.overlay_string_index >= 0)
1807 {
cafafe0b 1808 set_iterator_to_next (it, 1);
b28cb6ed
GM
1809 move_it_in_display_line_to (it, -1, -1, 0);
1810 }
2311178e 1811
b28cb6ed 1812 it->continuation_lines_width += it->current_x;
5f5c8ee5 1813 }
b28cb6ed
GM
1814
1815 /* We're starting a new display line, not affected by the
1816 height of the continued line, so clear the appropriate
1817 fields in the iterator structure. */
1818 it->max_ascent = it->max_descent = 0;
1819 it->max_phys_ascent = it->max_phys_descent = 0;
2311178e 1820
17fdcfc8
GM
1821 it->current_y = first_y;
1822 it->vpos = 0;
1823 it->current_x = it->hpos = 0;
1824 }
5f5c8ee5
GM
1825 }
1826
1827#if 0 /* Don't assert the following because start_display is sometimes
1828 called intentionally with a window start that is not at a
1829 line start. Please leave this code in as a comment. */
2311178e 1830
5f5c8ee5
GM
1831 /* Window start should be on a line start, now. */
1832 xassert (it->continuation_lines_width
1833 || IT_CHARPOS (it) == BEGV
1834 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
1835#endif /* 0 */
1836}
1837
1838
4bde0ebb
GM
1839/* Return 1 if POS is a position in ellipses displayed for invisible
1840 text. W is the window we display, for text property lookup. */
5f5c8ee5 1841
4bde0ebb
GM
1842static int
1843in_ellipses_for_invisible_text_p (pos, w)
5f5c8ee5 1844 struct display_pos *pos;
4bde0ebb 1845 struct window *w;
5f5c8ee5 1846{
ac90c44f 1847 Lisp_Object prop, window;
4bde0ebb
GM
1848 int ellipses_p = 0;
1849 int charpos = CHARPOS (pos->pos);
2311178e 1850
ac90c44f
GM
1851 /* If POS specifies a position in a display vector, this might
1852 be for an ellipsis displayed for invisible text. We won't
1853 get the iterator set up for delivering that ellipsis unless
1854 we make sure that it gets aware of the invisible text. */
1855 if (pos->dpvec_index >= 0
1856 && pos->overlay_string_index < 0
1857 && CHARPOS (pos->string_pos) < 0
1858 && charpos > BEGV
1859 && (XSETWINDOW (window, w),
1860 prop = Fget_char_property (make_number (charpos),
1861 Qinvisible, window),
20fbd925 1862 !TEXT_PROP_MEANS_INVISIBLE (prop)))
ac90c44f
GM
1863 {
1864 prop = Fget_char_property (make_number (charpos - 1), Qinvisible,
1865 window);
8580a4e3 1866 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
4bde0ebb
GM
1867 }
1868
1869 return ellipses_p;
1870}
1871
1872
1873/* Initialize IT for stepping through current_buffer in window W,
1874 starting at position POS that includes overlay string and display
47d57b22
GM
1875 vector/ control character translation position information. Value
1876 is zero if there are overlay strings with newlines at POS. */
4bde0ebb 1877
47d57b22 1878static int
4bde0ebb
GM
1879init_from_display_pos (it, w, pos)
1880 struct it *it;
1881 struct window *w;
1882 struct display_pos *pos;
1883{
1884 int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
47d57b22 1885 int i, overlay_strings_with_newlines = 0;
2311178e 1886
4bde0ebb
GM
1887 /* If POS specifies a position in a display vector, this might
1888 be for an ellipsis displayed for invisible text. We won't
1889 get the iterator set up for delivering that ellipsis unless
1890 we make sure that it gets aware of the invisible text. */
1891 if (in_ellipses_for_invisible_text_p (pos, w))
1892 {
1893 --charpos;
1894 bytepos = 0;
ac90c44f 1895 }
2311178e 1896
5f5c8ee5
GM
1897 /* Keep in mind: the call to reseat in init_iterator skips invisible
1898 text, so we might end up at a position different from POS. This
1899 is only a problem when POS is a row start after a newline and an
1900 overlay starts there with an after-string, and the overlay has an
1901 invisible property. Since we don't skip invisible text in
1902 display_line and elsewhere immediately after consuming the
1903 newline before the row start, such a POS will not be in a string,
1904 but the call to init_iterator below will move us to the
1905 after-string. */
ac90c44f 1906 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
5f5c8ee5 1907
47d57b22 1908 for (i = 0; i < it->n_overlay_strings; ++i)
1e1e5daf 1909 {
50f80c2f
KR
1910 const char *s = SDATA (it->overlay_strings[i]);
1911 const char *e = s + SBYTES (it->overlay_strings[i]);
2311178e 1912
1e1e5daf
GM
1913 while (s < e && *s != '\n')
1914 ++s;
1915
1916 if (s < e)
1917 {
1918 overlay_strings_with_newlines = 1;
1919 break;
1920 }
1921 }
47d57b22 1922
75c5350a
GM
1923 /* If position is within an overlay string, set up IT to the right
1924 overlay string. */
5f5c8ee5
GM
1925 if (pos->overlay_string_index >= 0)
1926 {
1927 int relative_index;
75c5350a
GM
1928
1929 /* If the first overlay string happens to have a `display'
1930 property for an image, the iterator will be set up for that
1931 image, and we have to undo that setup first before we can
1932 correct the overlay string index. */
1933 if (it->method == next_element_from_image)
1934 pop_it (it);
2311178e 1935
5f5c8ee5
GM
1936 /* We already have the first chunk of overlay strings in
1937 IT->overlay_strings. Load more until the one for
1938 pos->overlay_string_index is in IT->overlay_strings. */
1939 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
1940 {
1941 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
1942 it->current.overlay_string_index = 0;
1943 while (n--)
1944 {
5a08cbaf 1945 load_overlay_strings (it, 0);
5f5c8ee5
GM
1946 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
1947 }
1948 }
2311178e 1949
5f5c8ee5
GM
1950 it->current.overlay_string_index = pos->overlay_string_index;
1951 relative_index = (it->current.overlay_string_index
1952 % OVERLAY_STRING_CHUNK_SIZE);
1953 it->string = it->overlay_strings[relative_index];
cafafe0b 1954 xassert (STRINGP (it->string));
5f5c8ee5
GM
1955 it->current.string_pos = pos->string_pos;
1956 it->method = next_element_from_string;
1957 }
2311178e 1958
1e1e5daf
GM
1959#if 0 /* This is bogus because POS not having an overlay string
1960 position does not mean it's after the string. Example: A
1961 line starting with a before-string and initialization of IT
1962 to the previous row's end position. */
2be8f184
GM
1963 else if (it->current.overlay_string_index >= 0)
1964 {
1965 /* If POS says we're already after an overlay string ending at
1966 POS, make sure to pop the iterator because it will be in
1967 front of that overlay string. When POS is ZV, we've thereby
1968 also ``processed'' overlay strings at ZV. */
aeb2b8fc
GM
1969 while (it->sp)
1970 pop_it (it);
2be8f184
GM
1971 it->current.overlay_string_index = -1;
1972 it->method = next_element_from_buffer;
1973 if (CHARPOS (pos->pos) == ZV)
1974 it->overlay_strings_at_end_processed_p = 1;
1975 }
1e1e5daf 1976#endif /* 0 */
2311178e 1977
2be8f184 1978 if (CHARPOS (pos->string_pos) >= 0)
5f5c8ee5
GM
1979 {
1980 /* Recorded position is not in an overlay string, but in another
1981 string. This can only be a string from a `display' property.
1982 IT should already be filled with that string. */
1983 it->current.string_pos = pos->string_pos;
1984 xassert (STRINGP (it->string));
1985 }
1986
ac90c44f
GM
1987 /* Restore position in display vector translations, control
1988 character translations or ellipses. */
5f5c8ee5
GM
1989 if (pos->dpvec_index >= 0)
1990 {
ac90c44f
GM
1991 if (it->dpvec == NULL)
1992 get_next_display_element (it);
5f5c8ee5
GM
1993 xassert (it->dpvec && it->current.dpvec_index == 0);
1994 it->current.dpvec_index = pos->dpvec_index;
1995 }
2311178e 1996
5f5c8ee5 1997 CHECK_IT (it);
47d57b22 1998 return !overlay_strings_with_newlines;
5f5c8ee5
GM
1999}
2000
2001
2002/* Initialize IT for stepping through current_buffer in window W
2003 starting at ROW->start. */
2004
2005static void
2006init_to_row_start (it, w, row)
2007 struct it *it;
2008 struct window *w;
2009 struct glyph_row *row;
2010{
2011 init_from_display_pos (it, w, &row->start);
2012 it->continuation_lines_width = row->continuation_lines_width;
2013 CHECK_IT (it);
2014}
2015
2311178e 2016
5f5c8ee5 2017/* Initialize IT for stepping through current_buffer in window W
47d57b22
GM
2018 starting in the line following ROW, i.e. starting at ROW->end.
2019 Value is zero if there are overlay strings with newlines at ROW's
2020 end position. */
5f5c8ee5 2021
47d57b22 2022static int
5f5c8ee5
GM
2023init_to_row_end (it, w, row)
2024 struct it *it;
2025 struct window *w;
2026 struct glyph_row *row;
2027{
47d57b22 2028 int success = 0;
2311178e 2029
47d57b22
GM
2030 if (init_from_display_pos (it, w, &row->end))
2031 {
2032 if (row->continued_p)
2033 it->continuation_lines_width
2034 = row->continuation_lines_width + row->pixel_width;
2035 CHECK_IT (it);
2036 success = 1;
2037 }
2311178e 2038
47d57b22 2039 return success;
5f5c8ee5
GM
2040}
2041
2042
2043
2044\f
2045/***********************************************************************
2046 Text properties
2047 ***********************************************************************/
2048
2049/* Called when IT reaches IT->stop_charpos. Handle text property and
2050 overlay changes. Set IT->stop_charpos to the next position where
2051 to stop. */
2052
2053static void
2054handle_stop (it)
2055 struct it *it;
2056{
2057 enum prop_handled handled;
2058 int handle_overlay_change_p = 1;
2059 struct props *p;
2060
2061 it->dpvec = NULL;
2062 it->current.dpvec_index = -1;
2063
2064 do
2065 {
2066 handled = HANDLED_NORMALLY;
2311178e 2067
5f5c8ee5
GM
2068 /* Call text property handlers. */
2069 for (p = it_props; p->handler; ++p)
2070 {
2071 handled = p->handler (it);
2970b9be 2072
5f5c8ee5
GM
2073 if (handled == HANDLED_RECOMPUTE_PROPS)
2074 break;
2075 else if (handled == HANDLED_RETURN)
2076 return;
2077 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
2078 handle_overlay_change_p = 0;
2079 }
2080
2081 if (handled != HANDLED_RECOMPUTE_PROPS)
2082 {
2083 /* Don't check for overlay strings below when set to deliver
2084 characters from a display vector. */
2085 if (it->method == next_element_from_display_vector)
2086 handle_overlay_change_p = 0;
2087
2088 /* Handle overlay changes. */
2089 if (handle_overlay_change_p)
2090 handled = handle_overlay_change (it);
2311178e 2091
5f5c8ee5
GM
2092 /* Determine where to stop next. */
2093 if (handled == HANDLED_NORMALLY)
2094 compute_stop_pos (it);
2095 }
2096 }
2097 while (handled == HANDLED_RECOMPUTE_PROPS);
2098}
2099
2100
2101/* Compute IT->stop_charpos from text property and overlay change
2102 information for IT's current position. */
2103
2104static void
2105compute_stop_pos (it)
2106 struct it *it;
2107{
2108 register INTERVAL iv, next_iv;
2109 Lisp_Object object, limit, position;
2110
2111 /* If nowhere else, stop at the end. */
2112 it->stop_charpos = it->end_charpos;
2311178e 2113
5f5c8ee5
GM
2114 if (STRINGP (it->string))
2115 {
2116 /* Strings are usually short, so don't limit the search for
2117 properties. */
2118 object = it->string;
2119 limit = Qnil;
ac90c44f 2120 position = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
2121 }
2122 else
2123 {
2124 int charpos;
2125
2126 /* If next overlay change is in front of the current stop pos
2127 (which is IT->end_charpos), stop there. Note: value of
2128 next_overlay_change is point-max if no overlay change
2129 follows. */
2130 charpos = next_overlay_change (IT_CHARPOS (*it));
2131 if (charpos < it->stop_charpos)
2132 it->stop_charpos = charpos;
2133
2134 /* If showing the region, we have to stop at the region
2135 start or end because the face might change there. */
2136 if (it->region_beg_charpos > 0)
2137 {
2138 if (IT_CHARPOS (*it) < it->region_beg_charpos)
2139 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
2140 else if (IT_CHARPOS (*it) < it->region_end_charpos)
2141 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
2142 }
2311178e 2143
5f5c8ee5
GM
2144 /* Set up variables for computing the stop position from text
2145 property changes. */
2146 XSETBUFFER (object, current_buffer);
ac90c44f
GM
2147 limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
2148 position = make_number (IT_CHARPOS (*it));
5f5c8ee5
GM
2149
2150 }
2151
2152 /* Get the interval containing IT's position. Value is a null
2153 interval if there isn't such an interval. */
2154 iv = validate_interval_range (object, &position, &position, 0);
2155 if (!NULL_INTERVAL_P (iv))
2156 {
2157 Lisp_Object values_here[LAST_PROP_IDX];
2158 struct props *p;
2159
2160 /* Get properties here. */
2161 for (p = it_props; p->handler; ++p)
2162 values_here[p->idx] = textget (iv->plist, *p->name);
2163
2164 /* Look for an interval following iv that has different
2165 properties. */
2166 for (next_iv = next_interval (iv);
2167 (!NULL_INTERVAL_P (next_iv)
2168 && (NILP (limit)
2169 || XFASTINT (limit) > next_iv->position));
2170 next_iv = next_interval (next_iv))
2171 {
2172 for (p = it_props; p->handler; ++p)
2173 {
2174 Lisp_Object new_value;
2175
2176 new_value = textget (next_iv->plist, *p->name);
2177 if (!EQ (values_here[p->idx], new_value))
2178 break;
2179 }
2311178e 2180
5f5c8ee5
GM
2181 if (p->handler)
2182 break;
2183 }
2184
2185 if (!NULL_INTERVAL_P (next_iv))
2186 {
2187 if (INTEGERP (limit)
2188 && next_iv->position >= XFASTINT (limit))
2189 /* No text property change up to limit. */
2190 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
2191 else
2192 /* Text properties change in next_iv. */
2193 it->stop_charpos = min (it->stop_charpos, next_iv->position);
2194 }
2195 }
2196
2197 xassert (STRINGP (it->string)
2198 || (it->stop_charpos >= BEGV
2199 && it->stop_charpos >= IT_CHARPOS (*it)));
2200}
2201
2202
2203/* Return the position of the next overlay change after POS in
2204 current_buffer. Value is point-max if no overlay change
2205 follows. This is like `next-overlay-change' but doesn't use
2206 xmalloc. */
2207
2208static int
2209next_overlay_change (pos)
2210 int pos;
2211{
2212 int noverlays;
2213 int endpos;
2214 Lisp_Object *overlays;
2215 int len;
2216 int i;
2217
2218 /* Get all overlays at the given position. */
2219 len = 10;
2220 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2221 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2222 if (noverlays > len)
2223 {
2224 len = noverlays;
2225 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2226 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2227 }
2228
2229 /* If any of these overlays ends before endpos,
2230 use its ending point instead. */
2231 for (i = 0; i < noverlays; ++i)
2232 {
2233 Lisp_Object oend;
2234 int oendpos;
2235
2236 oend = OVERLAY_END (overlays[i]);
2237 oendpos = OVERLAY_POSITION (oend);
2238 endpos = min (endpos, oendpos);
2239 }
2240
2241 return endpos;
2242}
2243
2244
2245\f
2246/***********************************************************************
2247 Fontification
2248 ***********************************************************************/
2249
2250/* Handle changes in the `fontified' property of the current buffer by
2251 calling hook functions from Qfontification_functions to fontify
2252 regions of text. */
2253
2254static enum prop_handled
2255handle_fontified_prop (it)
2256 struct it *it;
2257{
2258 Lisp_Object prop, pos;
2259 enum prop_handled handled = HANDLED_NORMALLY;
2260
2261 /* Get the value of the `fontified' property at IT's current buffer
2262 position. (The `fontified' property doesn't have a special
2263 meaning in strings.) If the value is nil, call functions from
2264 Qfontification_functions. */
2265 if (!STRINGP (it->string)
2266 && it->s == NULL
2267 && !NILP (Vfontification_functions)
085536c2 2268 && !NILP (Vrun_hooks)
5f5c8ee5
GM
2269 && (pos = make_number (IT_CHARPOS (*it)),
2270 prop = Fget_char_property (pos, Qfontified, Qnil),
2271 NILP (prop)))
2272 {
331379bf 2273 int count = SPECPDL_INDEX ();
085536c2
GM
2274 Lisp_Object val;
2275
2276 val = Vfontification_functions;
2277 specbind (Qfontification_functions, Qnil);
2311178e 2278
085536c2 2279 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
116d6f5c 2280 safe_call1 (val, pos);
085536c2
GM
2281 else
2282 {
2283 Lisp_Object globals, fn;
2284 struct gcpro gcpro1, gcpro2;
5f5c8ee5 2285
085536c2
GM
2286 globals = Qnil;
2287 GCPRO2 (val, globals);
2311178e 2288
085536c2
GM
2289 for (; CONSP (val); val = XCDR (val))
2290 {
2291 fn = XCAR (val);
2311178e 2292
085536c2
GM
2293 if (EQ (fn, Qt))
2294 {
2295 /* A value of t indicates this hook has a local
2296 binding; it means to run the global binding too.
2297 In a global value, t should not occur. If it
2298 does, we must ignore it to avoid an endless
2299 loop. */
2300 for (globals = Fdefault_value (Qfontification_functions);
2301 CONSP (globals);
2302 globals = XCDR (globals))
2303 {
2304 fn = XCAR (globals);
2305 if (!EQ (fn, Qt))
116d6f5c 2306 safe_call1 (fn, pos);
085536c2
GM
2307 }
2308 }
2309 else
116d6f5c 2310 safe_call1 (fn, pos);
085536c2
GM
2311 }
2312
2313 UNGCPRO;
2314 }
2315
2316 unbind_to (count, Qnil);
5f5c8ee5
GM
2317
2318 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
2319 something. This avoids an endless loop if they failed to
2320 fontify the text for which reason ever. */
2321 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
2322 handled = HANDLED_RECOMPUTE_PROPS;
2323 }
2324
2325 return handled;
2326}
2327
2328
2329\f
2330/***********************************************************************
2331 Faces
2332 ***********************************************************************/
2333
2334/* Set up iterator IT from face properties at its current position.
2335 Called from handle_stop. */
2336
2337static enum prop_handled
2338handle_face_prop (it)
2339 struct it *it;
2340{
2341 int new_face_id, next_stop;
2311178e 2342
5f5c8ee5
GM
2343 if (!STRINGP (it->string))
2344 {
2345 new_face_id
2346 = face_at_buffer_position (it->w,
2347 IT_CHARPOS (*it),
2348 it->region_beg_charpos,
2349 it->region_end_charpos,
2350 &next_stop,
2351 (IT_CHARPOS (*it)
2352 + TEXT_PROP_DISTANCE_LIMIT),
2353 0);
2311178e 2354
5f5c8ee5
GM
2355 /* Is this a start of a run of characters with box face?
2356 Caveat: this can be called for a freshly initialized
4b41cebb 2357 iterator; face_id is -1 in this case. We know that the new
5f5c8ee5
GM
2358 face will not change until limit, i.e. if the new face has a
2359 box, all characters up to limit will have one. But, as
2360 usual, we don't know whether limit is really the end. */
2361 if (new_face_id != it->face_id)
2362 {
2363 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2311178e 2364
5f5c8ee5
GM
2365 /* If new face has a box but old face has not, this is
2366 the start of a run of characters with box, i.e. it has
2367 a shadow on the left side. The value of face_id of the
2368 iterator will be -1 if this is the initial call that gets
2369 the face. In this case, we have to look in front of IT's
2370 position and see whether there is a face != new_face_id. */
2371 it->start_of_box_run_p
2372 = (new_face->box != FACE_NO_BOX
2373 && (it->face_id >= 0
2374 || IT_CHARPOS (*it) == BEG
2375 || new_face_id != face_before_it_pos (it)));
2376 it->face_box_p = new_face->box != FACE_NO_BOX;
2377 }
2378 }
2379 else
2380 {
06a12811
GM
2381 int base_face_id, bufpos;
2382
2383 if (it->current.overlay_string_index >= 0)
2384 bufpos = IT_CHARPOS (*it);
2385 else
2386 bufpos = 0;
2311178e 2387
06a12811
GM
2388 /* For strings from a buffer, i.e. overlay strings or strings
2389 from a `display' property, use the face at IT's current
2390 buffer position as the base face to merge with, so that
2391 overlay strings appear in the same face as surrounding
2392 text, unless they specify their own faces. */
2393 base_face_id = underlying_face_id (it);
2311178e 2394
06a12811
GM
2395 new_face_id = face_at_string_position (it->w,
2396 it->string,
2397 IT_STRING_CHARPOS (*it),
2398 bufpos,
2399 it->region_beg_charpos,
2400 it->region_end_charpos,
2401 &next_stop,
5de7c6f2 2402 base_face_id, 0);
2311178e 2403
5f5c8ee5
GM
2404#if 0 /* This shouldn't be neccessary. Let's check it. */
2405 /* If IT is used to display a mode line we would really like to
2406 use the mode line face instead of the frame's default face. */
2407 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
2408 && new_face_id == DEFAULT_FACE_ID)
96d2320f 2409 new_face_id = CURRENT_MODE_LINE_FACE_ID (it->w);
5f5c8ee5 2410#endif
2311178e 2411
5f5c8ee5
GM
2412 /* Is this a start of a run of characters with box? Caveat:
2413 this can be called for a freshly allocated iterator; face_id
2414 is -1 is this case. We know that the new face will not
2415 change until the next check pos, i.e. if the new face has a
2416 box, all characters up to that position will have a
2417 box. But, as usual, we don't know whether that position
2418 is really the end. */
2419 if (new_face_id != it->face_id)
2420 {
2421 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2422 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
2311178e 2423
5f5c8ee5
GM
2424 /* If new face has a box but old face hasn't, this is the
2425 start of a run of characters with box, i.e. it has a
2426 shadow on the left side. */
2427 it->start_of_box_run_p
2428 = new_face->box && (old_face == NULL || !old_face->box);
2429 it->face_box_p = new_face->box != FACE_NO_BOX;
2430 }
2431 }
2311178e 2432
5f5c8ee5 2433 it->face_id = new_face_id;
5f5c8ee5
GM
2434 return HANDLED_NORMALLY;
2435}
2436
2437
06a12811
GM
2438/* Return the ID of the face ``underlying'' IT's current position,
2439 which is in a string. If the iterator is associated with a
2440 buffer, return the face at IT's current buffer position.
2441 Otherwise, use the iterator's base_face_id. */
2442
2443static int
2444underlying_face_id (it)
2445 struct it *it;
2446{
2447 int face_id = it->base_face_id, i;
2448
2449 xassert (STRINGP (it->string));
2450
2451 for (i = it->sp - 1; i >= 0; --i)
2452 if (NILP (it->stack[i].string))
2453 face_id = it->stack[i].face_id;
2454
2455 return face_id;
2456}
2457
2458
5f5c8ee5
GM
2459/* Compute the face one character before or after the current position
2460 of IT. BEFORE_P non-zero means get the face in front of IT's
2461 position. Value is the id of the face. */
2462
2463static int
2464face_before_or_after_it_pos (it, before_p)
2465 struct it *it;
2466 int before_p;
2467{
2468 int face_id, limit;
2469 int next_check_charpos;
2470 struct text_pos pos;
2471
2472 xassert (it->s == NULL);
2311178e 2473
5f5c8ee5
GM
2474 if (STRINGP (it->string))
2475 {
06a12811 2476 int bufpos, base_face_id;
2311178e 2477
5f5c8ee5
GM
2478 /* No face change past the end of the string (for the case
2479 we are padding with spaces). No face change before the
2480 string start. */
2051c264 2481 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
5f5c8ee5
GM
2482 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
2483 return it->face_id;
2484
2485 /* Set pos to the position before or after IT's current position. */
2486 if (before_p)
2487 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
2488 else
260a86a0
KH
2489 /* For composition, we must check the character after the
2490 composition. */
2491 pos = (it->what == IT_COMPOSITION
2492 ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
2493 : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
5f5c8ee5 2494
06a12811
GM
2495 if (it->current.overlay_string_index >= 0)
2496 bufpos = IT_CHARPOS (*it);
2497 else
2498 bufpos = 0;
2499
2500 base_face_id = underlying_face_id (it);
2501
5f5c8ee5 2502 /* Get the face for ASCII, or unibyte. */
06a12811
GM
2503 face_id = face_at_string_position (it->w,
2504 it->string,
2505 CHARPOS (pos),
2506 bufpos,
2507 it->region_beg_charpos,
2508 it->region_end_charpos,
2509 &next_check_charpos,
5de7c6f2 2510 base_face_id, 0);
5f5c8ee5
GM
2511
2512 /* Correct the face for charsets different from ASCII. Do it
2513 for the multibyte case only. The face returned above is
2514 suitable for unibyte text if IT->string is unibyte. */
2515 if (STRING_MULTIBYTE (it->string))
2516 {
50f80c2f 2517 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos);
2051c264 2518 int rest = SBYTES (it->string) - BYTEPOS (pos);
980806b6
KH
2519 int c, len;
2520 struct face *face = FACE_FROM_ID (it->f, face_id);
2311178e 2521
4fdb80f2 2522 c = string_char_and_length (p, rest, &len);
980806b6 2523 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2524 }
2525 }
2526 else
2527 {
70851746
GM
2528 if ((IT_CHARPOS (*it) >= ZV && !before_p)
2529 || (IT_CHARPOS (*it) <= BEGV && before_p))
2530 return it->face_id;
2311178e 2531
5f5c8ee5
GM
2532 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
2533 pos = it->current.pos;
2311178e 2534
5f5c8ee5 2535 if (before_p)
c1005d06 2536 DEC_TEXT_POS (pos, it->multibyte_p);
5f5c8ee5 2537 else
260a86a0
KH
2538 {
2539 if (it->what == IT_COMPOSITION)
2540 /* For composition, we must check the position after the
2541 composition. */
2542 pos.charpos += it->cmp_len, pos.bytepos += it->len;
2543 else
c1005d06 2544 INC_TEXT_POS (pos, it->multibyte_p);
260a86a0 2545 }
2311178e 2546
5f5c8ee5
GM
2547 /* Determine face for CHARSET_ASCII, or unibyte. */
2548 face_id = face_at_buffer_position (it->w,
2549 CHARPOS (pos),
2550 it->region_beg_charpos,
2551 it->region_end_charpos,
2552 &next_check_charpos,
2553 limit, 0);
2554
2555 /* Correct the face for charsets different from ASCII. Do it
2556 for the multibyte case only. The face returned above is
2557 suitable for unibyte text if current_buffer is unibyte. */
2558 if (it->multibyte_p)
2559 {
1d1b6e6a 2560 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
980806b6
KH
2561 struct face *face = FACE_FROM_ID (it->f, face_id);
2562 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2563 }
2564 }
2311178e 2565
5f5c8ee5
GM
2566 return face_id;
2567}
2568
2569
2570\f
2571/***********************************************************************
2572 Invisible text
2573 ***********************************************************************/
2574
2575/* Set up iterator IT from invisible properties at its current
2576 position. Called from handle_stop. */
2577
2578static enum prop_handled
2579handle_invisible_prop (it)
2580 struct it *it;
2581{
2582 enum prop_handled handled = HANDLED_NORMALLY;
2583
2584 if (STRINGP (it->string))
2585 {
2586 extern Lisp_Object Qinvisible;
2587 Lisp_Object prop, end_charpos, limit, charpos;
2588
2589 /* Get the value of the invisible text property at the
2590 current position. Value will be nil if there is no such
2591 property. */
ac90c44f 2592 charpos = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
2593 prop = Fget_text_property (charpos, Qinvisible, it->string);
2594
eadc0bf8
GM
2595 if (!NILP (prop)
2596 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
2597 {
2598 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 2599
5f5c8ee5
GM
2600 /* Get the position at which the next change of the
2601 invisible text property can be found in IT->string.
2602 Value will be nil if the property value is the same for
2603 all the rest of IT->string. */
2051c264 2604 XSETINT (limit, SCHARS (it->string));
5f5c8ee5 2605 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2051c264 2606 it->string, limit);
2311178e 2607
5f5c8ee5
GM
2608 /* Text at current position is invisible. The next
2609 change in the property is at position end_charpos.
2610 Move IT's current position to that position. */
2611 if (INTEGERP (end_charpos)
2612 && XFASTINT (end_charpos) < XFASTINT (limit))
2613 {
2614 struct text_pos old;
2615 old = it->current.string_pos;
2616 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
2617 compute_string_pos (&it->current.string_pos, old, it->string);
2618 }
2619 else
2620 {
2621 /* The rest of the string is invisible. If this is an
2622 overlay string, proceed with the next overlay string
2623 or whatever comes and return a character from there. */
2624 if (it->current.overlay_string_index >= 0)
2625 {
2626 next_overlay_string (it);
2627 /* Don't check for overlay strings when we just
2628 finished processing them. */
2629 handled = HANDLED_OVERLAY_STRING_CONSUMED;
2630 }
2631 else
2632 {
2051c264
GM
2633 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
2634 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5f5c8ee5
GM
2635 }
2636 }
2637 }
2638 }
2639 else
2640 {
8580a4e3 2641 int invis_p, newpos, next_stop, start_charpos;
5a08cbaf 2642 Lisp_Object pos, prop, overlay;
5f5c8ee5
GM
2643
2644 /* First of all, is there invisible text at this position? */
5a08cbaf 2645 start_charpos = IT_CHARPOS (*it);
ac90c44f 2646 pos = make_number (IT_CHARPOS (*it));
5a08cbaf
GM
2647 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
2648 &overlay);
8580a4e3
SM
2649 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
2650
5f5c8ee5 2651 /* If we are on invisible text, skip over it. */
8580a4e3 2652 if (invis_p && IT_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
2653 {
2654 /* Record whether we have to display an ellipsis for the
2655 invisible text. */
8580a4e3 2656 int display_ellipsis_p = invis_p == 2;
5f5c8ee5
GM
2657
2658 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 2659
5f5c8ee5
GM
2660 /* Loop skipping over invisible text. The loop is left at
2661 ZV or with IT on the first char being visible again. */
2662 do
2663 {
2664 /* Try to skip some invisible text. Return value is the
2665 position reached which can be equal to IT's position
2666 if there is nothing invisible here. This skips both
2667 over invisible text properties and overlays with
2668 invisible property. */
2669 newpos = skip_invisible (IT_CHARPOS (*it),
2670 &next_stop, ZV, it->window);
2671
2672 /* If we skipped nothing at all we weren't at invisible
2673 text in the first place. If everything to the end of
2674 the buffer was skipped, end the loop. */
2675 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
8580a4e3 2676 invis_p = 0;
5f5c8ee5
GM
2677 else
2678 {
2679 /* We skipped some characters but not necessarily
2680 all there are. Check if we ended up on visible
2681 text. Fget_char_property returns the property of
2682 the char before the given position, i.e. if we
8580a4e3 2683 get invis_p = 0, this means that the char at
5f5c8ee5 2684 newpos is visible. */
ac90c44f 2685 pos = make_number (newpos);
5f5c8ee5 2686 prop = Fget_char_property (pos, Qinvisible, it->window);
8580a4e3 2687 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
5f5c8ee5 2688 }
2311178e 2689
5f5c8ee5
GM
2690 /* If we ended up on invisible text, proceed to
2691 skip starting with next_stop. */
8580a4e3 2692 if (invis_p)
5f5c8ee5
GM
2693 IT_CHARPOS (*it) = next_stop;
2694 }
8580a4e3 2695 while (invis_p);
5a08cbaf 2696
5f5c8ee5
GM
2697 /* The position newpos is now either ZV or on visible text. */
2698 IT_CHARPOS (*it) = newpos;
2699 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2311178e 2700
5a08cbaf
GM
2701 /* If there are before-strings at the start of invisible
2702 text, and the text is invisible because of a text
2703 property, arrange to show before-strings because 20.x did
2704 it that way. (If the text is invisible because of an
2705 overlay property instead of a text property, this is
2706 already handled in the overlay code.) */
2707 if (NILP (overlay)
2708 && get_overlay_strings (it, start_charpos))
5f5c8ee5 2709 {
5a08cbaf
GM
2710 handled = HANDLED_RECOMPUTE_PROPS;
2711 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5f5c8ee5 2712 }
5a08cbaf
GM
2713 else if (display_ellipsis_p)
2714 setup_for_ellipsis (it);
5f5c8ee5
GM
2715 }
2716 }
2717
2718 return handled;
2719}
2720
2721
5a08cbaf
GM
2722/* Make iterator IT return `...' next. */
2723
2724static void
2725setup_for_ellipsis (it)
2726 struct it *it;
2727{
2311178e 2728 if (it->dp
5a08cbaf
GM
2729 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
2730 {
2731 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
2732 it->dpvec = v->contents;
2733 it->dpend = v->contents + v->size;
2734 }
2311178e 2735 else
5a08cbaf
GM
2736 {
2737 /* Default `...'. */
2738 it->dpvec = default_invis_vector;
2739 it->dpend = default_invis_vector + 3;
2740 }
2311178e 2741
5a08cbaf
GM
2742 /* The ellipsis display does not replace the display of the
2743 character at the new position. Indicate this by setting
2744 IT->dpvec_char_len to zero. */
2745 it->dpvec_char_len = 0;
2311178e 2746
5a08cbaf
GM
2747 it->current.dpvec_index = 0;
2748 it->method = next_element_from_display_vector;
2749}
2750
2751
5f5c8ee5
GM
2752\f
2753/***********************************************************************
2754 'display' property
2755 ***********************************************************************/
2756
2757/* Set up iterator IT from `display' property at its current position.
2758 Called from handle_stop. */
2759
2760static enum prop_handled
2761handle_display_prop (it)
2762 struct it *it;
2763{
2764 Lisp_Object prop, object;
2765 struct text_pos *position;
a61b7058 2766 int display_replaced_p = 0;
5f5c8ee5
GM
2767
2768 if (STRINGP (it->string))
2769 {
2770 object = it->string;
2771 position = &it->current.string_pos;
2772 }
2773 else
2774 {
221dd3e7 2775 object = it->w->buffer;
5f5c8ee5
GM
2776 position = &it->current.pos;
2777 }
2778
2779 /* Reset those iterator values set from display property values. */
2780 it->font_height = Qnil;
2781 it->space_width = Qnil;
2782 it->voffset = 0;
2783
2784 /* We don't support recursive `display' properties, i.e. string
2785 values that have a string `display' property, that have a string
2786 `display' property etc. */
2787 if (!it->string_from_display_prop_p)
2788 it->area = TEXT_AREA;
2789
2790 prop = Fget_char_property (make_number (position->charpos),
2791 Qdisplay, object);
2792 if (NILP (prop))
2793 return HANDLED_NORMALLY;
2794
f3751a65 2795 if (CONSP (prop)
12700f40
GM
2796 /* Simple properties. */
2797 && !EQ (XCAR (prop), Qimage)
2798 && !EQ (XCAR (prop), Qspace)
2799 && !EQ (XCAR (prop), Qwhen)
2800 && !EQ (XCAR (prop), Qspace_width)
2801 && !EQ (XCAR (prop), Qheight)
2802 && !EQ (XCAR (prop), Qraise)
2803 /* Marginal area specifications. */
2804 && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin))
2805 && !NILP (XCAR (prop)))
5f5c8ee5 2806 {
a61b7058 2807 for (; CONSP (prop); prop = XCDR (prop))
5f5c8ee5 2808 {
a61b7058
GM
2809 if (handle_single_display_prop (it, XCAR (prop), object,
2810 position, display_replaced_p))
2811 display_replaced_p = 1;
5f5c8ee5
GM
2812 }
2813 }
2814 else if (VECTORP (prop))
2815 {
2816 int i;
a61b7058
GM
2817 for (i = 0; i < ASIZE (prop); ++i)
2818 if (handle_single_display_prop (it, AREF (prop, i), object,
2819 position, display_replaced_p))
2820 display_replaced_p = 1;
5f5c8ee5
GM
2821 }
2822 else
2823 {
a61b7058
GM
2824 if (handle_single_display_prop (it, prop, object, position, 0))
2825 display_replaced_p = 1;
5f5c8ee5
GM
2826 }
2827
a61b7058 2828 return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
5f5c8ee5
GM
2829}
2830
2831
6c577098 2832/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
2833 at START_POS in OBJECT. */
2834
2835static struct text_pos
2836display_prop_end (it, object, start_pos)
2837 struct it *it;
2838 Lisp_Object object;
2839 struct text_pos start_pos;
2840{
2841 Lisp_Object end;
2842 struct text_pos end_pos;
5f5c8ee5 2843
016b5642
MB
2844 end = Fnext_single_char_property_change (make_number (CHARPOS (start_pos)),
2845 Qdisplay, object, Qnil);
6c577098
GM
2846 CHARPOS (end_pos) = XFASTINT (end);
2847 if (STRINGP (object))
5f5c8ee5
GM
2848 compute_string_pos (&end_pos, start_pos, it->string);
2849 else
6c577098 2850 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
2851
2852 return end_pos;
2853}
2854
2855
2856/* Set up IT from a single `display' sub-property value PROP. OBJECT
2857 is the object in which the `display' property was found. *POSITION
a61b7058
GM
2858 is the position at which it was found. DISPLAY_REPLACED_P non-zero
2859 means that we previously saw a display sub-property which already
2860 replaced text display with something else, for example an image;
2861 ignore such properties after the first one has been processed.
5f5c8ee5
GM
2862
2863 If PROP is a `space' or `image' sub-property, set *POSITION to the
2864 end position of the `display' property.
2865
4b41cebb 2866 Value is non-zero if something was found which replaces the display
a61b7058 2867 of buffer or string text. */
5f5c8ee5
GM
2868
2869static int
a61b7058
GM
2870handle_single_display_prop (it, prop, object, position,
2871 display_replaced_before_p)
5f5c8ee5
GM
2872 struct it *it;
2873 Lisp_Object prop;
2874 Lisp_Object object;
2875 struct text_pos *position;
a61b7058 2876 int display_replaced_before_p;
5f5c8ee5
GM
2877{
2878 Lisp_Object value;
a61b7058 2879 int replaces_text_display_p = 0;
5f5c8ee5
GM
2880 Lisp_Object form;
2881
d3acf96b 2882 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
4b41cebb 2883 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 2884 form = Qt;
d3acf96b 2885 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
2886 {
2887 prop = XCDR (prop);
2888 if (!CONSP (prop))
2889 return 0;
2890 form = XCAR (prop);
2891 prop = XCDR (prop);
5f5c8ee5
GM
2892 }
2893
2894 if (!NILP (form) && !EQ (form, Qt))
2895 {
331379bf 2896 int count = SPECPDL_INDEX ();
5f5c8ee5 2897 struct gcpro gcpro1;
5f5c8ee5 2898
b384d6f8
GM
2899 /* Bind `object' to the object having the `display' property, a
2900 buffer or string. Bind `position' to the position in the
2901 object where the property was found, and `buffer-position'
2902 to the current position in the buffer. */
2903 specbind (Qobject, object);
31ac723b
SM
2904 specbind (Qposition, make_number (CHARPOS (*position)));
2905 specbind (Qbuffer_position,
2906 make_number (STRINGP (object)
2907 ? IT_CHARPOS (*it) : CHARPOS (*position)));
b384d6f8 2908 GCPRO1 (form);
116d6f5c 2909 form = safe_eval (form);
b384d6f8
GM
2910 UNGCPRO;
2911 unbind_to (count, Qnil);
5f5c8ee5 2912 }
2311178e 2913
5f5c8ee5
GM
2914 if (NILP (form))
2915 return 0;
2916
2917 if (CONSP (prop)
2918 && EQ (XCAR (prop), Qheight)
2919 && CONSP (XCDR (prop)))
2920 {
e4093f38 2921 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
5f5c8ee5 2922 return 0;
2311178e 2923
5f5c8ee5
GM
2924 /* `(height HEIGHT)'. */
2925 it->font_height = XCAR (XCDR (prop));
2926 if (!NILP (it->font_height))
2927 {
2928 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2929 int new_height = -1;
2930
2931 if (CONSP (it->font_height)
2932 && (EQ (XCAR (it->font_height), Qplus)
2933 || EQ (XCAR (it->font_height), Qminus))
2934 && CONSP (XCDR (it->font_height))
2935 && INTEGERP (XCAR (XCDR (it->font_height))))
2936 {
2937 /* `(+ N)' or `(- N)' where N is an integer. */
2938 int steps = XINT (XCAR (XCDR (it->font_height)));
2939 if (EQ (XCAR (it->font_height), Qplus))
2940 steps = - steps;
2941 it->face_id = smaller_face (it->f, it->face_id, steps);
2942 }
0d8b31c0 2943 else if (FUNCTIONP (it->font_height))
5f5c8ee5
GM
2944 {
2945 /* Call function with current height as argument.
2946 Value is the new height. */
116d6f5c
GM
2947 Lisp_Object height;
2948 height = safe_call1 (it->font_height,
2949 face->lface[LFACE_HEIGHT_INDEX]);
5f5c8ee5
GM
2950 if (NUMBERP (height))
2951 new_height = XFLOATINT (height);
5f5c8ee5
GM
2952 }
2953 else if (NUMBERP (it->font_height))
2954 {
2955 /* Value is a multiple of the canonical char height. */
2956 struct face *face;
2311178e 2957
5f5c8ee5
GM
2958 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
2959 new_height = (XFLOATINT (it->font_height)
2960 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
2961 }
2962 else
2963 {
2964 /* Evaluate IT->font_height with `height' bound to the
2965 current specified height to get the new height. */
2966 Lisp_Object value;
331379bf 2967 int count = SPECPDL_INDEX ();
2311178e 2968
5f5c8ee5 2969 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
116d6f5c 2970 value = safe_eval (it->font_height);
5f5c8ee5 2971 unbind_to (count, Qnil);
2311178e 2972
5f5c8ee5
GM
2973 if (NUMBERP (value))
2974 new_height = XFLOATINT (value);
2975 }
2311178e 2976
5f5c8ee5
GM
2977 if (new_height > 0)
2978 it->face_id = face_with_height (it->f, it->face_id, new_height);
2979 }
2980 }
2981 else if (CONSP (prop)
2982 && EQ (XCAR (prop), Qspace_width)
2983 && CONSP (XCDR (prop)))
2984 {
2985 /* `(space_width WIDTH)'. */
e4093f38 2986 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 2987 return 0;
2311178e 2988
5f5c8ee5
GM
2989 value = XCAR (XCDR (prop));
2990 if (NUMBERP (value) && XFLOATINT (value) > 0)
2991 it->space_width = value;
2992 }
2993 else if (CONSP (prop)
2994 && EQ (XCAR (prop), Qraise)
2995 && CONSP (XCDR (prop)))
2996 {
5f5c8ee5 2997 /* `(raise FACTOR)'. */
e4093f38 2998 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 2999 return 0;
2311178e 3000
fb3842a8 3001#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
3002 value = XCAR (XCDR (prop));
3003 if (NUMBERP (value))
3004 {
3005 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3006 it->voffset = - (XFLOATINT (value)
1ab3e082 3007 * (FONT_HEIGHT (face->font)));
5f5c8ee5
GM
3008 }
3009#endif /* HAVE_WINDOW_SYSTEM */
3010 }
3011 else if (!it->string_from_display_prop_p)
3012 {
f3751a65 3013 /* `((margin left-margin) VALUE)' or `((margin right-margin)
4b41cebb 3014 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
3015 Lisp_Object location, value;
3016 struct text_pos start_pos;
3017 int valid_p;
3018
3019 /* Characters having this form of property are not displayed, so
3020 we have to find the end of the property. */
5f5c8ee5
GM
3021 start_pos = *position;
3022 *position = display_prop_end (it, object, start_pos);
15e26c76 3023 value = Qnil;
5f5c8ee5
GM
3024
3025 /* Let's stop at the new position and assume that all
3026 text properties change there. */
3027 it->stop_charpos = position->charpos;
3028
f3751a65
GM
3029 location = Qunbound;
3030 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 3031 {
f3751a65 3032 Lisp_Object tem;
2311178e 3033
5f5c8ee5 3034 value = XCDR (prop);
f3751a65
GM
3035 if (CONSP (value))
3036 value = XCAR (value);
3037
3038 tem = XCAR (prop);
3039 if (EQ (XCAR (tem), Qmargin)
3040 && (tem = XCDR (tem),
3041 tem = CONSP (tem) ? XCAR (tem) : Qnil,
3042 (NILP (tem)
3043 || EQ (tem, Qleft_margin)
3044 || EQ (tem, Qright_margin))))
3045 location = tem;
5f5c8ee5 3046 }
f3751a65
GM
3047
3048 if (EQ (location, Qunbound))
5f5c8ee5
GM
3049 {
3050 location = Qnil;
3051 value = prop;
3052 }
3053
3054#ifdef HAVE_WINDOW_SYSTEM
fb3842a8 3055 if (FRAME_TERMCAP_P (it->f))
5f5c8ee5
GM
3056 valid_p = STRINGP (value);
3057 else
3058 valid_p = (STRINGP (value)
3059 || (CONSP (value) && EQ (XCAR (value), Qspace))
3060 || valid_image_p (value));
3061#else /* not HAVE_WINDOW_SYSTEM */
3062 valid_p = STRINGP (value);
3063#endif /* not HAVE_WINDOW_SYSTEM */
2311178e 3064
5f5c8ee5
GM
3065 if ((EQ (location, Qleft_margin)
3066 || EQ (location, Qright_margin)
3067 || NILP (location))
a61b7058
GM
3068 && valid_p
3069 && !display_replaced_before_p)
5f5c8ee5 3070 {
a61b7058 3071 replaces_text_display_p = 1;
2311178e 3072
5f5c8ee5
GM
3073 /* Save current settings of IT so that we can restore them
3074 when we are finished with the glyph property value. */
3075 push_it (it);
2311178e 3076
5f5c8ee5
GM
3077 if (NILP (location))
3078 it->area = TEXT_AREA;
3079 else if (EQ (location, Qleft_margin))
3080 it->area = LEFT_MARGIN_AREA;
3081 else
3082 it->area = RIGHT_MARGIN_AREA;
2311178e 3083
5f5c8ee5
GM
3084 if (STRINGP (value))
3085 {
3086 it->string = value;
3087 it->multibyte_p = STRING_MULTIBYTE (it->string);
3088 it->current.overlay_string_index = -1;
3089 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2051c264 3090 it->end_charpos = it->string_nchars = SCHARS (it->string);
5f5c8ee5
GM
3091 it->method = next_element_from_string;
3092 it->stop_charpos = 0;
3093 it->string_from_display_prop_p = 1;
e187cf71
GM
3094 /* Say that we haven't consumed the characters with
3095 `display' property yet. The call to pop_it in
3096 set_iterator_to_next will clean this up. */
3097 *position = start_pos;
5f5c8ee5
GM
3098 }
3099 else if (CONSP (value) && EQ (XCAR (value), Qspace))
3100 {
3101 it->method = next_element_from_stretch;
3102 it->object = value;
3103 it->current.pos = it->position = start_pos;
3104 }
3105#ifdef HAVE_WINDOW_SYSTEM
3106 else
3107 {
3108 it->what = IT_IMAGE;
3109 it->image_id = lookup_image (it->f, value);
3110 it->position = start_pos;
3111 it->object = NILP (object) ? it->w->buffer : object;
3112 it->method = next_element_from_image;
2311178e 3113
02513cdd 3114 /* Say that we haven't consumed the characters with
5f5c8ee5
GM
3115 `display' property yet. The call to pop_it in
3116 set_iterator_to_next will clean this up. */
3117 *position = start_pos;
3118 }
3119#endif /* HAVE_WINDOW_SYSTEM */
3120 }
a21a3943
GM
3121 else
3122 /* Invalid property or property not supported. Restore
3123 the position to what it was before. */
3124 *position = start_pos;
5f5c8ee5
GM
3125 }
3126
a61b7058 3127 return replaces_text_display_p;
5f5c8ee5
GM
3128}
3129
3130
06568bbf
GM
3131/* Check if PROP is a display sub-property value whose text should be
3132 treated as intangible. */
3133
3134static int
3135single_display_prop_intangible_p (prop)
3136 Lisp_Object prop;
3137{
3138 /* Skip over `when FORM'. */
3139 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3140 {
3141 prop = XCDR (prop);
3142 if (!CONSP (prop))
3143 return 0;
3144 prop = XCDR (prop);
3145 }
3146
959bc044
SM
3147 if (STRINGP (prop))
3148 return 1;
3149
06568bbf
GM
3150 if (!CONSP (prop))
3151 return 0;
3152
3153 /* Skip over `margin LOCATION'. If LOCATION is in the margins,
3154 we don't need to treat text as intangible. */
3155 if (EQ (XCAR (prop), Qmargin))
3156 {
3157 prop = XCDR (prop);
3158 if (!CONSP (prop))
3159 return 0;
3160
3161 prop = XCDR (prop);
3162 if (!CONSP (prop)
3163 || EQ (XCAR (prop), Qleft_margin)
3164 || EQ (XCAR (prop), Qright_margin))
3165 return 0;
3166 }
2311178e 3167
06568bbf
GM
3168 return CONSP (prop) && EQ (XCAR (prop), Qimage);
3169}
3170
3171
3172/* Check if PROP is a display property value whose text should be
3173 treated as intangible. */
3174
3175int
3176display_prop_intangible_p (prop)
3177 Lisp_Object prop;
3178{
3179 if (CONSP (prop)
3180 && CONSP (XCAR (prop))
3181 && !EQ (Qmargin, XCAR (XCAR (prop))))
3182 {
3183 /* A list of sub-properties. */
3184 while (CONSP (prop))
3185 {
3186 if (single_display_prop_intangible_p (XCAR (prop)))
3187 return 1;
3188 prop = XCDR (prop);
3189 }
3190 }
3191 else if (VECTORP (prop))
3192 {
3193 /* A vector of sub-properties. */
3194 int i;
a61b7058
GM
3195 for (i = 0; i < ASIZE (prop); ++i)
3196 if (single_display_prop_intangible_p (AREF (prop, i)))
06568bbf
GM
3197 return 1;
3198 }
3199 else
3200 return single_display_prop_intangible_p (prop);
3201
3202 return 0;
3203}
3204
74bd6d65
GM
3205
3206/* Return 1 if PROP is a display sub-property value containing STRING. */
3207
3208static int
3209single_display_prop_string_p (prop, string)
3210 Lisp_Object prop, string;
3211{
74bd6d65
GM
3212 if (EQ (string, prop))
3213 return 1;
2311178e 3214
74bd6d65
GM
3215 /* Skip over `when FORM'. */
3216 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3217 {
3218 prop = XCDR (prop);
3219 if (!CONSP (prop))
3220 return 0;
3221 prop = XCDR (prop);
3222 }
3223
3224 if (CONSP (prop))
3225 /* Skip over `margin LOCATION'. */
3226 if (EQ (XCAR (prop), Qmargin))
3227 {
3228 prop = XCDR (prop);
3229 if (!CONSP (prop))
3230 return 0;
3231
3232 prop = XCDR (prop);
3233 if (!CONSP (prop))
3234 return 0;
3235 }
2311178e 3236
74bd6d65
GM
3237 return CONSP (prop) && EQ (XCAR (prop), string);
3238}
3239
3240
3241/* Return 1 if STRING appears in the `display' property PROP. */
3242
3243static int
3244display_prop_string_p (prop, string)
3245 Lisp_Object prop, string;
3246{
74bd6d65
GM
3247 if (CONSP (prop)
3248 && CONSP (XCAR (prop))
3249 && !EQ (Qmargin, XCAR (XCAR (prop))))
3250 {
3251 /* A list of sub-properties. */
3252 while (CONSP (prop))
3253 {
3254 if (single_display_prop_string_p (XCAR (prop), string))
3255 return 1;
3256 prop = XCDR (prop);
3257 }
3258 }
3259 else if (VECTORP (prop))
3260 {
3261 /* A vector of sub-properties. */
3262 int i;
3263 for (i = 0; i < ASIZE (prop); ++i)
3264 if (single_display_prop_string_p (AREF (prop, i), string))
3265 return 1;
3266 }
3267 else
3268 return single_display_prop_string_p (prop, string);
3269
3270 return 0;
3271}
3272
3273
3274/* Determine from which buffer position in W's buffer STRING comes
3275 from. AROUND_CHARPOS is an approximate position where it could
3276 be from. Value is the buffer position or 0 if it couldn't be
3277 determined.
3278
3279 W's buffer must be current.
3280
3281 This function is necessary because we don't record buffer positions
3282 in glyphs generated from strings (to keep struct glyph small).
3283 This function may only use code that doesn't eval because it is
3284 called asynchronously from note_mouse_highlight. */
3285
3286int
3287string_buffer_position (w, string, around_charpos)
3288 struct window *w;
3289 Lisp_Object string;
3290 int around_charpos;
3291{
74bd6d65
GM
3292 Lisp_Object limit, prop, pos;
3293 const int MAX_DISTANCE = 1000;
3294 int found = 0;
3295
d8731202 3296 pos = make_number (around_charpos);
74bd6d65
GM
3297 limit = make_number (min (XINT (pos) + MAX_DISTANCE, ZV));
3298 while (!found && !EQ (pos, limit))
3299 {
3300 prop = Fget_char_property (pos, Qdisplay, Qnil);
3301 if (!NILP (prop) && display_prop_string_p (prop, string))
3302 found = 1;
3303 else
134d9283 3304 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil, limit);
74bd6d65
GM
3305 }
3306
3307 if (!found)
3308 {
d8731202 3309 pos = make_number (around_charpos);
74bd6d65
GM
3310 limit = make_number (max (XINT (pos) - MAX_DISTANCE, BEGV));
3311 while (!found && !EQ (pos, limit))
3312 {
3313 prop = Fget_char_property (pos, Qdisplay, Qnil);
3314 if (!NILP (prop) && display_prop_string_p (prop, string))
3315 found = 1;
3316 else
134d9283
GM
3317 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
3318 limit);
74bd6d65
GM
3319 }
3320 }
3321
3322 return found ? XINT (pos) : 0;
3323}
3324
3325
5f5c8ee5 3326\f
260a86a0
KH
3327/***********************************************************************
3328 `composition' property
3329 ***********************************************************************/
3330
3331/* Set up iterator IT from `composition' property at its current
3332 position. Called from handle_stop. */
3333
3334static enum prop_handled
3335handle_composition_prop (it)
3336 struct it *it;
3337{
3338 Lisp_Object prop, string;
3339 int pos, pos_byte, end;
3340 enum prop_handled handled = HANDLED_NORMALLY;
3341
3342 if (STRINGP (it->string))
3343 {
3344 pos = IT_STRING_CHARPOS (*it);
3345 pos_byte = IT_STRING_BYTEPOS (*it);
3346 string = it->string;
3347 }
3348 else
3349 {
3350 pos = IT_CHARPOS (*it);
3351 pos_byte = IT_BYTEPOS (*it);
3352 string = Qnil;
3353 }
3354
3355 /* If there's a valid composition and point is not inside of the
3356 composition (in the case that the composition is from the current
3357 buffer), draw a glyph composed from the composition components. */
3358 if (find_composition (pos, -1, &pos, &end, &prop, string)
3359 && COMPOSITION_VALID_P (pos, end, prop)
3360 && (STRINGP (it->string) || (PT <= pos || PT >= end)))
3361 {
3362 int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
3363
3364 if (id >= 0)
3365 {
3366 it->method = next_element_from_composition;
3367 it->cmp_id = id;
3368 it->cmp_len = COMPOSITION_LENGTH (prop);
3369 /* For a terminal, draw only the first character of the
3370 components. */
3371 it->c = COMPOSITION_GLYPH (composition_table[id], 0);
3372 it->len = (STRINGP (it->string)
3373 ? string_char_to_byte (it->string, end)
3374 : CHAR_TO_BYTE (end)) - pos_byte;
3375 it->stop_charpos = end;
3376 handled = HANDLED_RETURN;
3377 }
3378 }
3379
3380 return handled;
3381}
3382
3383
3384\f
5f5c8ee5
GM
3385/***********************************************************************
3386 Overlay strings
3387 ***********************************************************************/
3388
3389/* The following structure is used to record overlay strings for
3390 later sorting in load_overlay_strings. */
3391
3392struct overlay_entry
3393{
2970b9be 3394 Lisp_Object overlay;
5f5c8ee5
GM
3395 Lisp_Object string;
3396 int priority;
3397 int after_string_p;
3398};
3399
3400
3401/* Set up iterator IT from overlay strings at its current position.
3402 Called from handle_stop. */
3403
3404static enum prop_handled
3405handle_overlay_change (it)
3406 struct it *it;
3407{
5a08cbaf 3408 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
2970b9be 3409 return HANDLED_RECOMPUTE_PROPS;
5f5c8ee5 3410 else
2970b9be 3411 return HANDLED_NORMALLY;
5f5c8ee5
GM
3412}
3413
3414
3415/* Set up the next overlay string for delivery by IT, if there is an
3416 overlay string to deliver. Called by set_iterator_to_next when the
3417 end of the current overlay string is reached. If there are more
3418 overlay strings to display, IT->string and
3419 IT->current.overlay_string_index are set appropriately here.
3420 Otherwise IT->string is set to nil. */
2311178e 3421
5f5c8ee5
GM
3422static void
3423next_overlay_string (it)
3424 struct it *it;
3425{
3426 ++it->current.overlay_string_index;
3427 if (it->current.overlay_string_index == it->n_overlay_strings)
3428 {
3429 /* No more overlay strings. Restore IT's settings to what
3430 they were before overlay strings were processed, and
3431 continue to deliver from current_buffer. */
5a08cbaf 3432 int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
2311178e 3433
5f5c8ee5
GM
3434 pop_it (it);
3435 xassert (it->stop_charpos >= BEGV
3436 && it->stop_charpos <= it->end_charpos);
3437 it->string = Qnil;
3438 it->current.overlay_string_index = -1;
3439 SET_TEXT_POS (it->current.string_pos, -1, -1);
3440 it->n_overlay_strings = 0;
3441 it->method = next_element_from_buffer;
2970b9be
GM
3442
3443 /* If we're at the end of the buffer, record that we have
3444 processed the overlay strings there already, so that
3445 next_element_from_buffer doesn't try it again. */
3446 if (IT_CHARPOS (*it) >= it->end_charpos)
3447 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf
GM
3448
3449 /* If we have to display `...' for invisible text, set
3450 the iterator up for that. */
3451 if (display_ellipsis_p)
3452 setup_for_ellipsis (it);
5f5c8ee5
GM
3453 }
3454 else
3455 {
3456 /* There are more overlay strings to process. If
3457 IT->current.overlay_string_index has advanced to a position
3458 where we must load IT->overlay_strings with more strings, do
3459 it. */
3460 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2311178e 3461
5f5c8ee5 3462 if (it->current.overlay_string_index && i == 0)
5a08cbaf 3463 load_overlay_strings (it, 0);
5f5c8ee5
GM
3464
3465 /* Initialize IT to deliver display elements from the overlay
3466 string. */
3467 it->string = it->overlay_strings[i];
3468 it->multibyte_p = STRING_MULTIBYTE (it->string);
3469 SET_TEXT_POS (it->current.string_pos, 0, 0);
3470 it->method = next_element_from_string;
3471 it->stop_charpos = 0;
3472 }
2311178e 3473
5f5c8ee5
GM
3474 CHECK_IT (it);
3475}
3476
3477
3478/* Compare two overlay_entry structures E1 and E2. Used as a
3479 comparison function for qsort in load_overlay_strings. Overlay
3480 strings for the same position are sorted so that
3481
2970b9be
GM
3482 1. All after-strings come in front of before-strings, except
3483 when they come from the same overlay.
2311178e 3484
5f5c8ee5
GM
3485 2. Within after-strings, strings are sorted so that overlay strings
3486 from overlays with higher priorities come first.
3487
3488 2. Within before-strings, strings are sorted so that overlay
3489 strings from overlays with higher priorities come last.
3490
3491 Value is analogous to strcmp. */
3492
2311178e 3493
5f5c8ee5
GM
3494static int
3495compare_overlay_entries (e1, e2)
3496 void *e1, *e2;
3497{
3498 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
3499 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
3500 int result;
3501
3502 if (entry1->after_string_p != entry2->after_string_p)
2970b9be
GM
3503 {
3504 /* Let after-strings appear in front of before-strings if
3505 they come from different overlays. */
3506 if (EQ (entry1->overlay, entry2->overlay))
3507 result = entry1->after_string_p ? 1 : -1;
3508 else
3509 result = entry1->after_string_p ? -1 : 1;
3510 }
5f5c8ee5
GM
3511 else if (entry1->after_string_p)
3512 /* After-strings sorted in order of decreasing priority. */
3513 result = entry2->priority - entry1->priority;
3514 else
3515 /* Before-strings sorted in order of increasing priority. */
3516 result = entry1->priority - entry2->priority;
3517
3518 return result;
3519}
3520
3521
3522/* Load the vector IT->overlay_strings with overlay strings from IT's
5a08cbaf
GM
3523 current buffer position, or from CHARPOS if that is > 0. Set
3524 IT->n_overlays to the total number of overlay strings found.
5f5c8ee5
GM
3525
3526 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
3527 a time. On entry into load_overlay_strings,
3528 IT->current.overlay_string_index gives the number of overlay
3529 strings that have already been loaded by previous calls to this
3530 function.
3531
2970b9be
GM
3532 IT->add_overlay_start contains an additional overlay start
3533 position to consider for taking overlay strings from, if non-zero.
3534 This position comes into play when the overlay has an `invisible'
3535 property, and both before and after-strings. When we've skipped to
3536 the end of the overlay, because of its `invisible' property, we
3537 nevertheless want its before-string to appear.
3538 IT->add_overlay_start will contain the overlay start position
3539 in this case.
3540
5f5c8ee5
GM
3541 Overlay strings are sorted so that after-string strings come in
3542 front of before-string strings. Within before and after-strings,
3543 strings are sorted by overlay priority. See also function
3544 compare_overlay_entries. */
2311178e 3545
5f5c8ee5 3546static void
5a08cbaf 3547load_overlay_strings (it, charpos)
5f5c8ee5 3548 struct it *it;
5a08cbaf 3549 int charpos;
5f5c8ee5
GM
3550{
3551 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
cafafe0b 3552 Lisp_Object ov, overlay, window, str, invisible;
5f5c8ee5
GM
3553 int start, end;
3554 int size = 20;
cafafe0b 3555 int n = 0, i, j, invis_p;
5f5c8ee5
GM
3556 struct overlay_entry *entries
3557 = (struct overlay_entry *) alloca (size * sizeof *entries);
5a08cbaf
GM
3558
3559 if (charpos <= 0)
3560 charpos = IT_CHARPOS (*it);
5f5c8ee5
GM
3561
3562 /* Append the overlay string STRING of overlay OVERLAY to vector
3563 `entries' which has size `size' and currently contains `n'
3564 elements. AFTER_P non-zero means STRING is an after-string of
3565 OVERLAY. */
3566#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
3567 do \
3568 { \
3569 Lisp_Object priority; \
3570 \
3571 if (n == size) \
3572 { \
3573 int new_size = 2 * size; \
3574 struct overlay_entry *old = entries; \
3575 entries = \
3576 (struct overlay_entry *) alloca (new_size \
3577 * sizeof *entries); \
3578 bcopy (old, entries, size * sizeof *entries); \
3579 size = new_size; \
3580 } \
3581 \
3582 entries[n].string = (STRING); \
2970b9be 3583 entries[n].overlay = (OVERLAY); \
5f5c8ee5 3584 priority = Foverlay_get ((OVERLAY), Qpriority); \
2970b9be 3585 entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0; \
5f5c8ee5
GM
3586 entries[n].after_string_p = (AFTER_P); \
3587 ++n; \
3588 } \
3589 while (0)
3590
3591 /* Process overlay before the overlay center. */
2970b9be 3592 for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
5f5c8ee5 3593 {
9472f927 3594 overlay = XCAR (ov);
5f5c8ee5
GM
3595 xassert (OVERLAYP (overlay));
3596 start = OVERLAY_POSITION (OVERLAY_START (overlay));
3597 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2311178e 3598
cafafe0b 3599 if (end < charpos)
5f5c8ee5
GM
3600 break;
3601
3602 /* Skip this overlay if it doesn't start or end at IT's current
3603 position. */
cafafe0b 3604 if (end != charpos && start != charpos)
5f5c8ee5 3605 continue;
2311178e 3606
5f5c8ee5
GM
3607 /* Skip this overlay if it doesn't apply to IT->w. */
3608 window = Foverlay_get (overlay, Qwindow);
3609 if (WINDOWP (window) && XWINDOW (window) != it->w)
3610 continue;
3611
cafafe0b
GM
3612 /* If the text ``under'' the overlay is invisible, both before-
3613 and after-strings from this overlay are visible; start and
3614 end position are indistinguishable. */
3615 invisible = Foverlay_get (overlay, Qinvisible);
3616 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
3617
5f5c8ee5 3618 /* If overlay has a non-empty before-string, record it. */
cafafe0b 3619 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 3620 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 3621 && SCHARS (str))
5f5c8ee5 3622 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 3623
5f5c8ee5 3624 /* If overlay has a non-empty after-string, record it. */
cafafe0b 3625 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 3626 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 3627 && SCHARS (str))
5f5c8ee5
GM
3628 RECORD_OVERLAY_STRING (overlay, str, 1);
3629 }
2311178e 3630
5f5c8ee5 3631 /* Process overlays after the overlay center. */
2970b9be 3632 for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
5f5c8ee5 3633 {
9472f927 3634 overlay = XCAR (ov);
5f5c8ee5
GM
3635 xassert (OVERLAYP (overlay));
3636 start = OVERLAY_POSITION (OVERLAY_START (overlay));
3637 end = OVERLAY_POSITION (OVERLAY_END (overlay));
3638
cafafe0b 3639 if (start > charpos)
5f5c8ee5 3640 break;
2311178e 3641
5f5c8ee5
GM
3642 /* Skip this overlay if it doesn't start or end at IT's current
3643 position. */
cafafe0b 3644 if (end != charpos && start != charpos)
5f5c8ee5
GM
3645 continue;
3646
3647 /* Skip this overlay if it doesn't apply to IT->w. */
3648 window = Foverlay_get (overlay, Qwindow);
3649 if (WINDOWP (window) && XWINDOW (window) != it->w)
3650 continue;
2311178e 3651
cafafe0b
GM
3652 /* If the text ``under'' the overlay is invisible, it has a zero
3653 dimension, and both before- and after-strings apply. */
3654 invisible = Foverlay_get (overlay, Qinvisible);
3655 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
3656
5f5c8ee5 3657 /* If overlay has a non-empty before-string, record it. */
cafafe0b 3658 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 3659 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 3660 && SCHARS (str))
5f5c8ee5 3661 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 3662
5f5c8ee5 3663 /* If overlay has a non-empty after-string, record it. */
cafafe0b 3664 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 3665 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 3666 && SCHARS (str))
5f5c8ee5
GM
3667 RECORD_OVERLAY_STRING (overlay, str, 1);
3668 }
3669
3670#undef RECORD_OVERLAY_STRING
2311178e 3671
5f5c8ee5 3672 /* Sort entries. */
cafafe0b 3673 if (n > 1)
2970b9be 3674 qsort (entries, n, sizeof *entries, compare_overlay_entries);
5f5c8ee5
GM
3675
3676 /* Record the total number of strings to process. */
3677 it->n_overlay_strings = n;
3678
3679 /* IT->current.overlay_string_index is the number of overlay strings
3680 that have already been consumed by IT. Copy some of the
3681 remaining overlay strings to IT->overlay_strings. */
3682 i = 0;
3683 j = it->current.overlay_string_index;
3684 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
3685 it->overlay_strings[i++] = entries[j++].string;
2970b9be 3686
5f5c8ee5
GM
3687 CHECK_IT (it);
3688}
3689
3690
3691/* Get the first chunk of overlay strings at IT's current buffer
5a08cbaf
GM
3692 position, or at CHARPOS if that is > 0. Value is non-zero if at
3693 least one overlay string was found. */
5f5c8ee5
GM
3694
3695static int
5a08cbaf 3696get_overlay_strings (it, charpos)
5f5c8ee5 3697 struct it *it;
5a08cbaf 3698 int charpos;
5f5c8ee5
GM
3699{
3700 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
3701 process. This fills IT->overlay_strings with strings, and sets
3702 IT->n_overlay_strings to the total number of strings to process.
3703 IT->pos.overlay_string_index has to be set temporarily to zero
3704 because load_overlay_strings needs this; it must be set to -1
3705 when no overlay strings are found because a zero value would
3706 indicate a position in the first overlay string. */
3707 it->current.overlay_string_index = 0;
5a08cbaf 3708 load_overlay_strings (it, charpos);
5f5c8ee5
GM
3709
3710 /* If we found overlay strings, set up IT to deliver display
3711 elements from the first one. Otherwise set up IT to deliver
3712 from current_buffer. */
3713 if (it->n_overlay_strings)
3714 {
3715 /* Make sure we know settings in current_buffer, so that we can
3716 restore meaningful values when we're done with the overlay
3717 strings. */
3718 compute_stop_pos (it);
3719 xassert (it->face_id >= 0);
2311178e 3720
5f5c8ee5
GM
3721 /* Save IT's settings. They are restored after all overlay
3722 strings have been processed. */
3723 xassert (it->sp == 0);
3724 push_it (it);
3725
3726 /* Set up IT to deliver display elements from the first overlay
3727 string. */
3728 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
5f5c8ee5 3729 it->string = it->overlay_strings[0];
b2046df8 3730 it->stop_charpos = 0;
5f5c8ee5 3731 xassert (STRINGP (it->string));
2051c264 3732 it->end_charpos = SCHARS (it->string);
d5db4077 3733 it->multibyte_p = STRING_MULTIBYTE (it->string);
5f5c8ee5
GM
3734 it->method = next_element_from_string;
3735 }
3736 else
3737 {
3738 it->string = Qnil;
3739 it->current.overlay_string_index = -1;
3740 it->method = next_element_from_buffer;
3741 }
3742
3743 CHECK_IT (it);
3744
3745 /* Value is non-zero if we found at least one overlay string. */
3746 return STRINGP (it->string);
3747}
3748
3749
3750\f
3751/***********************************************************************
3752 Saving and restoring state
3753 ***********************************************************************/
3754
3755/* Save current settings of IT on IT->stack. Called, for example,
3756 before setting up IT for an overlay string, to be able to restore
3757 IT's settings to what they were after the overlay string has been
3758 processed. */
3759
3760static void
3761push_it (it)
3762 struct it *it;
3763{
3764 struct iterator_stack_entry *p;
2311178e 3765
5f5c8ee5
GM
3766 xassert (it->sp < 2);
3767 p = it->stack + it->sp;
3768
3769 p->stop_charpos = it->stop_charpos;
3770 xassert (it->face_id >= 0);
3771 p->face_id = it->face_id;
3772 p->string = it->string;
3773 p->pos = it->current;
3774 p->end_charpos = it->end_charpos;
3775 p->string_nchars = it->string_nchars;
3776 p->area = it->area;
3777 p->multibyte_p = it->multibyte_p;
3778 p->space_width = it->space_width;
3779 p->font_height = it->font_height;
3780 p->voffset = it->voffset;
3781 p->string_from_display_prop_p = it->string_from_display_prop_p;
5a08cbaf 3782 p->display_ellipsis_p = 0;
5f5c8ee5
GM
3783 ++it->sp;
3784}
3785
3786
3787/* Restore IT's settings from IT->stack. Called, for example, when no
3788 more overlay strings must be processed, and we return to delivering
3789 display elements from a buffer, or when the end of a string from a
3790 `display' property is reached and we return to delivering display
3791 elements from an overlay string, or from a buffer. */
3792
3793static void
3794pop_it (it)
3795 struct it *it;
3796{
3797 struct iterator_stack_entry *p;
2311178e 3798
5f5c8ee5
GM
3799 xassert (it->sp > 0);
3800 --it->sp;
3801 p = it->stack + it->sp;
3802 it->stop_charpos = p->stop_charpos;
3803 it->face_id = p->face_id;
3804 it->string = p->string;
3805 it->current = p->pos;
3806 it->end_charpos = p->end_charpos;
3807 it->string_nchars = p->string_nchars;
3808 it->area = p->area;
3809 it->multibyte_p = p->multibyte_p;
3810 it->space_width = p->space_width;
3811 it->font_height = p->font_height;
3812 it->voffset = p->voffset;
3813 it->string_from_display_prop_p = p->string_from_display_prop_p;
3814}
3815
3816
3817\f
3818/***********************************************************************
3819 Moving over lines
3820 ***********************************************************************/
3821
3822/* Set IT's current position to the previous line start. */
3823
3824static void
3825back_to_previous_line_start (it)
3826 struct it *it;
3827{
3828 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
3829 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3830}
3831
3832
cafafe0b 3833/* Move IT to the next line start.
2311178e 3834
cafafe0b
GM
3835 Value is non-zero if a newline was found. Set *SKIPPED_P to 1 if
3836 we skipped over part of the text (as opposed to moving the iterator
3837 continuously over the text). Otherwise, don't change the value
3838 of *SKIPPED_P.
2311178e 3839
cafafe0b
GM
3840 Newlines may come from buffer text, overlay strings, or strings
3841 displayed via the `display' property. That's the reason we can't
0fd37545
GM
3842 simply use find_next_newline_no_quit.
3843
3844 Note that this function may not skip over invisible text that is so
3845 because of text properties and immediately follows a newline. If
3846 it would, function reseat_at_next_visible_line_start, when called
3847 from set_iterator_to_next, would effectively make invisible
3848 characters following a newline part of the wrong glyph row, which
3849 leads to wrong cursor motion. */
5f5c8ee5 3850
cafafe0b
GM
3851static int
3852forward_to_next_line_start (it, skipped_p)
5f5c8ee5 3853 struct it *it;
cafafe0b 3854 int *skipped_p;
5f5c8ee5 3855{
54918e2b 3856 int old_selective, newline_found_p, n;
cafafe0b
GM
3857 const int MAX_NEWLINE_DISTANCE = 500;
3858
0fd37545
GM
3859 /* If already on a newline, just consume it to avoid unintended
3860 skipping over invisible text below. */
51695746
GM
3861 if (it->what == IT_CHARACTER
3862 && it->c == '\n'
3863 && CHARPOS (it->position) == IT_CHARPOS (*it))
0fd37545
GM
3864 {
3865 set_iterator_to_next (it, 0);
a77dc1ec 3866 it->c = 0;
0fd37545
GM
3867 return 1;
3868 }
3869
54918e2b 3870 /* Don't handle selective display in the following. It's (a)
0fd37545
GM
3871 unnecessary because it's done by the caller, and (b) leads to an
3872 infinite recursion because next_element_from_ellipsis indirectly
3873 calls this function. */
54918e2b
GM
3874 old_selective = it->selective;
3875 it->selective = 0;
3876
cafafe0b
GM
3877 /* Scan for a newline within MAX_NEWLINE_DISTANCE display elements
3878 from buffer text. */
3aec8722
GM
3879 for (n = newline_found_p = 0;
3880 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
3881 n += STRINGP (it->string) ? 0 : 1)
cafafe0b 3882 {
8692ca92 3883 if (!get_next_display_element (it))
d43be70c 3884 return 0;
d02f1cb8 3885 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
cafafe0b 3886 set_iterator_to_next (it, 0);
cafafe0b
GM
3887 }
3888
3889 /* If we didn't find a newline near enough, see if we can use a
3890 short-cut. */
db0bb807 3891 if (!newline_found_p)
cafafe0b
GM
3892 {
3893 int start = IT_CHARPOS (*it);
3894 int limit = find_next_newline_no_quit (start, 1);
3895 Lisp_Object pos;
3896
3897 xassert (!STRINGP (it->string));
3898
3899 /* If there isn't any `display' property in sight, and no
3900 overlays, we can just use the position of the newline in
3901 buffer text. */
3902 if (it->stop_charpos >= limit
3903 || ((pos = Fnext_single_property_change (make_number (start),
3904 Qdisplay,
3905 Qnil, make_number (limit)),
3906 NILP (pos))
3907 && next_overlay_change (start) == ZV))
3908 {
3909 IT_CHARPOS (*it) = limit;
3910 IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
3911 *skipped_p = newline_found_p = 1;
3912 }
3913 else
3914 {
3915 while (get_next_display_element (it)
3916 && !newline_found_p)
3917 {
3918 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
3919 set_iterator_to_next (it, 0);
3920 }
3921 }
3922 }
3923
54918e2b 3924 it->selective = old_selective;
cafafe0b 3925 return newline_found_p;
5f5c8ee5
GM
3926}
3927
3928
3929/* Set IT's current position to the previous visible line start. Skip
3930 invisible text that is so either due to text properties or due to
3931 selective display. Caution: this does not change IT->current_x and
3932 IT->hpos. */
3933
3934static void
3935back_to_previous_visible_line_start (it)
3936 struct it *it;
3937{
3938 int visible_p = 0;
3939
3940 /* Go back one newline if not on BEGV already. */
3941 if (IT_CHARPOS (*it) > BEGV)
3942 back_to_previous_line_start (it);
3943
3944 /* Move over lines that are invisible because of selective display
3945 or text properties. */
3946 while (IT_CHARPOS (*it) > BEGV
3947 && !visible_p)
3948 {
3949 visible_p = 1;
3950
3951 /* If selective > 0, then lines indented more than that values
3952 are invisible. */
3953 if (it->selective > 0
3954 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 3955 (double) it->selective)) /* iftc */
5f5c8ee5 3956 visible_p = 0;
2311178e 3957 else
5f5c8ee5
GM
3958 {
3959 Lisp_Object prop;
3960
6fc556fd
KR
3961 prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
3962 Qinvisible, it->window);
5f5c8ee5
GM
3963 if (TEXT_PROP_MEANS_INVISIBLE (prop))
3964 visible_p = 0;
3965 }
5f5c8ee5
GM
3966
3967 /* Back one more newline if the current one is invisible. */
3968 if (!visible_p)
3969 back_to_previous_line_start (it);
3970 }
3971
3972 xassert (IT_CHARPOS (*it) >= BEGV);
3973 xassert (IT_CHARPOS (*it) == BEGV
3974 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3975 CHECK_IT (it);
3976}
3977
3978
3979/* Reseat iterator IT at the previous visible line start. Skip
3980 invisible text that is so either due to text properties or due to
3981 selective display. At the end, update IT's overlay information,
3982 face information etc. */
3983
3984static void
3985reseat_at_previous_visible_line_start (it)
3986 struct it *it;
3987{
3988 back_to_previous_visible_line_start (it);
3989 reseat (it, it->current.pos, 1);
3990 CHECK_IT (it);
3991}
3992
3993
3994/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
3995 buffer. ON_NEWLINE_P non-zero means position IT on the newline
3996 preceding the line start. Skip over invisible text that is so
3997 because of selective display. Compute faces, overlays etc at the
3998 new position. Note that this function does not skip over text that
3999 is invisible because of text properties. */
5f5c8ee5
GM
4000
4001static void
312246d1 4002reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 4003 struct it *it;
312246d1 4004 int on_newline_p;
5f5c8ee5 4005{
cafafe0b
GM
4006 int newline_found_p, skipped_p = 0;
4007
4008 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4009
4010 /* Skip over lines that are invisible because they are indented
4011 more than the value of IT->selective. */
4012 if (it->selective > 0)
4013 while (IT_CHARPOS (*it) < ZV
a77dc1ec 4014 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 4015 (double) it->selective)) /* iftc */
a77dc1ec
GM
4016 {
4017 xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
4018 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4019 }
cafafe0b
GM
4020
4021 /* Position on the newline if that's what's requested. */
4022 if (on_newline_p && newline_found_p)
5f5c8ee5 4023 {
cafafe0b 4024 if (STRINGP (it->string))
5f5c8ee5 4025 {
cafafe0b
GM
4026 if (IT_STRING_CHARPOS (*it) > 0)
4027 {
4028 --IT_STRING_CHARPOS (*it);
4029 --IT_STRING_BYTEPOS (*it);
4030 }
5f5c8ee5 4031 }
cafafe0b 4032 else if (IT_CHARPOS (*it) > BEGV)
312246d1
GM
4033 {
4034 --IT_CHARPOS (*it);
cafafe0b
GM
4035 --IT_BYTEPOS (*it);
4036 reseat (it, it->current.pos, 0);
312246d1 4037 }
5f5c8ee5 4038 }
cafafe0b
GM
4039 else if (skipped_p)
4040 reseat (it, it->current.pos, 0);
2311178e 4041
5f5c8ee5
GM
4042 CHECK_IT (it);
4043}
4044
4045
4046\f
4047/***********************************************************************
4048 Changing an iterator's position
4049***********************************************************************/
4050
4051/* Change IT's current position to POS in current_buffer. If FORCE_P
4052 is non-zero, always check for text properties at the new position.
4053 Otherwise, text properties are only looked up if POS >=
4054 IT->check_charpos of a property. */
4055
4056static void
4057reseat (it, pos, force_p)
4058 struct it *it;
4059 struct text_pos pos;
4060 int force_p;
4061{
4062 int original_pos = IT_CHARPOS (*it);
4063
4064 reseat_1 (it, pos, 0);
4065
4066 /* Determine where to check text properties. Avoid doing it
4067 where possible because text property lookup is very expensive. */
4068 if (force_p
4069 || CHARPOS (pos) > it->stop_charpos
4070 || CHARPOS (pos) < original_pos)
4071 handle_stop (it);
4072
4073 CHECK_IT (it);
4074}
4075
4076
4077/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
4078 IT->stop_pos to POS, also. */
4079
4080static void
4081reseat_1 (it, pos, set_stop_p)
4082 struct it *it;
4083 struct text_pos pos;
4084 int set_stop_p;
4085{
4086 /* Don't call this function when scanning a C string. */
4087 xassert (it->s == NULL);
4088
4089 /* POS must be a reasonable value. */
4090 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
4091
4092 it->current.pos = it->position = pos;
4093 XSETBUFFER (it->object, current_buffer);
78c663d8 4094 it->end_charpos = ZV;
5f5c8ee5
GM
4095 it->dpvec = NULL;
4096 it->current.dpvec_index = -1;
4097 it->current.overlay_string_index = -1;
4098 IT_STRING_CHARPOS (*it) = -1;
4099 IT_STRING_BYTEPOS (*it) = -1;
4100 it->string = Qnil;
4101 it->method = next_element_from_buffer;
06fd3792 4102 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
5f5c8ee5 4103 it->sp = 0;
4aad61f8 4104 it->face_before_selective_p = 0;
5f5c8ee5
GM
4105
4106 if (set_stop_p)
4107 it->stop_charpos = CHARPOS (pos);
4108}
4109
4110
4111/* Set up IT for displaying a string, starting at CHARPOS in window W.
4112 If S is non-null, it is a C string to iterate over. Otherwise,
4113 STRING gives a Lisp string to iterate over.
2311178e 4114
5f5c8ee5
GM
4115 If PRECISION > 0, don't return more then PRECISION number of
4116 characters from the string.
4117
4118 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
4119 characters have been returned. FIELD_WIDTH < 0 means an infinite
4120 field width.
4121
4122 MULTIBYTE = 0 means disable processing of multibyte characters,
4123 MULTIBYTE > 0 means enable it,
4124 MULTIBYTE < 0 means use IT->multibyte_p.
4125
4126 IT must be initialized via a prior call to init_iterator before
4127 calling this function. */
4128
4129static void
4130reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
4131 struct it *it;
4132 unsigned char *s;
4133 Lisp_Object string;
4134 int charpos;
4135 int precision, field_width, multibyte;
4136{
4137 /* No region in strings. */
4138 it->region_beg_charpos = it->region_end_charpos = -1;
4139
4140 /* No text property checks performed by default, but see below. */
4141 it->stop_charpos = -1;
4142
4143 /* Set iterator position and end position. */
4144 bzero (&it->current, sizeof it->current);
4145 it->current.overlay_string_index = -1;
4146 it->current.dpvec_index = -1;
5f5c8ee5 4147 xassert (charpos >= 0);
2311178e 4148
e719f5ae
GM
4149 /* If STRING is specified, use its multibyteness, otherwise use the
4150 setting of MULTIBYTE, if specified. */
cabf45da 4151 if (multibyte >= 0)
5f5c8ee5 4152 it->multibyte_p = multibyte > 0;
2311178e 4153
5f5c8ee5
GM
4154 if (s == NULL)
4155 {
4156 xassert (STRINGP (string));
4157 it->string = string;
4158 it->s = NULL;
2051c264 4159 it->end_charpos = it->string_nchars = SCHARS (string);
5f5c8ee5
GM
4160 it->method = next_element_from_string;
4161 it->current.string_pos = string_pos (charpos, string);
4162 }
4163 else
4164 {
4165 it->s = s;
4166 it->string = Qnil;
4167
4168 /* Note that we use IT->current.pos, not it->current.string_pos,
4169 for displaying C strings. */
4170 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
4171 if (it->multibyte_p)
4172 {
4173 it->current.pos = c_string_pos (charpos, s, 1);
4174 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
4175 }
4176 else
4177 {
4178 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
4179 it->end_charpos = it->string_nchars = strlen (s);
4180 }
2311178e 4181
5f5c8ee5
GM
4182 it->method = next_element_from_c_string;
4183 }
4184
4185 /* PRECISION > 0 means don't return more than PRECISION characters
4186 from the string. */
4187 if (precision > 0 && it->end_charpos - charpos > precision)
4188 it->end_charpos = it->string_nchars = charpos + precision;
4189
4190 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
4191 characters have been returned. FIELD_WIDTH == 0 means don't pad,
4192 FIELD_WIDTH < 0 means infinite field width. This is useful for
4193 padding with `-' at the end of a mode line. */
4194 if (field_width < 0)
4195 field_width = INFINITY;
4196 if (field_width > it->end_charpos - charpos)
4197 it->end_charpos = charpos + field_width;
4198
4199 /* Use the standard display table for displaying strings. */
4200 if (DISP_TABLE_P (Vstandard_display_table))
4201 it->dp = XCHAR_TABLE (Vstandard_display_table);
4202
4203 it->stop_charpos = charpos;
4204 CHECK_IT (it);
4205}
4206
4207
4208\f
4209/***********************************************************************
4210 Iteration
4211 ***********************************************************************/
4212
4213/* Load IT's display element fields with information about the next
4214 display element from the current position of IT. Value is zero if
4215 end of buffer (or C string) is reached. */
4216
4217int
4218get_next_display_element (it)
4219 struct it *it;
4220{
7d0393cf 4221 /* Non-zero means that we found a display element. Zero means that
5f5c8ee5
GM
4222 we hit the end of what we iterate over. Performance note: the
4223 function pointer `method' used here turns out to be faster than
4224 using a sequence of if-statements. */
4225 int success_p = (*it->method) (it);
5f5c8ee5
GM
4226
4227 if (it->what == IT_CHARACTER)
4228 {
4229 /* Map via display table or translate control characters.
4230 IT->c, IT->len etc. have been set to the next character by
4231 the function call above. If we have a display table, and it
4232 contains an entry for IT->c, translate it. Don't do this if
4233 IT->c itself comes from a display table, otherwise we could
4234 end up in an infinite recursion. (An alternative could be to
4235 count the recursion depth of this function and signal an
4236 error when a certain maximum depth is reached.) Is it worth
4237 it? */
4238 if (success_p && it->dpvec == NULL)
4239 {
4240 Lisp_Object dv;
4241
4242 if (it->dp
4243 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
4244 VECTORP (dv)))
4245 {
4246 struct Lisp_Vector *v = XVECTOR (dv);
4247
4248 /* Return the first character from the display table
4249 entry, if not empty. If empty, don't display the
4250 current character. */
4251 if (v->size)
4252 {
4253 it->dpvec_char_len = it->len;
4254 it->dpvec = v->contents;
4255 it->dpend = v->contents + v->size;
4256 it->current.dpvec_index = 0;
4257 it->method = next_element_from_display_vector;
7eee47cc
GM
4258 success_p = get_next_display_element (it);
4259 }
4260 else
4261 {
4262 set_iterator_to_next (it, 0);
4263 success_p = get_next_display_element (it);
5f5c8ee5 4264 }
5f5c8ee5
GM
4265 }
4266
4267 /* Translate control characters into `\003' or `^C' form.
4268 Control characters coming from a display table entry are
4269 currently not translated because we use IT->dpvec to hold
4270 the translation. This could easily be changed but I
197516c2
KH
4271 don't believe that it is worth doing.
4272
fa831cf8
KH
4273 If it->multibyte_p is nonzero, eight-bit characters and
4274 non-printable multibyte characters are also translated to
4275 octal form.
4276
4277 If it->multibyte_p is zero, eight-bit characters that
4278 don't have corresponding multibyte char code are also
4279 translated to octal form. */
ba197fe6 4280 else if ((it->c < ' '
5f5c8ee5 4281 && (it->area != TEXT_AREA
c6e89d6c 4282 || (it->c != '\n' && it->c != '\t')))
fa831cf8
KH
4283 || (it->multibyte_p
4284 ? ((it->c >= 127
4285 && it->len == 1)
4286 || !CHAR_PRINTABLE_P (it->c))
ba197fe6 4287 : (it->c >= 127
fa831cf8 4288 && it->c == unibyte_char_to_multibyte (it->c))))
5f5c8ee5
GM
4289 {
4290 /* IT->c is a control character which must be displayed
4291 either as '\003' or as `^C' where the '\\' and '^'
4292 can be defined in the display table. Fill
4293 IT->ctl_chars with glyphs for what we have to
4294 display. Then, set IT->dpvec to these glyphs. */
4295 GLYPH g;
4296
54c85a23 4297 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
4298 {
4299 /* Set IT->ctl_chars[0] to the glyph for `^'. */
4300 if (it->dp
4301 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
4302 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
4303 g = XINT (DISP_CTRL_GLYPH (it->dp));
4304 else
4305 g = FAST_MAKE_GLYPH ('^', 0);
4306 XSETINT (it->ctl_chars[0], g);
4307
4308 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
4309 XSETINT (it->ctl_chars[1], g);
4310
4311 /* Set up IT->dpvec and return first character from it. */
4312 it->dpvec_char_len = it->len;
4313 it->dpvec = it->ctl_chars;
4314 it->dpend = it->dpvec + 2;
4315 it->current.dpvec_index = 0;
4316 it->method = next_element_from_display_vector;
4317 get_next_display_element (it);
4318 }
4319 else
4320 {
260a86a0 4321 unsigned char str[MAX_MULTIBYTE_LENGTH];
c5924f47 4322 int len;
197516c2
KH
4323 int i;
4324 GLYPH escape_glyph;
4325
5f5c8ee5
GM
4326 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
4327 if (it->dp
4328 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
4329 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 4330 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 4331 else
197516c2
KH
4332 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
4333
c5924f47
KH
4334 if (SINGLE_BYTE_CHAR_P (it->c))
4335 str[0] = it->c, len = 1;
4336 else
ea9dd091
GM
4337 {
4338 len = CHAR_STRING_NO_SIGNAL (it->c, str);
4339 if (len < 0)
4340 {
4341 /* It's an invalid character, which
4342 shouldn't happen actually, but due to
4343 bugs it may happen. Let's print the char
4344 as is, there's not much meaningful we can
4345 do with it. */
4346 str[0] = it->c;
4347 str[1] = it->c >> 8;
4348 str[2] = it->c >> 16;
4349 str[3] = it->c >> 24;
4350 len = 4;
4351 }
4352 }
c5924f47 4353
197516c2
KH
4354 for (i = 0; i < len; i++)
4355 {
4356 XSETINT (it->ctl_chars[i * 4], escape_glyph);
4357 /* Insert three more glyphs into IT->ctl_chars for
4358 the octal display of the character. */
2311178e 4359 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
197516c2 4360 XSETINT (it->ctl_chars[i * 4 + 1], g);
2311178e 4361 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
197516c2 4362 XSETINT (it->ctl_chars[i * 4 + 2], g);
2311178e 4363 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
197516c2
KH
4364 XSETINT (it->ctl_chars[i * 4 + 3], g);
4365 }
5f5c8ee5
GM
4366
4367 /* Set up IT->dpvec and return the first character
4368 from it. */
4369 it->dpvec_char_len = it->len;
4370 it->dpvec = it->ctl_chars;
197516c2 4371 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
4372 it->current.dpvec_index = 0;
4373 it->method = next_element_from_display_vector;
4374 get_next_display_element (it);
4375 }
4376 }
4377 }
4378
980806b6
KH
4379 /* Adjust face id for a multibyte character. There are no
4380 multibyte character in unibyte text. */
5f5c8ee5
GM
4381 if (it->multibyte_p
4382 && success_p
980806b6 4383 && FRAME_WINDOW_P (it->f))
5f5c8ee5 4384 {
980806b6
KH
4385 struct face *face = FACE_FROM_ID (it->f, it->face_id);
4386 it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
5f5c8ee5
GM
4387 }
4388 }
4389
4390 /* Is this character the last one of a run of characters with
4391 box? If yes, set IT->end_of_box_run_p to 1. */
4392 if (it->face_box_p
4393 && it->s == NULL)
4394 {
4395 int face_id;
4396 struct face *face;
4397
4398 it->end_of_box_run_p
4399 = ((face_id = face_after_it_pos (it),
4400 face_id != it->face_id)
4401 && (face = FACE_FROM_ID (it->f, face_id),
4402 face->box == FACE_NO_BOX));
4403 }
4404
4405 /* Value is 0 if end of buffer or string reached. */
4406 return success_p;
4407}
4408
4409
4410/* Move IT to the next display element.
4411
cafafe0b
GM
4412 RESEAT_P non-zero means if called on a newline in buffer text,
4413 skip to the next visible line start.
4414
5f5c8ee5
GM
4415 Functions get_next_display_element and set_iterator_to_next are
4416 separate because I find this arrangement easier to handle than a
4417 get_next_display_element function that also increments IT's
4418 position. The way it is we can first look at an iterator's current
4419 display element, decide whether it fits on a line, and if it does,
4420 increment the iterator position. The other way around we probably
4421 would either need a flag indicating whether the iterator has to be
4422 incremented the next time, or we would have to implement a
4423 decrement position function which would not be easy to write. */
4424
4425void
cafafe0b 4426set_iterator_to_next (it, reseat_p)
5f5c8ee5 4427 struct it *it;
cafafe0b 4428 int reseat_p;
5f5c8ee5 4429{
483de32b
GM
4430 /* Reset flags indicating start and end of a sequence of characters
4431 with box. Reset them at the start of this function because
4432 moving the iterator to a new position might set them. */
4433 it->start_of_box_run_p = it->end_of_box_run_p = 0;
2311178e 4434
5f5c8ee5
GM
4435 if (it->method == next_element_from_buffer)
4436 {
4437 /* The current display element of IT is a character from
4438 current_buffer. Advance in the buffer, and maybe skip over
4439 invisible lines that are so because of selective display. */
cafafe0b 4440 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
312246d1 4441 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4442 else
4443 {
4444 xassert (it->len != 0);
4445 IT_BYTEPOS (*it) += it->len;
4446 IT_CHARPOS (*it) += 1;
4447 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
4448 }
4449 }
260a86a0
KH
4450 else if (it->method == next_element_from_composition)
4451 {
4452 xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
4453 if (STRINGP (it->string))
4454 {
4455 IT_STRING_BYTEPOS (*it) += it->len;
4456 IT_STRING_CHARPOS (*it) += it->cmp_len;
4457 it->method = next_element_from_string;
4458 goto consider_string_end;
4459 }
4460 else
4461 {
4462 IT_BYTEPOS (*it) += it->len;
4463 IT_CHARPOS (*it) += it->cmp_len;
4464 it->method = next_element_from_buffer;
4465 }
4466 }
5f5c8ee5
GM
4467 else if (it->method == next_element_from_c_string)
4468 {
4469 /* Current display element of IT is from a C string. */
4470 IT_BYTEPOS (*it) += it->len;
4471 IT_CHARPOS (*it) += 1;
4472 }
4473 else if (it->method == next_element_from_display_vector)
4474 {
4475 /* Current display element of IT is from a display table entry.
4476 Advance in the display table definition. Reset it to null if
4477 end reached, and continue with characters from buffers/
4478 strings. */
4479 ++it->current.dpvec_index;
286bcbc9 4480
980806b6
KH
4481 /* Restore face of the iterator to what they were before the
4482 display vector entry (these entries may contain faces). */
5f5c8ee5 4483 it->face_id = it->saved_face_id;
2311178e 4484
5f5c8ee5
GM
4485 if (it->dpvec + it->current.dpvec_index == it->dpend)
4486 {
4487 if (it->s)
4488 it->method = next_element_from_c_string;
4489 else if (STRINGP (it->string))
4490 it->method = next_element_from_string;
4491 else
4492 it->method = next_element_from_buffer;
4493
4494 it->dpvec = NULL;
4495 it->current.dpvec_index = -1;
4496
312246d1
GM
4497 /* Skip over characters which were displayed via IT->dpvec. */
4498 if (it->dpvec_char_len < 0)
4499 reseat_at_next_visible_line_start (it, 1);
4500 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
4501 {
4502 it->len = it->dpvec_char_len;
cafafe0b 4503 set_iterator_to_next (it, reseat_p);
5f5c8ee5
GM
4504 }
4505 }
4506 }
4507 else if (it->method == next_element_from_string)
4508 {
4509 /* Current display element is a character from a Lisp string. */
4510 xassert (it->s == NULL && STRINGP (it->string));
4511 IT_STRING_BYTEPOS (*it) += it->len;
4512 IT_STRING_CHARPOS (*it) += 1;
2311178e 4513
5f5c8ee5
GM
4514 consider_string_end:
4515
4516 if (it->current.overlay_string_index >= 0)
4517 {
4518 /* IT->string is an overlay string. Advance to the
4519 next, if there is one. */
2051c264 4520 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
4521 next_overlay_string (it);
4522 }
4523 else
4524 {
4525 /* IT->string is not an overlay string. If we reached
4526 its end, and there is something on IT->stack, proceed
4527 with what is on the stack. This can be either another
4528 string, this time an overlay string, or a buffer. */
2051c264 4529 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
5f5c8ee5
GM
4530 && it->sp > 0)
4531 {
4532 pop_it (it);
4533 if (!STRINGP (it->string))
4534 it->method = next_element_from_buffer;
b2046df8
GM
4535 else
4536 goto consider_string_end;
5f5c8ee5
GM
4537 }
4538 }
4539 }
4540 else if (it->method == next_element_from_image
4541 || it->method == next_element_from_stretch)
4542 {
4543 /* The position etc with which we have to proceed are on
4544 the stack. The position may be at the end of a string,
4545 if the `display' property takes up the whole string. */
4546 pop_it (it);
4547 it->image_id = 0;
4548 if (STRINGP (it->string))
4549 {
4550 it->method = next_element_from_string;
4551 goto consider_string_end;
4552 }
4553 else
4554 it->method = next_element_from_buffer;
4555 }
4556 else
4557 /* There are no other methods defined, so this should be a bug. */
4558 abort ();
4559
5f5c8ee5
GM
4560 xassert (it->method != next_element_from_string
4561 || (STRINGP (it->string)
4562 && IT_STRING_CHARPOS (*it) >= 0));
4563}
4564
4565
4566/* Load IT's display element fields with information about the next
4567 display element which comes from a display table entry or from the
4568 result of translating a control character to one of the forms `^C'
4569 or `\003'. IT->dpvec holds the glyphs to return as characters. */
4570
4571static int
4572next_element_from_display_vector (it)
4573 struct it *it;
4574{
4575 /* Precondition. */
4576 xassert (it->dpvec && it->current.dpvec_index >= 0);
4577
4578 /* Remember the current face id in case glyphs specify faces.
4579 IT's face is restored in set_iterator_to_next. */
4580 it->saved_face_id = it->face_id;
2311178e 4581
5f5c8ee5
GM
4582 if (INTEGERP (*it->dpvec)
4583 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
4584 {
4585 int lface_id;
4586 GLYPH g;
4587
4588 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
4589 it->c = FAST_GLYPH_CHAR (g);
c5924f47 4590 it->len = CHAR_BYTES (it->c);
5f5c8ee5
GM
4591
4592 /* The entry may contain a face id to use. Such a face id is
4593 the id of a Lisp face, not a realized face. A face id of
969065c3 4594 zero means no face is specified. */
5f5c8ee5
GM
4595 lface_id = FAST_GLYPH_FACE (g);
4596 if (lface_id)
4597 {
969065c3 4598 /* The function returns -1 if lface_id is invalid. */
5f5c8ee5
GM
4599 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
4600 if (face_id >= 0)
969065c3 4601 it->face_id = face_id;
5f5c8ee5
GM
4602 }
4603 }
4604 else
4605 /* Display table entry is invalid. Return a space. */
4606 it->c = ' ', it->len = 1;
4607
4608 /* Don't change position and object of the iterator here. They are
4609 still the values of the character that had this display table
4610 entry or was translated, and that's what we want. */
4611 it->what = IT_CHARACTER;
4612 return 1;
4613}
4614
4615
4616/* Load IT with the next display element from Lisp string IT->string.
4617 IT->current.string_pos is the current position within the string.
4618 If IT->current.overlay_string_index >= 0, the Lisp string is an
4619 overlay string. */
4620
4621static int
4622next_element_from_string (it)
4623 struct it *it;
4624{
4625 struct text_pos position;
4626
4627 xassert (STRINGP (it->string));
4628 xassert (IT_STRING_CHARPOS (*it) >= 0);
4629 position = it->current.string_pos;
4630
4631 /* Time to check for invisible text? */
4632 if (IT_STRING_CHARPOS (*it) < it->end_charpos
4633 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
4634 {
4635 handle_stop (it);
4636
4637 /* Since a handler may have changed IT->method, we must
4638 recurse here. */
4639 return get_next_display_element (it);
4640 }
4641
4642 if (it->current.overlay_string_index >= 0)
4643 {
4644 /* Get the next character from an overlay string. In overlay
4645 strings, There is no field width or padding with spaces to
4646 do. */
2051c264 4647 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
4648 {
4649 it->what = IT_EOB;
4650 return 0;
4651 }
4652 else if (STRING_MULTIBYTE (it->string))
4653 {
2051c264 4654 int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
4655 const unsigned char *s = (SDATA (it->string)
4656 + IT_STRING_BYTEPOS (*it));
4fdb80f2 4657 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
4658 }
4659 else
4660 {
2051c264 4661 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
4662 it->len = 1;
4663 }
4664 }
4665 else
4666 {
4667 /* Get the next character from a Lisp string that is not an
4668 overlay string. Such strings come from the mode line, for
4669 example. We may have to pad with spaces, or truncate the
4670 string. See also next_element_from_c_string. */
4671 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
4672 {
4673 it->what = IT_EOB;
4674 return 0;
4675 }
4676 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
4677 {
4678 /* Pad with spaces. */
4679 it->c = ' ', it->len = 1;
4680 CHARPOS (position) = BYTEPOS (position) = -1;
4681 }
4682 else if (STRING_MULTIBYTE (it->string))
4683 {
2051c264 4684 int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
4685 const unsigned char *s = (SDATA (it->string)
4686 + IT_STRING_BYTEPOS (*it));
4fdb80f2 4687 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
4688 }
4689 else
4690 {
2051c264 4691 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
4692 it->len = 1;
4693 }
4694 }
4695
4696 /* Record what we have and where it came from. Note that we store a
4697 buffer position in IT->position although it could arguably be a
4698 string position. */
4699 it->what = IT_CHARACTER;
4700 it->object = it->string;
4701 it->position = position;
4702 return 1;
4703}
4704
4705
4706/* Load IT with next display element from C string IT->s.
4707 IT->string_nchars is the maximum number of characters to return
4708 from the string. IT->end_charpos may be greater than
4709 IT->string_nchars when this function is called, in which case we
4710 may have to return padding spaces. Value is zero if end of string
4711 reached, including padding spaces. */
4712
4713static int
4714next_element_from_c_string (it)
4715 struct it *it;
4716{
4717 int success_p = 1;
2311178e 4718
5f5c8ee5
GM
4719 xassert (it->s);
4720 it->what = IT_CHARACTER;
4721 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
4722 it->object = Qnil;
2311178e 4723
5f5c8ee5
GM
4724 /* IT's position can be greater IT->string_nchars in case a field
4725 width or precision has been specified when the iterator was
4726 initialized. */
4727 if (IT_CHARPOS (*it) >= it->end_charpos)
4728 {
4729 /* End of the game. */
4730 it->what = IT_EOB;
4731 success_p = 0;
4732 }
4733 else if (IT_CHARPOS (*it) >= it->string_nchars)
4734 {
4735 /* Pad with spaces. */
4736 it->c = ' ', it->len = 1;
4737 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
4738 }
4739 else if (it->multibyte_p)
4740 {
4741 /* Implementation note: The calls to strlen apparently aren't a
4742 performance problem because there is no noticeable performance
4743 difference between Emacs running in unibyte or multibyte mode. */
4744 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
4745 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
4746 maxlen, &it->len);
5f5c8ee5
GM
4747 }
4748 else
4749 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
2311178e 4750
5f5c8ee5
GM
4751 return success_p;
4752}
4753
4754
4755/* Set up IT to return characters from an ellipsis, if appropriate.
4756 The definition of the ellipsis glyphs may come from a display table
4757 entry. This function Fills IT with the first glyph from the
4758 ellipsis if an ellipsis is to be displayed. */
4759
13f19968 4760static int
5f5c8ee5
GM
4761next_element_from_ellipsis (it)
4762 struct it *it;
4763{
13f19968 4764 if (it->selective_display_ellipsis_p)
5f5c8ee5 4765 {
13f19968
GM
4766 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
4767 {
4768 /* Use the display table definition for `...'. Invalid glyphs
4769 will be handled by the method returning elements from dpvec. */
4770 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
4771 it->dpvec_char_len = it->len;
4772 it->dpvec = v->contents;
4773 it->dpend = v->contents + v->size;
4774 it->current.dpvec_index = 0;
4775 it->method = next_element_from_display_vector;
4776 }
4777 else
4778 {
4779 /* Use default `...' which is stored in default_invis_vector. */
4780 it->dpvec_char_len = it->len;
4781 it->dpvec = default_invis_vector;
4782 it->dpend = default_invis_vector + 3;
4783 it->current.dpvec_index = 0;
4784 it->method = next_element_from_display_vector;
4785 }
5f5c8ee5 4786 }
13f19968 4787 else
54918e2b 4788 {
4aad61f8
GM
4789 /* The face at the current position may be different from the
4790 face we find after the invisible text. Remember what it
4791 was in IT->saved_face_id, and signal that it's there by
4792 setting face_before_selective_p. */
4793 it->saved_face_id = it->face_id;
54918e2b
GM
4794 it->method = next_element_from_buffer;
4795 reseat_at_next_visible_line_start (it, 1);
4aad61f8 4796 it->face_before_selective_p = 1;
54918e2b 4797 }
2311178e 4798
13f19968 4799 return get_next_display_element (it);
5f5c8ee5
GM
4800}
4801
4802
4803/* Deliver an image display element. The iterator IT is already
4804 filled with image information (done in handle_display_prop). Value
4805 is always 1. */
2311178e 4806
5f5c8ee5
GM
4807
4808static int
4809next_element_from_image (it)
4810 struct it *it;
4811{
4812 it->what = IT_IMAGE;
4813 return 1;
4814}
4815
4816
4817/* Fill iterator IT with next display element from a stretch glyph
4818 property. IT->object is the value of the text property. Value is
4819 always 1. */
4820
4821static int
4822next_element_from_stretch (it)
4823 struct it *it;
4824{
4825 it->what = IT_STRETCH;
4826 return 1;
4827}
4828
4829
4830/* Load IT with the next display element from current_buffer. Value
4831 is zero if end of buffer reached. IT->stop_charpos is the next
4832 position at which to stop and check for text properties or buffer
4833 end. */
4834
4835static int
4836next_element_from_buffer (it)
4837 struct it *it;
4838{
4839 int success_p = 1;
4840
4841 /* Check this assumption, otherwise, we would never enter the
4842 if-statement, below. */
4843 xassert (IT_CHARPOS (*it) >= BEGV
4844 && IT_CHARPOS (*it) <= it->stop_charpos);
4845
4846 if (IT_CHARPOS (*it) >= it->stop_charpos)
4847 {
4848 if (IT_CHARPOS (*it) >= it->end_charpos)
4849 {
4850 int overlay_strings_follow_p;
2311178e 4851
5f5c8ee5
GM
4852 /* End of the game, except when overlay strings follow that
4853 haven't been returned yet. */
4854 if (it->overlay_strings_at_end_processed_p)
4855 overlay_strings_follow_p = 0;
4856 else
4857 {
4858 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf 4859 overlay_strings_follow_p = get_overlay_strings (it, 0);
5f5c8ee5
GM
4860 }
4861
4862 if (overlay_strings_follow_p)
4863 success_p = get_next_display_element (it);
4864 else
4865 {
4866 it->what = IT_EOB;
4867 it->position = it->current.pos;
4868 success_p = 0;
4869 }
4870 }
4871 else
4872 {
4873 handle_stop (it);
4874 return get_next_display_element (it);
4875 }
4876 }
4877 else
4878 {
4879 /* No face changes, overlays etc. in sight, so just return a
4880 character from current_buffer. */
4881 unsigned char *p;
4882
4883 /* Maybe run the redisplay end trigger hook. Performance note:
4884 This doesn't seem to cost measurable time. */
4885 if (it->redisplay_end_trigger_charpos
4886 && it->glyph_row
4887 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
4888 run_redisplay_end_trigger_hook (it);
4889
4890 /* Get the next character, maybe multibyte. */
4891 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
260a86a0 4892 if (it->multibyte_p && !ASCII_BYTE_P (*p))
5f5c8ee5
GM
4893 {
4894 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
4895 - IT_BYTEPOS (*it));
4fdb80f2 4896 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
4897 }
4898 else
4899 it->c = *p, it->len = 1;
4900
4901 /* Record what we have and where it came from. */
4902 it->what = IT_CHARACTER;;
4903 it->object = it->w->buffer;
4904 it->position = it->current.pos;
4905
4906 /* Normally we return the character found above, except when we
4907 really want to return an ellipsis for selective display. */
4908 if (it->selective)
4909 {
4910 if (it->c == '\n')
4911 {
4912 /* A value of selective > 0 means hide lines indented more
4913 than that number of columns. */
4914 if (it->selective > 0
4915 && IT_CHARPOS (*it) + 1 < ZV
4916 && indented_beyond_p (IT_CHARPOS (*it) + 1,
4917 IT_BYTEPOS (*it) + 1,
a67e162b 4918 (double) it->selective)) /* iftc */
312246d1 4919 {
13f19968 4920 success_p = next_element_from_ellipsis (it);
312246d1
GM
4921 it->dpvec_char_len = -1;
4922 }
5f5c8ee5
GM
4923 }
4924 else if (it->c == '\r' && it->selective == -1)
4925 {
4926 /* A value of selective == -1 means that everything from the
4927 CR to the end of the line is invisible, with maybe an
4928 ellipsis displayed for it. */
13f19968 4929 success_p = next_element_from_ellipsis (it);
312246d1 4930 it->dpvec_char_len = -1;
5f5c8ee5
GM
4931 }
4932 }
4933 }
4934
4935 /* Value is zero if end of buffer reached. */
c880678e 4936 xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
5f5c8ee5
GM
4937 return success_p;
4938}
4939
2311178e 4940
5f5c8ee5
GM
4941/* Run the redisplay end trigger hook for IT. */
4942
4943static void
4944run_redisplay_end_trigger_hook (it)
4945 struct it *it;
4946{
4947 Lisp_Object args[3];
4948
4949 /* IT->glyph_row should be non-null, i.e. we should be actually
4950 displaying something, or otherwise we should not run the hook. */
4951 xassert (it->glyph_row);
4952
4953 /* Set up hook arguments. */
4954 args[0] = Qredisplay_end_trigger_functions;
4955 args[1] = it->window;
4956 XSETINT (args[2], it->redisplay_end_trigger_charpos);
4957 it->redisplay_end_trigger_charpos = 0;
4958
4959 /* Since we are *trying* to run these functions, don't try to run
4960 them again, even if they get an error. */
4961 it->w->redisplay_end_trigger = Qnil;
4962 Frun_hook_with_args (3, args);
2311178e 4963
5f5c8ee5
GM
4964 /* Notice if it changed the face of the character we are on. */
4965 handle_face_prop (it);
4966}
4967
4968
260a86a0
KH
4969/* Deliver a composition display element. The iterator IT is already
4970 filled with composition information (done in
4971 handle_composition_prop). Value is always 1. */
4972
4973static int
4974next_element_from_composition (it)
4975 struct it *it;
4976{
4977 it->what = IT_COMPOSITION;
4978 it->position = (STRINGP (it->string)
4979 ? it->current.string_pos
4980 : it->current.pos);
4981 return 1;
4982}
4983
4984
5f5c8ee5
GM
4985\f
4986/***********************************************************************
4987 Moving an iterator without producing glyphs
4988 ***********************************************************************/
4989
4990/* Move iterator IT to a specified buffer or X position within one
4991 line on the display without producing glyphs.
4992
c53a1624
RS
4993 OP should be a bit mask including some or all of these bits:
4994 MOVE_TO_X: Stop on reaching x-position TO_X.
4995 MOVE_TO_POS: Stop on reaching buffer or string position TO_CHARPOS.
4996 Regardless of OP's value, stop in reaching the end of the display line.
5f5c8ee5 4997
c53a1624
RS
4998 TO_X is normally a value 0 <= TO_X <= IT->last_visible_x.
4999 This means, in particular, that TO_X includes window's horizontal
5000 scroll amount.
5f5c8ee5 5001
c53a1624
RS
5002 The return value has several possible values that
5003 say what condition caused the scan to stop:
5f5c8ee5
GM
5004
5005 MOVE_POS_MATCH_OR_ZV
5006 - when TO_POS or ZV was reached.
2311178e 5007
5f5c8ee5
GM
5008 MOVE_X_REACHED
5009 -when TO_X was reached before TO_POS or ZV were reached.
2311178e 5010
5f5c8ee5
GM
5011 MOVE_LINE_CONTINUED
5012 - when we reached the end of the display area and the line must
5013 be continued.
2311178e 5014
5f5c8ee5
GM
5015 MOVE_LINE_TRUNCATED
5016 - when we reached the end of the display area and the line is
5017 truncated.
5018
5019 MOVE_NEWLINE_OR_CR
5020 - when we stopped at a line end, i.e. a newline or a CR and selective
5021 display is on. */
5022
701552dd 5023static enum move_it_result
5f5c8ee5
GM
5024move_it_in_display_line_to (it, to_charpos, to_x, op)
5025 struct it *it;
5026 int to_charpos, to_x, op;
5027{
5028 enum move_it_result result = MOVE_UNDEFINED;
5029 struct glyph_row *saved_glyph_row;
5030
5031 /* Don't produce glyphs in produce_glyphs. */
5032 saved_glyph_row = it->glyph_row;
5033 it->glyph_row = NULL;
5034
5f5c8ee5
GM
5035 while (1)
5036 {
ae26e27d 5037 int x, i, ascent = 0, descent = 0;
2311178e 5038
5f5c8ee5
GM
5039 /* Stop when ZV or TO_CHARPOS reached. */
5040 if (!get_next_display_element (it)
5041 || ((op & MOVE_TO_POS) != 0
5042 && BUFFERP (it->object)
5043 && IT_CHARPOS (*it) >= to_charpos))
5044 {
5045 result = MOVE_POS_MATCH_OR_ZV;
5046 break;
5047 }
2311178e 5048
5f5c8ee5
GM
5049 /* The call to produce_glyphs will get the metrics of the
5050 display element IT is loaded with. We record in x the
5051 x-position before this display element in case it does not
5052 fit on the line. */
5053 x = it->current_x;
2311178e 5054
47589c8c
GM
5055 /* Remember the line height so far in case the next element doesn't
5056 fit on the line. */
5057 if (!it->truncate_lines_p)
5058 {
5059 ascent = it->max_ascent;
5060 descent = it->max_descent;
5061 }
2311178e 5062
5f5c8ee5
GM
5063 PRODUCE_GLYPHS (it);
5064
5065 if (it->area != TEXT_AREA)
5066 {
cafafe0b 5067 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5068 continue;
5069 }
5070
5071 /* The number of glyphs we get back in IT->nglyphs will normally
5072 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
5073 character on a terminal frame, or (iii) a line end. For the
5074 second case, IT->nglyphs - 1 padding glyphs will be present
5075 (on X frames, there is only one glyph produced for a
5076 composite character.
5077
5078 The behavior implemented below means, for continuation lines,
5079 that as many spaces of a TAB as fit on the current line are
5080 displayed there. For terminal frames, as many glyphs of a
5081 multi-glyph character are displayed in the current line, too.
5082 This is what the old redisplay code did, and we keep it that
5083 way. Under X, the whole shape of a complex character must
5084 fit on the line or it will be completely displayed in the
5085 next line.
5086
5087 Note that both for tabs and padding glyphs, all glyphs have
5088 the same width. */
5089 if (it->nglyphs)
5090 {
5091 /* More than one glyph or glyph doesn't fit on line. All
5092 glyphs have the same width. */
5093 int single_glyph_width = it->pixel_width / it->nglyphs;
5094 int new_x;
2311178e 5095
5f5c8ee5
GM
5096 for (i = 0; i < it->nglyphs; ++i, x = new_x)
5097 {
5098 new_x = x + single_glyph_width;
5099
5100 /* We want to leave anything reaching TO_X to the caller. */
5101 if ((op & MOVE_TO_X) && new_x > to_x)
5102 {
5103 it->current_x = x;
5104 result = MOVE_X_REACHED;
5105 break;
5106 }
5107 else if (/* Lines are continued. */
5108 !it->truncate_lines_p
5109 && (/* And glyph doesn't fit on the line. */
5110 new_x > it->last_visible_x
5111 /* Or it fits exactly and we're on a window
5112 system frame. */
5113 || (new_x == it->last_visible_x
5114 && FRAME_WINDOW_P (it->f))))
5115 {
5116 if (/* IT->hpos == 0 means the very first glyph
5117 doesn't fit on the line, e.g. a wide image. */
5118 it->hpos == 0
5119 || (new_x == it->last_visible_x
5120 && FRAME_WINDOW_P (it->f)))
5121 {
5122 ++it->hpos;
5123 it->current_x = new_x;
5124 if (i == it->nglyphs - 1)
cafafe0b 5125 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5126 }
5127 else
47589c8c
GM
5128 {
5129 it->current_x = x;
5130 it->max_ascent = ascent;
5131 it->max_descent = descent;
5132 }
2311178e 5133
47589c8c
GM
5134 TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
5135 IT_CHARPOS (*it)));
5f5c8ee5
GM
5136 result = MOVE_LINE_CONTINUED;
5137 break;
5138 }
5139 else if (new_x > it->first_visible_x)
5140 {
5141 /* Glyph is visible. Increment number of glyphs that
5142 would be displayed. */
5143 ++it->hpos;
5144 }
5145 else
5146 {
2311178e 5147 /* Glyph is completely off the left margin of the display
5f5c8ee5
GM
5148 area. Nothing to do. */
5149 }
5150 }
5151
5152 if (result != MOVE_UNDEFINED)
5153 break;
5154 }
5155 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
5156 {
5157 /* Stop when TO_X specified and reached. This check is
5158 necessary here because of lines consisting of a line end,
5159 only. The line end will not produce any glyphs and we
5160 would never get MOVE_X_REACHED. */
5161 xassert (it->nglyphs == 0);
5162 result = MOVE_X_REACHED;
5163 break;
5164 }
2311178e 5165
5f5c8ee5
GM
5166 /* Is this a line end? If yes, we're done. */
5167 if (ITERATOR_AT_END_OF_LINE_P (it))
5168 {
5169 result = MOVE_NEWLINE_OR_CR;
5170 break;
5171 }
2311178e 5172
5f5c8ee5
GM
5173 /* The current display element has been consumed. Advance
5174 to the next. */
cafafe0b 5175 set_iterator_to_next (it, 1);
2311178e 5176
5f5c8ee5
GM
5177 /* Stop if lines are truncated and IT's current x-position is
5178 past the right edge of the window now. */
5179 if (it->truncate_lines_p
5180 && it->current_x >= it->last_visible_x)
5181 {
5182 result = MOVE_LINE_TRUNCATED;
5183 break;
5184 }
5185 }
5186
5187 /* Restore the iterator settings altered at the beginning of this
5188 function. */
5189 it->glyph_row = saved_glyph_row;
5190 return result;
5191}
5192
5193
9b2bba76
RS
5194/* Move IT forward until it satisfies one or more of the criteria in
5195 TO_CHARPOS, TO_X, TO_Y, and TO_VPOS.
5196
5197 OP is a bit-mask that specifies where to stop, and in particular,
5198 which of those four position arguments makes a difference. See the
5199 description of enum move_operation_enum.
2311178e 5200
5f5c8ee5
GM
5201 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
5202 screen line, this function will set IT to the next position >
5203 TO_CHARPOS. */
5204
5205void
5206move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
5207 struct it *it;
5208 int to_charpos, to_x, to_y, to_vpos;
5209 int op;
5210{
5211 enum move_it_result skip, skip2 = MOVE_X_REACHED;
5212 int line_height;
47589c8c 5213 int reached = 0;
5f5c8ee5 5214
47589c8c 5215 for (;;)
5f5c8ee5
GM
5216 {
5217 if (op & MOVE_TO_VPOS)
5218 {
5219 /* If no TO_CHARPOS and no TO_X specified, stop at the
5220 start of the line TO_VPOS. */
5221 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
5222 {
5223 if (it->vpos == to_vpos)
47589c8c
GM
5224 {
5225 reached = 1;
5226 break;
5227 }
5228 else
5229 skip = move_it_in_display_line_to (it, -1, -1, 0);
5f5c8ee5
GM
5230 }
5231 else
5232 {
5233 /* TO_VPOS >= 0 means stop at TO_X in the line at
5234 TO_VPOS, or at TO_POS, whichever comes first. */
47589c8c
GM
5235 if (it->vpos == to_vpos)
5236 {
5237 reached = 2;
5238 break;
5239 }
2311178e 5240
5f5c8ee5
GM
5241 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
5242
5243 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
47589c8c
GM
5244 {
5245 reached = 3;
5246 break;
5247 }
5f5c8ee5
GM
5248 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
5249 {
5250 /* We have reached TO_X but not in the line we want. */
5251 skip = move_it_in_display_line_to (it, to_charpos,
5252 -1, MOVE_TO_POS);
5253 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5254 {
5255 reached = 4;
5256 break;
5257 }
5f5c8ee5
GM
5258 }
5259 }
5260 }
5261 else if (op & MOVE_TO_Y)
5262 {
5263 struct it it_backup;
2311178e 5264
5f5c8ee5
GM
5265 /* TO_Y specified means stop at TO_X in the line containing
5266 TO_Y---or at TO_CHARPOS if this is reached first. The
5267 problem is that we can't really tell whether the line
5268 contains TO_Y before we have completely scanned it, and
5269 this may skip past TO_X. What we do is to first scan to
5270 TO_X.
5271
5272 If TO_X is not specified, use a TO_X of zero. The reason
5273 is to make the outcome of this function more predictable.
5274 If we didn't use TO_X == 0, we would stop at the end of
5275 the line which is probably not what a caller would expect
5276 to happen. */
5277 skip = move_it_in_display_line_to (it, to_charpos,
5278 ((op & MOVE_TO_X)
5279 ? to_x : 0),
5280 (MOVE_TO_X
5281 | (op & MOVE_TO_POS)));
5282
5283 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
5284 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5285 {
5286 reached = 5;
5287 break;
5288 }
2311178e 5289
5f5c8ee5
GM
5290 /* If TO_X was reached, we would like to know whether TO_Y
5291 is in the line. This can only be said if we know the
5292 total line height which requires us to scan the rest of
5293 the line. */
5f5c8ee5
GM
5294 if (skip == MOVE_X_REACHED)
5295 {
5296 it_backup = *it;
47589c8c 5297 TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5298 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
5299 op & MOVE_TO_POS);
47589c8c 5300 TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5301 }
5302
5303 /* Now, decide whether TO_Y is in this line. */
5304 line_height = it->max_ascent + it->max_descent;
47589c8c 5305 TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
2311178e 5306
5f5c8ee5
GM
5307 if (to_y >= it->current_y
5308 && to_y < it->current_y + line_height)
5309 {
5310 if (skip == MOVE_X_REACHED)
5311 /* If TO_Y is in this line and TO_X was reached above,
5312 we scanned too far. We have to restore IT's settings
5313 to the ones before skipping. */
5314 *it = it_backup;
47589c8c 5315 reached = 6;
5f5c8ee5
GM
5316 }
5317 else if (skip == MOVE_X_REACHED)
5318 {
5319 skip = skip2;
5320 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c 5321 reached = 7;
5f5c8ee5
GM
5322 }
5323
47589c8c 5324 if (reached)
5f5c8ee5
GM
5325 break;
5326 }
5327 else
5328 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
5329
5330 switch (skip)
5331 {
5332 case MOVE_POS_MATCH_OR_ZV:
47589c8c
GM
5333 reached = 8;
5334 goto out;
5f5c8ee5
GM
5335
5336 case MOVE_NEWLINE_OR_CR:
cafafe0b 5337 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5338 it->continuation_lines_width = 0;
5339 break;
5340
5341 case MOVE_LINE_TRUNCATED:
5342 it->continuation_lines_width = 0;
312246d1 5343 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
5344 if ((op & MOVE_TO_POS) != 0
5345 && IT_CHARPOS (*it) > to_charpos)
47589c8c
GM
5346 {
5347 reached = 9;
5348 goto out;
5349 }
5f5c8ee5
GM
5350 break;
5351
5352 case MOVE_LINE_CONTINUED:
5353 it->continuation_lines_width += it->current_x;
5354 break;
5355
5356 default:
5357 abort ();
5358 }
5359
5360 /* Reset/increment for the next run. */
5361 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
5362 it->current_x = it->hpos = 0;
5363 it->current_y += it->max_ascent + it->max_descent;
5364 ++it->vpos;
5365 last_height = it->max_ascent + it->max_descent;
5366 last_max_ascent = it->max_ascent;
5367 it->max_ascent = it->max_descent = 0;
5368 }
2311178e 5369
47589c8c
GM
5370 out:
5371
5372 TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
5f5c8ee5
GM
5373}
5374
5375
5376/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
5377
5378 If DY > 0, move IT backward at least that many pixels. DY = 0
5379 means move IT backward to the preceding line start or BEGV. This
5380 function may move over more than DY pixels if IT->current_y - DY
5381 ends up in the middle of a line; in this case IT->current_y will be
5382 set to the top of the line moved to. */
5383
5384void
5385move_it_vertically_backward (it, dy)
5386 struct it *it;
5387 int dy;
5388{
79ddf6f7
GM
5389 int nlines, h;
5390 struct it it2, it3;
5f5c8ee5 5391 int start_pos = IT_CHARPOS (*it);
2311178e 5392
5f5c8ee5
GM
5393 xassert (dy >= 0);
5394
5395 /* Estimate how many newlines we must move back. */
5396 nlines = max (1, dy / CANON_Y_UNIT (it->f));
5397
5398 /* Set the iterator's position that many lines back. */
5399 while (nlines-- && IT_CHARPOS (*it) > BEGV)
5400 back_to_previous_visible_line_start (it);
5401
5402 /* Reseat the iterator here. When moving backward, we don't want
5403 reseat to skip forward over invisible text, set up the iterator
5404 to deliver from overlay strings at the new position etc. So,
5405 use reseat_1 here. */
5406 reseat_1 (it, it->current.pos, 1);
5407
5408 /* We are now surely at a line start. */
5409 it->current_x = it->hpos = 0;
5410
5411 /* Move forward and see what y-distance we moved. First move to the
5412 start of the next line so that we get its height. We need this
5413 height to be able to tell whether we reached the specified
5414 y-distance. */
5415 it2 = *it;
5416 it2.max_ascent = it2.max_descent = 0;
5417 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
5418 MOVE_TO_POS | MOVE_TO_VPOS);
5419 xassert (IT_CHARPOS (*it) >= BEGV);
79ddf6f7 5420 it3 = it2;
2311178e 5421
5f5c8ee5
GM
5422 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
5423 xassert (IT_CHARPOS (*it) >= BEGV);
5424 h = it2.current_y - it->current_y;
5425 nlines = it2.vpos - it->vpos;
5426
5427 /* Correct IT's y and vpos position. */
5428 it->vpos -= nlines;
5429 it->current_y -= h;
2311178e 5430
5f5c8ee5
GM
5431 if (dy == 0)
5432 {
5433 /* DY == 0 means move to the start of the screen line. The
5434 value of nlines is > 0 if continuation lines were involved. */
5435 if (nlines > 0)
5436 move_it_by_lines (it, nlines, 1);
5437 xassert (IT_CHARPOS (*it) <= start_pos);
5438 }
5439 else if (nlines)
5440 {
5441 /* The y-position we try to reach. Note that h has been
5442 subtracted in front of the if-statement. */
5443 int target_y = it->current_y + h - dy;
79ddf6f7
GM
5444 int y0 = it3.current_y;
5445 int y1 = line_bottom_y (&it3);
5446 int line_height = y1 - y0;
f7ccfc8c 5447
5f5c8ee5
GM
5448 /* If we did not reach target_y, try to move further backward if
5449 we can. If we moved too far backward, try to move forward. */
5450 if (target_y < it->current_y
79ddf6f7
GM
5451 /* This is heuristic. In a window that's 3 lines high, with
5452 a line height of 13 pixels each, recentering with point
5453 on the bottom line will try to move -39/2 = 19 pixels
5454 backward. Try to avoid moving into the first line. */
798dbe1f 5455 && it->current_y - target_y > line_height / 3 * 2
5f5c8ee5
GM
5456 && IT_CHARPOS (*it) > BEGV)
5457 {
f7ccfc8c
GM
5458 TRACE_MOVE ((stderr, " not far enough -> move_vert %d\n",
5459 target_y - it->current_y));
5f5c8ee5
GM
5460 move_it_vertically (it, target_y - it->current_y);
5461 xassert (IT_CHARPOS (*it) >= BEGV);
5462 }
5463 else if (target_y >= it->current_y + line_height
5464 && IT_CHARPOS (*it) < ZV)
5465 {
55591976 5466 /* Should move forward by at least one line, maybe more.
2311178e 5467
55591976
GM
5468 Note: Calling move_it_by_lines can be expensive on
5469 terminal frames, where compute_motion is used (via
5470 vmotion) to do the job, when there are very long lines
5471 and truncate-lines is nil. That's the reason for
5472 treating terminal frames specially here. */
2311178e 5473
55591976
GM
5474 if (!FRAME_WINDOW_P (it->f))
5475 move_it_vertically (it, target_y - (it->current_y + line_height));
5476 else
f7ccfc8c 5477 {
55591976
GM
5478 do
5479 {
5480 move_it_by_lines (it, 1, 1);
5481 }
5482 while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
f7ccfc8c 5483 }
f7ccfc8c 5484
5f5c8ee5
GM
5485 xassert (IT_CHARPOS (*it) >= BEGV);
5486 }
5487 }
5488}
5489
5490
5491/* Move IT by a specified amount of pixel lines DY. DY negative means
5492 move backwards. DY = 0 means move to start of screen line. At the
5493 end, IT will be on the start of a screen line. */
5494
2311178e 5495void
5f5c8ee5
GM
5496move_it_vertically (it, dy)
5497 struct it *it;
5498 int dy;
5499{
5500 if (dy <= 0)
5501 move_it_vertically_backward (it, -dy);
5502 else if (dy > 0)
5503 {
47589c8c 5504 TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
5f5c8ee5
GM
5505 move_it_to (it, ZV, -1, it->current_y + dy, -1,
5506 MOVE_TO_POS | MOVE_TO_Y);
47589c8c 5507 TRACE_MOVE ((stderr, "move_it_v: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5508
5509 /* If buffer ends in ZV without a newline, move to the start of
5510 the line to satisfy the post-condition. */
5511 if (IT_CHARPOS (*it) == ZV
5512 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
5513 move_it_by_lines (it, 0, 0);
5514 }
5515}
5516
5517
47fc2c10
GM
5518/* Move iterator IT past the end of the text line it is in. */
5519
5520void
5521move_it_past_eol (it)
5522 struct it *it;
5523{
5524 enum move_it_result rc;
2311178e 5525
47fc2c10
GM
5526 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
5527 if (rc == MOVE_NEWLINE_OR_CR)
5528 set_iterator_to_next (it, 0);
5529}
5530
5531
2c79b732
GM
5532#if 0 /* Currently not used. */
5533
5f5c8ee5
GM
5534/* Return non-zero if some text between buffer positions START_CHARPOS
5535 and END_CHARPOS is invisible. IT->window is the window for text
5536 property lookup. */
5537
5538static int
5539invisible_text_between_p (it, start_charpos, end_charpos)
5540 struct it *it;
5541 int start_charpos, end_charpos;
5542{
5f5c8ee5
GM
5543 Lisp_Object prop, limit;
5544 int invisible_found_p;
2311178e 5545
5f5c8ee5
GM
5546 xassert (it != NULL && start_charpos <= end_charpos);
5547
5548 /* Is text at START invisible? */
5549 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
5550 it->window);
5551 if (TEXT_PROP_MEANS_INVISIBLE (prop))
5552 invisible_found_p = 1;
5553 else
5554 {
016b5642
MB
5555 limit = Fnext_single_char_property_change (make_number (start_charpos),
5556 Qinvisible, Qnil,
5557 make_number (end_charpos));
5f5c8ee5
GM
5558 invisible_found_p = XFASTINT (limit) < end_charpos;
5559 }
5560
5561 return invisible_found_p;
5f5c8ee5
GM
5562}
5563
2c79b732
GM
5564#endif /* 0 */
5565
5f5c8ee5
GM
5566
5567/* Move IT by a specified number DVPOS of screen lines down. DVPOS
5568 negative means move up. DVPOS == 0 means move to the start of the
5569 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
5570 NEED_Y_P is zero, IT->current_y will be left unchanged.
5571
5572 Further optimization ideas: If we would know that IT->f doesn't use
5573 a face with proportional font, we could be faster for
5574 truncate-lines nil. */
5575
5576void
5577move_it_by_lines (it, dvpos, need_y_p)
5578 struct it *it;
5579 int dvpos, need_y_p;
5580{
5581 struct position pos;
2311178e 5582
5f5c8ee5
GM
5583 if (!FRAME_WINDOW_P (it->f))
5584 {
5585 struct text_pos textpos;
2311178e 5586
5f5c8ee5
GM
5587 /* We can use vmotion on frames without proportional fonts. */
5588 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
5589 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
5590 reseat (it, textpos, 1);
5591 it->vpos += pos.vpos;
5592 it->current_y += pos.vpos;
5593 }
5594 else if (dvpos == 0)
5595 {
5596 /* DVPOS == 0 means move to the start of the screen line. */
5597 move_it_vertically_backward (it, 0);
5598 xassert (it->current_x == 0 && it->hpos == 0);
5599 }
5600 else if (dvpos > 0)
2c79b732 5601 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
5f5c8ee5
GM
5602 else
5603 {
5604 struct it it2;
5605 int start_charpos, i;
2311178e 5606
e8660d73
GM
5607 /* Start at the beginning of the screen line containing IT's
5608 position. */
5609 move_it_vertically_backward (it, 0);
2311178e 5610
5f5c8ee5
GM
5611 /* Go back -DVPOS visible lines and reseat the iterator there. */
5612 start_charpos = IT_CHARPOS (*it);
5613 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
5614 back_to_previous_visible_line_start (it);
5615 reseat (it, it->current.pos, 1);
5616 it->current_x = it->hpos = 0;
5617
5618 /* Above call may have moved too far if continuation lines
5619 are involved. Scan forward and see if it did. */
5620 it2 = *it;
5621 it2.vpos = it2.current_y = 0;
5622 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
5623 it->vpos -= it2.vpos;
5624 it->current_y -= it2.current_y;
5625 it->current_x = it->hpos = 0;
5626
5627 /* If we moved too far, move IT some lines forward. */
5628 if (it2.vpos > -dvpos)
5629 {
5630 int delta = it2.vpos + dvpos;
5631 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
5632 }
5633 }
5634}
5635
5636
5637\f
5638/***********************************************************************
5639 Messages
5640 ***********************************************************************/
5641
5642
937248bc
GM
5643/* Add a message with format string FORMAT and arguments ARG1 and ARG2
5644 to *Messages*. */
5645
5646void
5647add_to_log (format, arg1, arg2)
5648 char *format;
5649 Lisp_Object arg1, arg2;
5650{
5651 Lisp_Object args[3];
5652 Lisp_Object msg, fmt;
5653 char *buffer;
5654 int len;
5655 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5656
ae794295
GM
5657 /* Do nothing if called asynchronously. Inserting text into
5658 a buffer may call after-change-functions and alike and
5659 that would means running Lisp asynchronously. */
5660 if (handling_signal)
5661 return;
5662
937248bc
GM
5663 fmt = msg = Qnil;
5664 GCPRO4 (fmt, msg, arg1, arg2);
2311178e 5665
937248bc
GM
5666 args[0] = fmt = build_string (format);
5667 args[1] = arg1;
5668 args[2] = arg2;
6fc556fd 5669 msg = Fformat (3, args);
937248bc 5670
2051c264 5671 len = SBYTES (msg) + 1;
937248bc 5672 buffer = (char *) alloca (len);
2051c264 5673 bcopy (SDATA (msg), buffer, len);
2311178e 5674
796184bc 5675 message_dolog (buffer, len - 1, 1, 0);
937248bc
GM
5676 UNGCPRO;
5677}
5678
5679
5f5c8ee5
GM
5680/* Output a newline in the *Messages* buffer if "needs" one. */
5681
5682void
5683message_log_maybe_newline ()
5684{
5685 if (message_log_need_newline)
5686 message_dolog ("", 0, 1, 0);
5687}
5688
5689
1e313f28 5690/* Add a string M of length NBYTES to the message log, optionally
5f5c8ee5
GM
5691 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
5692 nonzero, means interpret the contents of M as multibyte. This
5693 function calls low-level routines in order to bypass text property
5694 hooks, etc. which might not be safe to run. */
5695
5696void
1e313f28 5697message_dolog (m, nbytes, nlflag, multibyte)
50f80c2f 5698 const char *m;
1e313f28 5699 int nbytes, nlflag, multibyte;
5f5c8ee5 5700{
a67e162b
RS
5701 if (!NILP (Vmemory_full))
5702 return;
5703
5f5c8ee5
GM
5704 if (!NILP (Vmessage_log_max))
5705 {
5706 struct buffer *oldbuf;
5707 Lisp_Object oldpoint, oldbegv, oldzv;
5708 int old_windows_or_buffers_changed = windows_or_buffers_changed;
5709 int point_at_end = 0;
5710 int zv_at_end = 0;
5711 Lisp_Object old_deactivate_mark, tem;
6052529b 5712 struct gcpro gcpro1;
5f5c8ee5
GM
5713
5714 old_deactivate_mark = Vdeactivate_mark;
5715 oldbuf = current_buffer;
6a94510a 5716 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
5f5c8ee5
GM
5717 current_buffer->undo_list = Qt;
5718
b14bc55e
RS
5719 oldpoint = message_dolog_marker1;
5720 set_marker_restricted (oldpoint, make_number (PT), Qnil);
5721 oldbegv = message_dolog_marker2;
5722 set_marker_restricted (oldbegv, make_number (BEGV), Qnil);
5723 oldzv = message_dolog_marker3;
5724 set_marker_restricted (oldzv, make_number (ZV), Qnil);
5725 GCPRO1 (old_deactivate_mark);
5f5c8ee5
GM
5726
5727 if (PT == Z)
5728 point_at_end = 1;
5729 if (ZV == Z)
5730 zv_at_end = 1;
5731
5732 BEGV = BEG;
5733 BEGV_BYTE = BEG_BYTE;
5734 ZV = Z;
5735 ZV_BYTE = Z_BYTE;
5736 TEMP_SET_PT_BOTH (Z, Z_BYTE);
5737
5738 /* Insert the string--maybe converting multibyte to single byte
5739 or vice versa, so that all the text fits the buffer. */
5740 if (multibyte
5741 && NILP (current_buffer->enable_multibyte_characters))
5742 {
1e313f28 5743 int i, c, char_bytes;
5f5c8ee5 5744 unsigned char work[1];
2311178e 5745
5f5c8ee5
GM
5746 /* Convert a multibyte string to single-byte
5747 for the *Message* buffer. */
1e313f28 5748 for (i = 0; i < nbytes; i += nbytes)
5f5c8ee5 5749 {
1e313f28 5750 c = string_char_and_length (m + i, nbytes - i, &char_bytes);
5f5c8ee5
GM
5751 work[0] = (SINGLE_BYTE_CHAR_P (c)
5752 ? c
5753 : multibyte_char_to_unibyte (c, Qnil));
5754 insert_1_both (work, 1, 1, 1, 0, 0);
5755 }
5756 }
5757 else if (! multibyte
5758 && ! NILP (current_buffer->enable_multibyte_characters))
5759 {
1e313f28 5760 int i, c, char_bytes;
5f5c8ee5 5761 unsigned char *msg = (unsigned char *) m;
260a86a0 5762 unsigned char str[MAX_MULTIBYTE_LENGTH];
5f5c8ee5
GM
5763 /* Convert a single-byte string to multibyte
5764 for the *Message* buffer. */
1e313f28 5765 for (i = 0; i < nbytes; i++)
5f5c8ee5
GM
5766 {
5767 c = unibyte_char_to_multibyte (msg[i]);
1e313f28
GM
5768 char_bytes = CHAR_STRING (c, str);
5769 insert_1_both (str, 1, char_bytes, 1, 0, 0);
5f5c8ee5
GM
5770 }
5771 }
1e313f28
GM
5772 else if (nbytes)
5773 insert_1 (m, nbytes, 1, 0, 0);
5f5c8ee5
GM
5774
5775 if (nlflag)
5776 {
5777 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
5778 insert_1 ("\n", 1, 1, 0, 0);
5779
5780 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
5781 this_bol = PT;
5782 this_bol_byte = PT_BYTE;
5783
b14bc55e
RS
5784 /* See if this line duplicates the previous one.
5785 If so, combine duplicates. */
5f5c8ee5
GM
5786 if (this_bol > BEG)
5787 {
5788 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
5789 prev_bol = PT;
5790 prev_bol_byte = PT_BYTE;
5791
5792 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
5793 this_bol, this_bol_byte);
5794 if (dup)
5795 {
5796 del_range_both (prev_bol, prev_bol_byte,
5797 this_bol, this_bol_byte, 0);
5798 if (dup > 1)
5799 {
5800 char dupstr[40];
5801 int duplen;
5802
5803 /* If you change this format, don't forget to also
5804 change message_log_check_duplicate. */
5805 sprintf (dupstr, " [%d times]", dup);
5806 duplen = strlen (dupstr);
5807 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
5808 insert_1 (dupstr, duplen, 1, 0, 1);
5809 }
5810 }
5811 }
5812
b14bc55e
RS
5813 /* If we have more than the desired maximum number of lines
5814 in the *Messages* buffer now, delete the oldest ones.
5815 This is safe because we don't have undo in this buffer. */
5816
5f5c8ee5
GM
5817 if (NATNUMP (Vmessage_log_max))
5818 {
5819 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
5820 -XFASTINT (Vmessage_log_max) - 1, 0);
5821 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
5822 }
5823 }
5824 BEGV = XMARKER (oldbegv)->charpos;
5825 BEGV_BYTE = marker_byte_position (oldbegv);
5826
5827 if (zv_at_end)
5828 {
5829 ZV = Z;
5830 ZV_BYTE = Z_BYTE;
5831 }
5832 else
5833 {
5834 ZV = XMARKER (oldzv)->charpos;
5835 ZV_BYTE = marker_byte_position (oldzv);
5836 }
5837
5838 if (point_at_end)
5839 TEMP_SET_PT_BOTH (Z, Z_BYTE);
5840 else
5841 /* We can't do Fgoto_char (oldpoint) because it will run some
5842 Lisp code. */
5843 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
5844 XMARKER (oldpoint)->bytepos);
5845
5846 UNGCPRO;
b14bc55e
RS
5847 unchain_marker (oldpoint);
5848 unchain_marker (oldbegv);
5849 unchain_marker (oldzv);
5f5c8ee5
GM
5850
5851 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
5852 set_buffer_internal (oldbuf);
5853 if (NILP (tem))
5854 windows_or_buffers_changed = old_windows_or_buffers_changed;
5855 message_log_need_newline = !nlflag;
5856 Vdeactivate_mark = old_deactivate_mark;
5857 }
5858}
5859
5860
5861/* We are at the end of the buffer after just having inserted a newline.
5862 (Note: We depend on the fact we won't be crossing the gap.)
5863 Check to see if the most recent message looks a lot like the previous one.
5864 Return 0 if different, 1 if the new one should just replace it, or a
5865 value N > 1 if we should also append " [N times]". */
5866
5867static int
5868message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
5869 int prev_bol, this_bol;
5870 int prev_bol_byte, this_bol_byte;
5871{
5872 int i;
5873 int len = Z_BYTE - 1 - this_bol_byte;
5874 int seen_dots = 0;
5875 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
5876 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
5877
5878 for (i = 0; i < len; i++)
5879 {
509633e3 5880 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.')
5f5c8ee5
GM
5881 seen_dots = 1;
5882 if (p1[i] != p2[i])
5883 return seen_dots;
5884 }
5885 p1 += len;
5886 if (*p1 == '\n')
5887 return 2;
5888 if (*p1++ == ' ' && *p1++ == '[')
5889 {
5890 int n = 0;
5891 while (*p1 >= '0' && *p1 <= '9')
5892 n = n * 10 + *p1++ - '0';
5893 if (strncmp (p1, " times]\n", 8) == 0)
5894 return n+1;
5895 }
5896 return 0;
5897}
5898
5899
1e313f28
GM
5900/* Display an echo area message M with a specified length of NBYTES
5901 bytes. The string may include null characters. If M is 0, clear
5902 out any existing message, and let the mini-buffer text show
5903 through.
5f5c8ee5
GM
5904
5905 The buffer M must continue to exist until after the echo area gets
5906 cleared or some other message gets displayed there. This means do
5907 not pass text that is stored in a Lisp string; do not pass text in
5908 a buffer that was alloca'd. */
5909
5910void
1e313f28 5911message2 (m, nbytes, multibyte)
50f80c2f 5912 const char *m;
1e313f28 5913 int nbytes;
5f5c8ee5
GM
5914 int multibyte;
5915{
5916 /* First flush out any partial line written with print. */
5917 message_log_maybe_newline ();
5918 if (m)
1e313f28
GM
5919 message_dolog (m, nbytes, 1, multibyte);
5920 message2_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
5921}
5922
5923
5924/* The non-logging counterpart of message2. */
5925
5926void
1e313f28 5927message2_nolog (m, nbytes, multibyte)
50f80c2f 5928 const char *m;
e3383b6f 5929 int nbytes, multibyte;
5f5c8ee5 5930{
886bd6f2 5931 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5932 message_enable_multibyte = multibyte;
5933
5934 if (noninteractive)
5935 {
5936 if (noninteractive_need_newline)
5937 putc ('\n', stderr);
5938 noninteractive_need_newline = 0;
5939 if (m)
1e313f28 5940 fwrite (m, nbytes, 1, stderr);
5f5c8ee5
GM
5941 if (cursor_in_echo_area == 0)
5942 fprintf (stderr, "\n");
5943 fflush (stderr);
5944 }
5945 /* A null message buffer means that the frame hasn't really been
5946 initialized yet. Error messages get reported properly by
5947 cmd_error, so this must be just an informative message; toss it. */
2311178e 5948 else if (INTERACTIVE
886bd6f2
GM
5949 && sf->glyphs_initialized_p
5950 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
5951 {
5952 Lisp_Object mini_window;
5953 struct frame *f;
5954
5955 /* Get the frame containing the mini-buffer
5956 that the selected frame is using. */
886bd6f2 5957 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5958 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5959
5960 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 5961 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
5962 && ! FRAME_VISIBLE_P (f))
5963 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
5964
5965 if (m)
5966 {
1e313f28 5967 set_message (m, Qnil, nbytes, multibyte);
5f5c8ee5
GM
5968 if (minibuffer_auto_raise)
5969 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5970 }
5971 else
c6e89d6c 5972 clear_message (1, 1);
5f5c8ee5 5973
c6e89d6c 5974 do_pending_window_change (0);
5f5c8ee5 5975 echo_area_display (1);
c6e89d6c 5976 do_pending_window_change (0);
5f5c8ee5
GM
5977 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
5978 (*frame_up_to_date_hook) (f);
5979 }
5980}
5981
5982
c6e89d6c
GM
5983/* Display an echo area message M with a specified length of NBYTES
5984 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
5985 string, clear out any existing message, and let the mini-buffer
5986 text show through. */
5987
5988void
c6e89d6c 5989message3 (m, nbytes, multibyte)
5f5c8ee5 5990 Lisp_Object m;
c6e89d6c 5991 int nbytes;
5f5c8ee5
GM
5992 int multibyte;
5993{
5994 struct gcpro gcpro1;
5995
5996 GCPRO1 (m);
2311178e 5997
5f5c8ee5
GM
5998 /* First flush out any partial line written with print. */
5999 message_log_maybe_newline ();
6000 if (STRINGP (m))
2051c264 6001 message_dolog (SDATA (m), nbytes, 1, multibyte);
c6e89d6c 6002 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
6003
6004 UNGCPRO;
6005}
6006
6007
6008/* The non-logging version of message3. */
6009
6010void
c6e89d6c 6011message3_nolog (m, nbytes, multibyte)
5f5c8ee5 6012 Lisp_Object m;
c6e89d6c 6013 int nbytes, multibyte;
5f5c8ee5 6014{
886bd6f2 6015 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6016 message_enable_multibyte = multibyte;
6017
6018 if (noninteractive)
6019 {
6020 if (noninteractive_need_newline)
6021 putc ('\n', stderr);
6022 noninteractive_need_newline = 0;
6023 if (STRINGP (m))
2051c264 6024 fwrite (SDATA (m), nbytes, 1, stderr);
5f5c8ee5
GM
6025 if (cursor_in_echo_area == 0)
6026 fprintf (stderr, "\n");
6027 fflush (stderr);
6028 }
6029 /* A null message buffer means that the frame hasn't really been
6030 initialized yet. Error messages get reported properly by
6031 cmd_error, so this must be just an informative message; toss it. */
2311178e 6032 else if (INTERACTIVE
886bd6f2
GM
6033 && sf->glyphs_initialized_p
6034 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
6035 {
6036 Lisp_Object mini_window;
c6e89d6c 6037 Lisp_Object frame;
5f5c8ee5
GM
6038 struct frame *f;
6039
6040 /* Get the frame containing the mini-buffer
6041 that the selected frame is using. */
886bd6f2 6042 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6043 frame = XWINDOW (mini_window)->frame;
6044 f = XFRAME (frame);
5f5c8ee5
GM
6045
6046 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 6047 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
6048 && !FRAME_VISIBLE_P (f))
6049 Fmake_frame_visible (frame);
5f5c8ee5 6050
2051c264 6051 if (STRINGP (m) && SCHARS (m) > 0)
5f5c8ee5 6052 {
c6e89d6c 6053 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
6054 if (minibuffer_auto_raise)
6055 Fraise_frame (frame);
5f5c8ee5
GM
6056 }
6057 else
c6e89d6c 6058 clear_message (1, 1);
5f5c8ee5 6059
c6e89d6c 6060 do_pending_window_change (0);
5f5c8ee5 6061 echo_area_display (1);
c6e89d6c 6062 do_pending_window_change (0);
5f5c8ee5
GM
6063 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
6064 (*frame_up_to_date_hook) (f);
6065 }
6066}
6067
6068
6069/* Display a null-terminated echo area message M. If M is 0, clear
6070 out any existing message, and let the mini-buffer text show through.
6071
6072 The buffer M must continue to exist until after the echo area gets
6073 cleared or some other message gets displayed there. Do not pass
6074 text that is stored in a Lisp string. Do not pass text in a buffer
6075 that was alloca'd. */
6076
6077void
6078message1 (m)
6079 char *m;
6080{
6081 message2 (m, (m ? strlen (m) : 0), 0);
6082}
6083
6084
6085/* The non-logging counterpart of message1. */
6086
6087void
6088message1_nolog (m)
6089 char *m;
6090{
6091 message2_nolog (m, (m ? strlen (m) : 0), 0);
6092}
6093
6094/* Display a message M which contains a single %s
6095 which gets replaced with STRING. */
6096
6097void
6098message_with_string (m, string, log)
6099 char *m;
6100 Lisp_Object string;
6101 int log;
6102{
5b6d51b6
RS
6103 CHECK_STRING (string);
6104
5f5c8ee5
GM
6105 if (noninteractive)
6106 {
6107 if (m)
6108 {
6109 if (noninteractive_need_newline)
6110 putc ('\n', stderr);
6111 noninteractive_need_newline = 0;
2051c264 6112 fprintf (stderr, m, SDATA (string));
5f5c8ee5
GM
6113 if (cursor_in_echo_area == 0)
6114 fprintf (stderr, "\n");
6115 fflush (stderr);
6116 }
6117 }
6118 else if (INTERACTIVE)
6119 {
6120 /* The frame whose minibuffer we're going to display the message on.
6121 It may be larger than the selected frame, so we need
6122 to use its buffer, not the selected frame's buffer. */
6123 Lisp_Object mini_window;
886bd6f2 6124 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6125
6126 /* Get the frame containing the minibuffer
6127 that the selected frame is using. */
886bd6f2 6128 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6129 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6130
6131 /* A null message buffer means that the frame hasn't really been
6132 initialized yet. Error messages get reported properly by
6133 cmd_error, so this must be just an informative message; toss it. */
6134 if (FRAME_MESSAGE_BUF (f))
6135 {
eb484132
GM
6136 Lisp_Object args[2], message;
6137 struct gcpro gcpro1, gcpro2;
5f5c8ee5 6138
eb484132
GM
6139 args[0] = build_string (m);
6140 args[1] = message = string;
78e17433 6141 GCPRO2 (args[0], message);
eb484132 6142 gcpro1.nvars = 2;
2311178e 6143
eb484132 6144 message = Fformat (2, args);
5f5c8ee5
GM
6145
6146 if (log)
d5db4077 6147 message3 (message, SBYTES (message), STRING_MULTIBYTE (message));
5f5c8ee5 6148 else
d5db4077 6149 message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message));
eb484132
GM
6150
6151 UNGCPRO;
5f5c8ee5
GM
6152
6153 /* Print should start at the beginning of the message
6154 buffer next time. */
6155 message_buf_print = 0;
6156 }
6157 }
6158}
6159
6160
5f5c8ee5
GM
6161/* Dump an informative message to the minibuf. If M is 0, clear out
6162 any existing message, and let the mini-buffer text show through. */
6163
6164/* VARARGS 1 */
6165void
6166message (m, a1, a2, a3)
6167 char *m;
6168 EMACS_INT a1, a2, a3;
6169{
6170 if (noninteractive)
6171 {
6172 if (m)
6173 {
6174 if (noninteractive_need_newline)
6175 putc ('\n', stderr);
6176 noninteractive_need_newline = 0;
6177 fprintf (stderr, m, a1, a2, a3);
6178 if (cursor_in_echo_area == 0)
6179 fprintf (stderr, "\n");
6180 fflush (stderr);
6181 }
6182 }
6183 else if (INTERACTIVE)
6184 {
6185 /* The frame whose mini-buffer we're going to display the message
6186 on. It may be larger than the selected frame, so we need to
6187 use its buffer, not the selected frame's buffer. */
6188 Lisp_Object mini_window;
886bd6f2 6189 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6190
6191 /* Get the frame containing the mini-buffer
6192 that the selected frame is using. */
886bd6f2 6193 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6194 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6195
6196 /* A null message buffer means that the frame hasn't really been
6197 initialized yet. Error messages get reported properly by
6198 cmd_error, so this must be just an informative message; toss
6199 it. */
6200 if (FRAME_MESSAGE_BUF (f))
6201 {
6202 if (m)
6203 {
6204 int len;
6205#ifdef NO_ARG_ARRAY
6206 char *a[3];
6207 a[0] = (char *) a1;
6208 a[1] = (char *) a2;
6209 a[2] = (char *) a3;
6210
6211 len = doprnt (FRAME_MESSAGE_BUF (f),
6212 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
6213#else
6214 len = doprnt (FRAME_MESSAGE_BUF (f),
6215 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
6216 (char **) &a1);
6217#endif /* NO_ARG_ARRAY */
6218
6219 message2 (FRAME_MESSAGE_BUF (f), len, 0);
6220 }
6221 else
6222 message1 (0);
6223
6224 /* Print should start at the beginning of the message
6225 buffer next time. */
6226 message_buf_print = 0;
6227 }
6228 }
6229}
6230
6231
6232/* The non-logging version of message. */
6233
6234void
6235message_nolog (m, a1, a2, a3)
6236 char *m;
6237 EMACS_INT a1, a2, a3;
6238{
6239 Lisp_Object old_log_max;
6240 old_log_max = Vmessage_log_max;
6241 Vmessage_log_max = Qnil;
6242 message (m, a1, a2, a3);
6243 Vmessage_log_max = old_log_max;
6244}
6245
6246
c6e89d6c
GM
6247/* Display the current message in the current mini-buffer. This is
6248 only called from error handlers in process.c, and is not time
6249 critical. */
5f5c8ee5
GM
6250
6251void
6252update_echo_area ()
6253{
c6e89d6c
GM
6254 if (!NILP (echo_area_buffer[0]))
6255 {
6256 Lisp_Object string;
6257 string = Fcurrent_message ();
2311178e 6258 message3 (string, SBYTES (string),
c6e89d6c
GM
6259 !NILP (current_buffer->enable_multibyte_characters));
6260 }
6261}
6262
6263
a67e162b
RS
6264/* Make sure echo area buffers in `echo_buffers' are live.
6265 If they aren't, make new ones. */
5bcfeb49
GM
6266
6267static void
6268ensure_echo_area_buffers ()
6269{
6270 int i;
6271
6272 for (i = 0; i < 2; ++i)
6273 if (!BUFFERP (echo_buffer[i])
6274 || NILP (XBUFFER (echo_buffer[i])->name))
6275 {
6276 char name[30];
ff3d9573
GM
6277 Lisp_Object old_buffer;
6278 int j;
6279
6280 old_buffer = echo_buffer[i];
5bcfeb49
GM
6281 sprintf (name, " *Echo Area %d*", i);
6282 echo_buffer[i] = Fget_buffer_create (build_string (name));
ad4f174e 6283 XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
ff3d9573
GM
6284
6285 for (j = 0; j < 2; ++j)
6286 if (EQ (old_buffer, echo_area_buffer[j]))
6287 echo_area_buffer[j] = echo_buffer[i];
5bcfeb49
GM
6288 }
6289}
6290
6291
23a96c77 6292/* Call FN with args A1..A4 with either the current or last displayed
c6e89d6c
GM
6293 echo_area_buffer as current buffer.
6294
6295 WHICH zero means use the current message buffer
6296 echo_area_buffer[0]. If that is nil, choose a suitable buffer
6297 from echo_buffer[] and clear it.
6298
6299 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
6300 suitable buffer from echo_buffer[] and clear it.
6301
6302 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
6303 that the current message becomes the last displayed one, make
6304 choose a suitable buffer for echo_area_buffer[0], and clear it.
6305
4b41cebb 6306 Value is what FN returns. */
c6e89d6c
GM
6307
6308static int
23a96c77 6309with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
c6e89d6c
GM
6310 struct window *w;
6311 int which;
23dd2d97
KR
6312 int (*fn) P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
6313 EMACS_INT a1;
6314 Lisp_Object a2;
6315 EMACS_INT a3, a4;
c6e89d6c
GM
6316{
6317 Lisp_Object buffer;
15e26c76 6318 int this_one, the_other, clear_buffer_p, rc;
331379bf 6319 int count = SPECPDL_INDEX ();
c6e89d6c 6320
9583b2bb 6321 /* If buffers aren't live, make new ones. */
5bcfeb49 6322 ensure_echo_area_buffers ();
c6e89d6c
GM
6323
6324 clear_buffer_p = 0;
2311178e 6325
c6e89d6c
GM
6326 if (which == 0)
6327 this_one = 0, the_other = 1;
6328 else if (which > 0)
6329 this_one = 1, the_other = 0;
5f5c8ee5 6330 else
c6e89d6c
GM
6331 {
6332 this_one = 0, the_other = 1;
6333 clear_buffer_p = 1;
2311178e 6334
c6e89d6c
GM
6335 /* We need a fresh one in case the current echo buffer equals
6336 the one containing the last displayed echo area message. */
6337 if (!NILP (echo_area_buffer[this_one])
6338 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
6339 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
6340 }
6341
6342 /* Choose a suitable buffer from echo_buffer[] is we don't
6343 have one. */
6344 if (NILP (echo_area_buffer[this_one]))
6345 {
6346 echo_area_buffer[this_one]
6347 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
6348 ? echo_buffer[the_other]
6349 : echo_buffer[this_one]);
6350 clear_buffer_p = 1;
6351 }
6352
6353 buffer = echo_area_buffer[this_one];
6354
1013f4e3
GM
6355 /* Don't get confused by reusing the buffer used for echoing
6356 for a different purpose. */
032906b1 6357 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
1013f4e3
GM
6358 cancel_echoing ();
6359
c6e89d6c
GM
6360 record_unwind_protect (unwind_with_echo_area_buffer,
6361 with_echo_area_buffer_unwind_data (w));
6362
6363 /* Make the echo area buffer current. Note that for display
6364 purposes, it is not necessary that the displayed window's buffer
6365 == current_buffer, except for text property lookup. So, let's
6366 only set that buffer temporarily here without doing a full
6367 Fset_window_buffer. We must also change w->pointm, though,
6368 because otherwise an assertions in unshow_buffer fails, and Emacs
6369 aborts. */
9142dd5b 6370 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
6371 if (w)
6372 {
6373 w->buffer = buffer;
6374 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
6375 }
ad4f174e 6376
c6e89d6c
GM
6377 current_buffer->undo_list = Qt;
6378 current_buffer->read_only = Qnil;
bbbf6d06 6379 specbind (Qinhibit_read_only, Qt);
0b04fa5f 6380 specbind (Qinhibit_modification_hooks, Qt);
c6e89d6c
GM
6381
6382 if (clear_buffer_p && Z > BEG)
6383 del_range (BEG, Z);
6384
6385 xassert (BEGV >= BEG);
6386 xassert (ZV <= Z && ZV >= BEGV);
6387
23a96c77 6388 rc = fn (a1, a2, a3, a4);
c6e89d6c
GM
6389
6390 xassert (BEGV >= BEG);
6391 xassert (ZV <= Z && ZV >= BEGV);
6392
6393 unbind_to (count, Qnil);
6394 return rc;
5f5c8ee5
GM
6395}
6396
6397
c6e89d6c
GM
6398/* Save state that should be preserved around the call to the function
6399 FN called in with_echo_area_buffer. */
5f5c8ee5 6400
c6e89d6c
GM
6401static Lisp_Object
6402with_echo_area_buffer_unwind_data (w)
6403 struct window *w;
5f5c8ee5 6404{
c6e89d6c
GM
6405 int i = 0;
6406 Lisp_Object vector;
5f5c8ee5 6407
c6e89d6c
GM
6408 /* Reduce consing by keeping one vector in
6409 Vwith_echo_area_save_vector. */
6410 vector = Vwith_echo_area_save_vector;
6411 Vwith_echo_area_save_vector = Qnil;
2311178e 6412
c6e89d6c 6413 if (NILP (vector))
9142dd5b 6414 vector = Fmake_vector (make_number (7), Qnil);
2311178e 6415
a61b7058
GM
6416 XSETBUFFER (AREF (vector, i), current_buffer); ++i;
6417 AREF (vector, i) = Vdeactivate_mark, ++i;
6418 AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
2311178e 6419
c6e89d6c
GM
6420 if (w)
6421 {
a61b7058
GM
6422 XSETWINDOW (AREF (vector, i), w); ++i;
6423 AREF (vector, i) = w->buffer; ++i;
6424 AREF (vector, i) = make_number (XMARKER (w->pointm)->charpos); ++i;
6425 AREF (vector, i) = make_number (XMARKER (w->pointm)->bytepos); ++i;
c6e89d6c
GM
6426 }
6427 else
6428 {
6429 int end = i + 4;
a61b7058
GM
6430 for (; i < end; ++i)
6431 AREF (vector, i) = Qnil;
c6e89d6c 6432 }
5f5c8ee5 6433
a61b7058 6434 xassert (i == ASIZE (vector));
c6e89d6c
GM
6435 return vector;
6436}
5f5c8ee5 6437
5f5c8ee5 6438
c6e89d6c
GM
6439/* Restore global state from VECTOR which was created by
6440 with_echo_area_buffer_unwind_data. */
6441
6442static Lisp_Object
6443unwind_with_echo_area_buffer (vector)
6444 Lisp_Object vector;
6445{
bbbf6d06
GM
6446 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
6447 Vdeactivate_mark = AREF (vector, 1);
6448 windows_or_buffers_changed = XFASTINT (AREF (vector, 2));
c6e89d6c 6449
bbbf6d06 6450 if (WINDOWP (AREF (vector, 3)))
c6e89d6c
GM
6451 {
6452 struct window *w;
6453 Lisp_Object buffer, charpos, bytepos;
2311178e 6454
bbbf6d06
GM
6455 w = XWINDOW (AREF (vector, 3));
6456 buffer = AREF (vector, 4);
6457 charpos = AREF (vector, 5);
6458 bytepos = AREF (vector, 6);
2311178e 6459
c6e89d6c
GM
6460 w->buffer = buffer;
6461 set_marker_both (w->pointm, buffer,
6462 XFASTINT (charpos), XFASTINT (bytepos));
6463 }
6464
6465 Vwith_echo_area_save_vector = vector;
6466 return Qnil;
6467}
6468
6469
6470/* Set up the echo area for use by print functions. MULTIBYTE_P
6471 non-zero means we will print multibyte. */
6472
6473void
6474setup_echo_area_for_printing (multibyte_p)
6475 int multibyte_p;
6476{
5bcfeb49
GM
6477 ensure_echo_area_buffers ();
6478
c6e89d6c
GM
6479 if (!message_buf_print)
6480 {
6481 /* A message has been output since the last time we printed.
6482 Choose a fresh echo area buffer. */
6483 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 6484 echo_area_buffer[0] = echo_buffer[1];
c6e89d6c
GM
6485 else
6486 echo_area_buffer[0] = echo_buffer[0];
6487
6488 /* Switch to that buffer and clear it. */
6489 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
ab2c5f0a 6490 current_buffer->truncate_lines = Qnil;
2311178e 6491
c6e89d6c 6492 if (Z > BEG)
bbbf6d06 6493 {
331379bf 6494 int count = SPECPDL_INDEX ();
bbbf6d06 6495 specbind (Qinhibit_read_only, Qt);
a67e162b 6496 /* Note that undo recording is always disabled. */
bbbf6d06
GM
6497 del_range (BEG, Z);
6498 unbind_to (count, Qnil);
6499 }
c6e89d6c
GM
6500 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
6501
6502 /* Set up the buffer for the multibyteness we need. */
6503 if (multibyte_p
6504 != !NILP (current_buffer->enable_multibyte_characters))
6505 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
6506
6507 /* Raise the frame containing the echo area. */
6508 if (minibuffer_auto_raise)
6509 {
886bd6f2 6510 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 6511 Lisp_Object mini_window;
886bd6f2 6512 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6513 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
6514 }
6515
8a4e3c0c 6516 message_log_maybe_newline ();
c6e89d6c
GM
6517 message_buf_print = 1;
6518 }
fa77249f
GM
6519 else
6520 {
6521 if (NILP (echo_area_buffer[0]))
6522 {
6523 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 6524 echo_area_buffer[0] = echo_buffer[1];
fa77249f
GM
6525 else
6526 echo_area_buffer[0] = echo_buffer[0];
6527 }
2311178e 6528
fa77249f 6529 if (current_buffer != XBUFFER (echo_area_buffer[0]))
ab2c5f0a
GM
6530 {
6531 /* Someone switched buffers between print requests. */
6532 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
6533 current_buffer->truncate_lines = Qnil;
6534 }
fa77249f 6535 }
c6e89d6c
GM
6536}
6537
6538
dd2eb166
GM
6539/* Display an echo area message in window W. Value is non-zero if W's
6540 height is changed. If display_last_displayed_message_p is
6541 non-zero, display the message that was last displayed, otherwise
6542 display the current message. */
c6e89d6c
GM
6543
6544static int
6545display_echo_area (w)
6546 struct window *w;
6547{
25edb08f
GM
6548 int i, no_message_p, window_height_changed_p, count;
6549
6550 /* Temporarily disable garbage collections while displaying the echo
6551 area. This is done because a GC can print a message itself.
6552 That message would modify the echo area buffer's contents while a
6553 redisplay of the buffer is going on, and seriously confuse
6554 redisplay. */
6555 count = inhibit_garbage_collection ();
dd2eb166
GM
6556
6557 /* If there is no message, we must call display_echo_area_1
6558 nevertheless because it resizes the window. But we will have to
6559 reset the echo_area_buffer in question to nil at the end because
6560 with_echo_area_buffer will sets it to an empty buffer. */
6561 i = display_last_displayed_message_p ? 1 : 0;
6562 no_message_p = NILP (echo_area_buffer[i]);
2311178e 6563
dd2eb166
GM
6564 window_height_changed_p
6565 = with_echo_area_buffer (w, display_last_displayed_message_p,
23a96c77 6566 display_echo_area_1,
23dd2d97 6567 (EMACS_INT) w, Qnil, 0, 0);
dd2eb166
GM
6568
6569 if (no_message_p)
6570 echo_area_buffer[i] = Qnil;
25edb08f
GM
6571
6572 unbind_to (count, Qnil);
dd2eb166 6573 return window_height_changed_p;
c6e89d6c
GM
6574}
6575
6576
6577/* Helper for display_echo_area. Display the current buffer which
23a96c77
GM
6578 contains the current echo area message in window W, a mini-window,
6579 a pointer to which is passed in A1. A2..A4 are currently not used.
c6e89d6c
GM
6580 Change the height of W so that all of the message is displayed.
6581 Value is non-zero if height of W was changed. */
6582
6583static int
23a96c77 6584display_echo_area_1 (a1, a2, a3, a4)
23dd2d97
KR
6585 EMACS_INT a1;
6586 Lisp_Object a2;
6587 EMACS_INT a3, a4;
c6e89d6c 6588{
23a96c77 6589 struct window *w = (struct window *) a1;
c6e89d6c 6590 Lisp_Object window;
c6e89d6c
GM
6591 struct text_pos start;
6592 int window_height_changed_p = 0;
6593
6594 /* Do this before displaying, so that we have a large enough glyph
6595 matrix for the display. */
92a90e89 6596 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
6597
6598 /* Display. */
6599 clear_glyph_matrix (w->desired_matrix);
6600 XSETWINDOW (window, w);
6601 SET_TEXT_POS (start, BEG, BEG_BYTE);
6602 try_window (window, start);
6603
c6e89d6c
GM
6604 return window_height_changed_p;
6605}
6606
6607
92a90e89 6608/* Resize the echo area window to exactly the size needed for the
6d004fea
GM
6609 currently displayed message, if there is one. If a mini-buffer
6610 is active, don't shrink it. */
92a90e89
GM
6611
6612void
308a74d8 6613resize_echo_area_exactly ()
92a90e89
GM
6614{
6615 if (BUFFERP (echo_area_buffer[0])
6616 && WINDOWP (echo_area_window))
6617 {
6618 struct window *w = XWINDOW (echo_area_window);
6619 int resized_p;
6d004fea
GM
6620 Lisp_Object resize_exactly;
6621
6622 if (minibuf_level == 0)
6623 resize_exactly = Qt;
6624 else
6625 resize_exactly = Qnil;
2311178e 6626
23a96c77 6627 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
6d004fea 6628 (EMACS_INT) w, resize_exactly, 0, 0);
92a90e89
GM
6629 if (resized_p)
6630 {
6631 ++windows_or_buffers_changed;
6632 ++update_mode_lines;
6633 redisplay_internal (0);
6634 }
6635 }
6636}
6637
6638
23a96c77 6639/* Callback function for with_echo_area_buffer, when used from
308a74d8 6640 resize_echo_area_exactly. A1 contains a pointer to the window to
6d004fea
GM
6641 resize, EXACTLY non-nil means resize the mini-window exactly to the
6642 size of the text displayed. A3 and A4 are not used. Value is what
6643 resize_mini_window returns. */
23a96c77
GM
6644
6645static int
6d004fea 6646resize_mini_window_1 (a1, exactly, a3, a4)
23dd2d97 6647 EMACS_INT a1;
6d004fea 6648 Lisp_Object exactly;
23dd2d97 6649 EMACS_INT a3, a4;
23a96c77 6650{
6d004fea 6651 return resize_mini_window ((struct window *) a1, !NILP (exactly));
23a96c77
GM
6652}
6653
6654
92a90e89
GM
6655/* Resize mini-window W to fit the size of its contents. EXACT:P
6656 means size the window exactly to the size needed. Otherwise, it's
6657 only enlarged until W's buffer is empty. Value is non-zero if
4b41cebb 6658 the window height has been changed. */
c6e89d6c 6659
9472f927 6660int
92a90e89 6661resize_mini_window (w, exact_p)
c6e89d6c 6662 struct window *w;
92a90e89 6663 int exact_p;
c6e89d6c
GM
6664{
6665 struct frame *f = XFRAME (w->frame);
6666 int window_height_changed_p = 0;
6667
6668 xassert (MINI_WINDOW_P (w));
97cafc0f 6669
2913a9c0
GM
6670 /* Don't resize windows while redisplaying a window; it would
6671 confuse redisplay functions when the size of the window they are
6672 displaying changes from under them. Such a resizing can happen,
6673 for instance, when which-func prints a long message while
6674 we are running fontification-functions. We're running these
6675 functions with safe_call which binds inhibit-redisplay to t. */
6676 if (!NILP (Vinhibit_redisplay))
64c5be50 6677 return 0;
2311178e 6678
97cafc0f 6679 /* Nil means don't try to resize. */
6422c1d7 6680 if (NILP (Vresize_mini_windows)
00f6d59e 6681 || (FRAME_X_P (f) && f->output_data.x == NULL))
97cafc0f 6682 return 0;
2311178e 6683
c6e89d6c
GM
6684 if (!FRAME_MINIBUF_ONLY_P (f))
6685 {
6686 struct it it;
dd2eb166
GM
6687 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
6688 int total_height = XFASTINT (root->height) + XFASTINT (w->height);
6689 int height, max_height;
6690 int unit = CANON_Y_UNIT (f);
6691 struct text_pos start;
1bfdbe43
GM
6692 struct buffer *old_current_buffer = NULL;
6693
6694 if (current_buffer != XBUFFER (w->buffer))
6695 {
6696 old_current_buffer = current_buffer;
6697 set_buffer_internal (XBUFFER (w->buffer));
6698 }
9142dd5b 6699
c6e89d6c 6700 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 6701
dd2eb166
GM
6702 /* Compute the max. number of lines specified by the user. */
6703 if (FLOATP (Vmax_mini_window_height))
18f9986a 6704 max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_HEIGHT (f);
dd2eb166
GM
6705 else if (INTEGERP (Vmax_mini_window_height))
6706 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
6707 else
6708 max_height = total_height / 4;
2311178e 6709
4b41cebb 6710 /* Correct that max. height if it's bogus. */
dd2eb166
GM
6711 max_height = max (1, max_height);
6712 max_height = min (total_height, max_height);
2311178e 6713
dd2eb166 6714 /* Find out the height of the text in the window. */
ad4f174e
GM
6715 if (it.truncate_lines_p)
6716 height = 1;
55b064bd 6717 else
ad4f174e
GM
6718 {
6719 last_height = 0;
6720 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
6721 if (it.max_ascent == 0 && it.max_descent == 0)
6722 height = it.current_y + last_height;
6723 else
6724 height = it.current_y + it.max_ascent + it.max_descent;
3c4b7685 6725 height -= it.extra_line_spacing;
ad4f174e
GM
6726 height = (height + unit - 1) / unit;
6727 }
2311178e 6728
dd2eb166
GM
6729 /* Compute a suitable window start. */
6730 if (height > max_height)
6731 {
6732 height = max_height;
6733 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
6734 move_it_vertically_backward (&it, (height - 1) * unit);
6735 start = it.current.pos;
6736 }
6737 else
6738 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
6739 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 6740
6422c1d7 6741 if (EQ (Vresize_mini_windows, Qgrow_only))
dd2eb166 6742 {
6422c1d7
GM
6743 /* Let it grow only, until we display an empty message, in which
6744 case the window shrinks again. */
6745 if (height > XFASTINT (w->height))
6746 {
6747 int old_height = XFASTINT (w->height);
6748 freeze_window_starts (f, 1);
6749 grow_mini_window (w, height - XFASTINT (w->height));
6750 window_height_changed_p = XFASTINT (w->height) != old_height;
6751 }
6752 else if (height < XFASTINT (w->height)
6753 && (exact_p || BEGV == ZV))
6754 {
6755 int old_height = XFASTINT (w->height);
6756 freeze_window_starts (f, 0);
6757 shrink_mini_window (w);
6758 window_height_changed_p = XFASTINT (w->height) != old_height;
6759 }
da448723 6760 }
2311178e 6761 else
da448723 6762 {
6422c1d7
GM
6763 /* Always resize to exact size needed. */
6764 if (height > XFASTINT (w->height))
6765 {
6766 int old_height = XFASTINT (w->height);
6767 freeze_window_starts (f, 1);
6768 grow_mini_window (w, height - XFASTINT (w->height));
6769 window_height_changed_p = XFASTINT (w->height) != old_height;
6770 }
6771 else if (height < XFASTINT (w->height))
6772 {
6773 int old_height = XFASTINT (w->height);
6774 freeze_window_starts (f, 0);
6775 shrink_mini_window (w);
6776
6777 if (height)
6778 {
6779 freeze_window_starts (f, 1);
6780 grow_mini_window (w, height - XFASTINT (w->height));
6781 }
2311178e 6782
6422c1d7
GM
6783 window_height_changed_p = XFASTINT (w->height) != old_height;
6784 }
9142dd5b 6785 }
1bfdbe43
GM
6786
6787 if (old_current_buffer)
6788 set_buffer_internal (old_current_buffer);
c6e89d6c
GM
6789 }
6790
6791 return window_height_changed_p;
6792}
6793
6794
6795/* Value is the current message, a string, or nil if there is no
6796 current message. */
6797
6798Lisp_Object
6799current_message ()
6800{
6801 Lisp_Object msg;
6802
6803 if (NILP (echo_area_buffer[0]))
6804 msg = Qnil;
6805 else
6806 {
23a96c77 6807 with_echo_area_buffer (0, 0, current_message_1,
23dd2d97 6808 (EMACS_INT) &msg, Qnil, 0, 0);
c6e89d6c
GM
6809 if (NILP (msg))
6810 echo_area_buffer[0] = Qnil;
6811 }
2311178e 6812
c6e89d6c
GM
6813 return msg;
6814}
6815
6816
6817static int
23a96c77 6818current_message_1 (a1, a2, a3, a4)
23dd2d97
KR
6819 EMACS_INT a1;
6820 Lisp_Object a2;
6821 EMACS_INT a3, a4;
c6e89d6c 6822{
23a96c77 6823 Lisp_Object *msg = (Lisp_Object *) a1;
2311178e 6824
c6e89d6c
GM
6825 if (Z > BEG)
6826 *msg = make_buffer_string (BEG, Z, 1);
6827 else
6828 *msg = Qnil;
6829 return 0;
6830}
6831
6832
6833/* Push the current message on Vmessage_stack for later restauration
6834 by restore_message. Value is non-zero if the current message isn't
6835 empty. This is a relatively infrequent operation, so it's not
6836 worth optimizing. */
6837
6838int
6839push_message ()
6840{
6841 Lisp_Object msg;
6842 msg = current_message ();
6843 Vmessage_stack = Fcons (msg, Vmessage_stack);
6844 return STRINGP (msg);
6845}
6846
6847
6848/* Restore message display from the top of Vmessage_stack. */
6849
6850void
6851restore_message ()
6852{
6853 Lisp_Object msg;
2311178e 6854
c6e89d6c
GM
6855 xassert (CONSP (Vmessage_stack));
6856 msg = XCAR (Vmessage_stack);
6857 if (STRINGP (msg))
d5db4077 6858 message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
c6e89d6c
GM
6859 else
6860 message3_nolog (msg, 0, 0);
6861}
6862
6863
37d66095
RS
6864/* Handler for record_unwind_protect calling pop_message. */
6865
6866Lisp_Object
6867pop_message_unwind (dummy)
6868 Lisp_Object dummy;
6869{
6870 pop_message ();
6871 return Qnil;
6872}
6873
c6e89d6c
GM
6874/* Pop the top-most entry off Vmessage_stack. */
6875
6876void
6877pop_message ()
6878{
6879 xassert (CONSP (Vmessage_stack));
6880 Vmessage_stack = XCDR (Vmessage_stack);
6881}
6882
6883
6884/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
6885 exits. If the stack is not empty, we have a missing pop_message
6886 somewhere. */
6887
6888void
6889check_message_stack ()
6890{
6891 if (!NILP (Vmessage_stack))
6892 abort ();
6893}
6894
6895
6896/* Truncate to NCHARS what will be displayed in the echo area the next
6897 time we display it---but don't redisplay it now. */
6898
6899void
6900truncate_echo_area (nchars)
6901 int nchars;
6902{
6903 if (nchars == 0)
6904 echo_area_buffer[0] = Qnil;
6905 /* A null message buffer means that the frame hasn't really been
6906 initialized yet. Error messages get reported properly by
6907 cmd_error, so this must be just an informative message; toss it. */
6908 else if (!noninteractive
6909 && INTERACTIVE
c6e89d6c 6910 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
6911 {
6912 struct frame *sf = SELECTED_FRAME ();
6913 if (FRAME_MESSAGE_BUF (sf))
23dd2d97 6914 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0);
886bd6f2 6915 }
c6e89d6c
GM
6916}
6917
6918
6919/* Helper function for truncate_echo_area. Truncate the current
6920 message to at most NCHARS characters. */
6921
6922static int
23a96c77 6923truncate_message_1 (nchars, a2, a3, a4)
23dd2d97
KR
6924 EMACS_INT nchars;
6925 Lisp_Object a2;
6926 EMACS_INT a3, a4;
c6e89d6c
GM
6927{
6928 if (BEG + nchars < Z)
6929 del_range (BEG + nchars, Z);
6930 if (Z == BEG)
6931 echo_area_buffer[0] = Qnil;
6932 return 0;
6933}
6934
6935
6936/* Set the current message to a substring of S or STRING.
6937
6938 If STRING is a Lisp string, set the message to the first NBYTES
6939 bytes from STRING. NBYTES zero means use the whole string. If
6940 STRING is multibyte, the message will be displayed multibyte.
6941
6942 If S is not null, set the message to the first LEN bytes of S. LEN
6943 zero means use the whole string. MULTIBYTE_P non-zero means S is
6944 multibyte. Display the message multibyte in that case. */
6945
6946void
6947set_message (s, string, nbytes, multibyte_p)
50f80c2f 6948 const char *s;
c6e89d6c 6949 Lisp_Object string;
e3383b6f 6950 int nbytes, multibyte_p;
c6e89d6c
GM
6951{
6952 message_enable_multibyte
6953 = ((s && multibyte_p)
6954 || (STRINGP (string) && STRING_MULTIBYTE (string)));
2311178e 6955
23a96c77
GM
6956 with_echo_area_buffer (0, -1, set_message_1,
6957 (EMACS_INT) s, string, nbytes, multibyte_p);
c6e89d6c 6958 message_buf_print = 0;
21fdfb65 6959 help_echo_showing_p = 0;
c6e89d6c
GM
6960}
6961
6962
6963/* Helper function for set_message. Arguments have the same meaning
23a96c77
GM
6964 as there, with A1 corresponding to S and A2 corresponding to STRING
6965 This function is called with the echo area buffer being
c6e89d6c
GM
6966 current. */
6967
6968static int
23a96c77 6969set_message_1 (a1, a2, nbytes, multibyte_p)
23dd2d97
KR
6970 EMACS_INT a1;
6971 Lisp_Object a2;
6972 EMACS_INT nbytes, multibyte_p;
c6e89d6c 6973{
50f80c2f 6974 const char *s = (const char *) a1;
23dd2d97 6975 Lisp_Object string = a2;
2311178e 6976
c6e89d6c 6977 xassert (BEG == Z);
2311178e 6978
c6e89d6c
GM
6979 /* Change multibyteness of the echo buffer appropriately. */
6980 if (message_enable_multibyte
6981 != !NILP (current_buffer->enable_multibyte_characters))
6982 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
6983
ad4f174e 6984 current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
2311178e 6985
c6e89d6c
GM
6986 /* Insert new message at BEG. */
6987 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
6988
6989 if (STRINGP (string))
6990 {
6991 int nchars;
2311178e 6992
c6e89d6c 6993 if (nbytes == 0)
2051c264 6994 nbytes = SBYTES (string);
c6e89d6c 6995 nchars = string_byte_to_char (string, nbytes);
2311178e 6996
c6e89d6c
GM
6997 /* This function takes care of single/multibyte conversion. We
6998 just have to ensure that the echo area buffer has the right
6999 setting of enable_multibyte_characters. */
7000 insert_from_string (string, 0, 0, nchars, nbytes, 1);
7001 }
7002 else if (s)
7003 {
7004 if (nbytes == 0)
7005 nbytes = strlen (s);
2311178e 7006
c6e89d6c
GM
7007 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
7008 {
7009 /* Convert from multi-byte to single-byte. */
7010 int i, c, n;
7011 unsigned char work[1];
2311178e 7012
c6e89d6c
GM
7013 /* Convert a multibyte string to single-byte. */
7014 for (i = 0; i < nbytes; i += n)
7015 {
7016 c = string_char_and_length (s + i, nbytes - i, &n);
7017 work[0] = (SINGLE_BYTE_CHAR_P (c)
7018 ? c
7019 : multibyte_char_to_unibyte (c, Qnil));
7020 insert_1_both (work, 1, 1, 1, 0, 0);
7021 }
7022 }
7023 else if (!multibyte_p
7024 && !NILP (current_buffer->enable_multibyte_characters))
7025 {
7026 /* Convert from single-byte to multi-byte. */
7027 int i, c, n;
50f80c2f 7028 const unsigned char *msg = (const unsigned char *) s;
260a86a0 7029 unsigned char str[MAX_MULTIBYTE_LENGTH];
2311178e 7030
c6e89d6c
GM
7031 /* Convert a single-byte string to multibyte. */
7032 for (i = 0; i < nbytes; i++)
7033 {
7034 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
7035 n = CHAR_STRING (c, str);
7036 insert_1_both (str, 1, n, 1, 0, 0);
c6e89d6c
GM
7037 }
7038 }
7039 else
7040 insert_1 (s, nbytes, 1, 0, 0);
7041 }
7042
7043 return 0;
7044}
7045
7046
7047/* Clear messages. CURRENT_P non-zero means clear the current
7048 message. LAST_DISPLAYED_P non-zero means clear the message
7049 last displayed. */
7050
7051void
7052clear_message (current_p, last_displayed_p)
7053 int current_p, last_displayed_p;
7054{
7055 if (current_p)
6e019995
GM
7056 {
7057 echo_area_buffer[0] = Qnil;
7058 message_cleared_p = 1;
7059 }
2311178e 7060
c6e89d6c
GM
7061 if (last_displayed_p)
7062 echo_area_buffer[1] = Qnil;
2311178e 7063
c6e89d6c
GM
7064 message_buf_print = 0;
7065}
7066
7067/* Clear garbaged frames.
7068
7069 This function is used where the old redisplay called
7070 redraw_garbaged_frames which in turn called redraw_frame which in
7071 turn called clear_frame. The call to clear_frame was a source of
7072 flickering. I believe a clear_frame is not necessary. It should
7073 suffice in the new redisplay to invalidate all current matrices,
7074 and ensure a complete redisplay of all windows. */
7075
7076static void
7077clear_garbaged_frames ()
7078{
5f5c8ee5
GM
7079 if (frame_garbaged)
7080 {
5f5c8ee5 7081 Lisp_Object tail, frame;
5fb96e96 7082 int changed_count = 0;
2311178e 7083
5f5c8ee5
GM
7084 FOR_EACH_FRAME (tail, frame)
7085 {
7086 struct frame *f = XFRAME (frame);
2311178e 7087
5f5c8ee5
GM
7088 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
7089 {
6bb95882 7090 if (f->resized_p)
573e57f1 7091 Fredraw_frame (frame);
5f5c8ee5 7092 clear_current_matrices (f);
5fb96e96 7093 changed_count++;
5f5c8ee5 7094 f->garbaged = 0;
6bb95882 7095 f->resized_p = 0;
5f5c8ee5
GM
7096 }
7097 }
7098
7099 frame_garbaged = 0;
5fb96e96
RS
7100 if (changed_count)
7101 ++windows_or_buffers_changed;
5f5c8ee5 7102 }
c6e89d6c 7103}
5f5c8ee5 7104
5f5c8ee5 7105
886bd6f2
GM
7106/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
7107 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 7108 mini-windows height has been changed. */
5f5c8ee5 7109
c6e89d6c
GM
7110static int
7111echo_area_display (update_frame_p)
7112 int update_frame_p;
7113{
7114 Lisp_Object mini_window;
7115 struct window *w;
7116 struct frame *f;
7117 int window_height_changed_p = 0;
886bd6f2 7118 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 7119
886bd6f2 7120 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
7121 w = XWINDOW (mini_window);
7122 f = XFRAME (WINDOW_FRAME (w));
7123
7124 /* Don't display if frame is invisible or not yet initialized. */
7125 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
7126 return 0;
5f5c8ee5 7127
1a578e9b 7128/* The terminal frame is used as the first Emacs frame on the Mac OS. */
e0f712ba 7129#ifndef MAC_OS8
1ab3e082 7130#ifdef HAVE_WINDOW_SYSTEM
c6e89d6c
GM
7131 /* When Emacs starts, selected_frame may be a visible terminal
7132 frame, even if we run under a window system. If we let this
7133 through, a message would be displayed on the terminal. */
2311178e 7134 if (EQ (selected_frame, Vterminal_frame)
622e3754 7135 && !NILP (Vwindow_system))
c6e89d6c 7136 return 0;
1ab3e082 7137#endif /* HAVE_WINDOW_SYSTEM */
1a578e9b 7138#endif
c6e89d6c
GM
7139
7140 /* Redraw garbaged frames. */
7141 if (frame_garbaged)
7142 clear_garbaged_frames ();
7143
7144 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
7145 {
7146 echo_area_window = mini_window;
7147 window_height_changed_p = display_echo_area (w);
5f5c8ee5 7148 w->must_be_updated_p = 1;
c59c668a 7149
d4358b37
GM
7150 /* Update the display, unless called from redisplay_internal.
7151 Also don't update the screen during redisplay itself. The
7152 update will happen at the end of redisplay, and an update
7153 here could cause confusion. */
7154 if (update_frame_p && !redisplaying_p)
5f5c8ee5 7155 {
715e84c9 7156 int n = 0;
edc68111 7157
715e84c9
GM
7158 /* If the display update has been interrupted by pending
7159 input, update mode lines in the frame. Due to the
7160 pending input, it might have been that redisplay hasn't
7161 been called, so that mode lines above the echo area are
7162 garbaged. This looks odd, so we prevent it here. */
7163 if (!display_completed)
7164 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
2311178e 7165
8af1308e
GM
7166 if (window_height_changed_p
7167 /* Don't do this if Emacs is shutting down. Redisplay
7168 needs to run hooks. */
7169 && !NILP (Vrun_hooks))
c59c668a 7170 {
c06017fb
GM
7171 /* Must update other windows. Likewise as in other
7172 cases, don't let this update be interrupted by
7173 pending input. */
331379bf 7174 int count = SPECPDL_INDEX ();
c06017fb 7175 specbind (Qredisplay_dont_pause, Qt);
edc68111 7176 windows_or_buffers_changed = 1;
c59c668a 7177 redisplay_internal (0);
c06017fb 7178 unbind_to (count, Qnil);
c59c668a 7179 }
715e84c9 7180 else if (FRAME_WINDOW_P (f) && n == 0)
5f5c8ee5 7181 {
edc68111 7182 /* Window configuration is the same as before.
715e84c9
GM
7183 Can do with a display update of the echo area,
7184 unless we displayed some mode lines. */
5f5c8ee5
GM
7185 update_single_window (w, 1);
7186 rif->flush_display (f);
7187 }
7188 else
7189 update_frame (f, 1, 1);
31b6671b
GM
7190
7191 /* If cursor is in the echo area, make sure that the next
7192 redisplay displays the minibuffer, so that the cursor will
7193 be replaced with what the minibuffer wants. */
7194 if (cursor_in_echo_area)
7195 ++windows_or_buffers_changed;
5f5c8ee5
GM
7196 }
7197 }
7198 else if (!EQ (mini_window, selected_window))
7199 windows_or_buffers_changed++;
c59c668a
GM
7200
7201 /* Last displayed message is now the current message. */
dd2eb166 7202 echo_area_buffer[1] = echo_area_buffer[0];
2311178e 7203
5f5c8ee5
GM
7204 /* Prevent redisplay optimization in redisplay_internal by resetting
7205 this_line_start_pos. This is done because the mini-buffer now
7206 displays the message instead of its buffer text. */
7207 if (EQ (mini_window, selected_window))
7208 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
7209
7210 return window_height_changed_p;
5f5c8ee5
GM
7211}
7212
7213
7214\f
7215/***********************************************************************
7216 Frame Titles
7217 ***********************************************************************/
7218
7219
8143e6ab
KS
7220/* The frame title buffering code is also used by Fformat_mode_line.
7221 So it is not conditioned by HAVE_WINDOW_SYSTEM. */
5f5c8ee5
GM
7222
7223/* A buffer for constructing frame titles in it; allocated from the
7224 heap in init_xdisp and resized as needed in store_frame_title_char. */
7225
7226static char *frame_title_buf;
7227
7228/* The buffer's end, and a current output position in it. */
7229
7230static char *frame_title_buf_end;
7231static char *frame_title_ptr;
7232
7233
7234/* Store a single character C for the frame title in frame_title_buf.
7235 Re-allocate frame_title_buf if necessary. */
7236
7237static void
7238store_frame_title_char (c)
7239 char c;
7240{
7241 /* If output position has reached the end of the allocated buffer,
7242 double the buffer's size. */
7243 if (frame_title_ptr == frame_title_buf_end)
7244 {
7245 int len = frame_title_ptr - frame_title_buf;
7246 int new_size = 2 * len * sizeof *frame_title_buf;
7247 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
7248 frame_title_buf_end = frame_title_buf + new_size;
7249 frame_title_ptr = frame_title_buf + len;
7250 }
7251
7252 *frame_title_ptr++ = c;
7253}
7254
7255
7256/* Store part of a frame title in frame_title_buf, beginning at
d26b89b8
KH
7257 frame_title_ptr. STR is the string to store. Do not copy
7258 characters that yield more columns than PRECISION; PRECISION <= 0
7259 means copy the whole string. Pad with spaces until FIELD_WIDTH
7260 number of characters have been copied; FIELD_WIDTH <= 0 means don't
7261 pad. Called from display_mode_element when it is used to build a
7262 frame title. */
5f5c8ee5
GM
7263
7264static int
7265store_frame_title (str, field_width, precision)
50f80c2f 7266 const unsigned char *str;
5f5c8ee5
GM
7267 int field_width, precision;
7268{
7269 int n = 0;
3b552d56 7270 int dummy, nbytes;
5f5c8ee5
GM
7271
7272 /* Copy at most PRECISION chars from STR. */
d26b89b8
KH
7273 nbytes = strlen (str);
7274 n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
7275 while (nbytes--)
7276 store_frame_title_char (*str++);
5f5c8ee5
GM
7277
7278 /* Fill up with spaces until FIELD_WIDTH reached. */
7279 while (field_width > 0
7280 && n < field_width)
7281 {
7282 store_frame_title_char (' ');
7283 ++n;
7284 }
7285
7286 return n;
7287}
7288
8143e6ab 7289#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
7290
7291/* Set the title of FRAME, if it has changed. The title format is
7292 Vicon_title_format if FRAME is iconified, otherwise it is
7293 frame_title_format. */
7294
7295static void
7296x_consider_frame_title (frame)
7297 Lisp_Object frame;
7298{
7299 struct frame *f = XFRAME (frame);
7300
7301 if (FRAME_WINDOW_P (f)
7302 || FRAME_MINIBUF_ONLY_P (f)
7303 || f->explicit_name)
7304 {
7305 /* Do we have more than one visible frame on this X display? */
7306 Lisp_Object tail;
7307 Lisp_Object fmt;
7308 struct buffer *obuf;
7309 int len;
7310 struct it it;
7311
9472f927 7312 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 7313 {
74779f52
JR
7314 Lisp_Object other_frame = XCAR (tail);
7315 struct frame *tf = XFRAME (other_frame);
5f5c8ee5 7316
2311178e 7317 if (tf != f
5f5c8ee5
GM
7318 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
7319 && !FRAME_MINIBUF_ONLY_P (tf)
74779f52 7320 && !EQ (other_frame, tip_frame)
5f5c8ee5
GM
7321 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
7322 break;
7323 }
7324
7325 /* Set global variable indicating that multiple frames exist. */
7326 multiple_frames = CONSP (tail);
7327
7328 /* Switch to the buffer of selected window of the frame. Set up
7329 frame_title_ptr so that display_mode_element will output into it;
7330 then display the title. */
7331 obuf = current_buffer;
bb336f8d 7332 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
5f5c8ee5
GM
7333 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
7334 frame_title_ptr = frame_title_buf;
7335 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
7336 NULL, DEFAULT_FACE_ID);
c53a1624 7337 display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
d26b89b8 7338 len = frame_title_ptr - frame_title_buf;
5f5c8ee5 7339 frame_title_ptr = NULL;
bb336f8d 7340 set_buffer_internal_1 (obuf);
5f5c8ee5
GM
7341
7342 /* Set the title only if it's changed. This avoids consing in
7343 the common case where it hasn't. (If it turns out that we've
7344 already wasted too much time by walking through the list with
7345 display_mode_element, then we might need to optimize at a
7346 higher level than this.) */
2311178e 7347 if (! STRINGP (f->name)
2051c264
GM
7348 || SBYTES (f->name) != len
7349 || bcmp (frame_title_buf, SDATA (f->name), len) != 0)
5f5c8ee5
GM
7350 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
7351 }
7352}
7353
5f5c8ee5
GM
7354#endif /* not HAVE_WINDOW_SYSTEM */
7355
7356
7357
7358\f
7359/***********************************************************************
7360 Menu Bars
7361 ***********************************************************************/
7362
7363
7364/* Prepare for redisplay by updating menu-bar item lists when
7365 appropriate. This can call eval. */
7366
7367void
7368prepare_menu_bars ()
7369{
7370 int all_windows;
7371 struct gcpro gcpro1, gcpro2;
7372 struct frame *f;
6b5c4794 7373 Lisp_Object tooltip_frame;
5f5c8ee5 7374
86ffe5cd 7375#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
7376 tooltip_frame = tip_frame;
7377#else
6b5c4794 7378 tooltip_frame = Qnil;
5f5c8ee5
GM
7379#endif
7380
7381 /* Update all frame titles based on their buffer names, etc. We do
7382 this before the menu bars so that the buffer-menu will show the
7383 up-to-date frame titles. */
7384#ifdef HAVE_WINDOW_SYSTEM
7385 if (windows_or_buffers_changed || update_mode_lines)
7386 {
7387 Lisp_Object tail, frame;
7388
7389 FOR_EACH_FRAME (tail, frame)
7390 {
7391 f = XFRAME (frame);
6b5c4794 7392 if (!EQ (frame, tooltip_frame)
5f5c8ee5
GM
7393 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
7394 x_consider_frame_title (frame);
7395 }
7396 }
7397#endif /* HAVE_WINDOW_SYSTEM */
7398
7399 /* Update the menu bar item lists, if appropriate. This has to be
7400 done before any actual redisplay or generation of display lines. */
2311178e 7401 all_windows = (update_mode_lines
5f5c8ee5
GM
7402 || buffer_shared > 1
7403 || windows_or_buffers_changed);
7404 if (all_windows)
7405 {
7406 Lisp_Object tail, frame;
331379bf 7407 int count = SPECPDL_INDEX ();
5f5c8ee5
GM
7408
7409 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
7410
7411 FOR_EACH_FRAME (tail, frame)
7412 {
7413 f = XFRAME (frame);
7414
7415 /* Ignore tooltip frame. */
6b5c4794 7416 if (EQ (frame, tooltip_frame))
5f5c8ee5 7417 continue;
2311178e 7418
5f5c8ee5
GM
7419 /* If a window on this frame changed size, report that to
7420 the user and clear the size-change flag. */
7421 if (FRAME_WINDOW_SIZES_CHANGED (f))
7422 {
7423 Lisp_Object functions;
2311178e 7424
5f5c8ee5
GM
7425 /* Clear flag first in case we get an error below. */
7426 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
7427 functions = Vwindow_size_change_functions;
7428 GCPRO2 (tail, functions);
2311178e 7429
5f5c8ee5
GM
7430 while (CONSP (functions))
7431 {
7432 call1 (XCAR (functions), frame);
7433 functions = XCDR (functions);
7434 }
7435 UNGCPRO;
7436 }
2311178e 7437
5f5c8ee5
GM
7438 GCPRO1 (tail);
7439 update_menu_bar (f, 0);
7440#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 7441 update_tool_bar (f, 0);
5f5c8ee5
GM
7442#endif
7443 UNGCPRO;
7444 }
7445
7446 unbind_to (count, Qnil);
7447 }
7448 else
7449 {
886bd6f2
GM
7450 struct frame *sf = SELECTED_FRAME ();
7451 update_menu_bar (sf, 1);
5f5c8ee5 7452#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 7453 update_tool_bar (sf, 1);
5f5c8ee5
GM
7454#endif
7455 }
7456
7457 /* Motif needs this. See comment in xmenu.c. Turn it off when
7458 pending_menu_activation is not defined. */
7459#ifdef USE_X_TOOLKIT
7460 pending_menu_activation = 0;
7461#endif
7462}
7463
7464
7465/* Update the menu bar item list for frame F. This has to be done
7466 before we start to fill in any display lines, because it can call
7467 eval.
7468
7469 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
7470
7471static void
7472update_menu_bar (f, save_match_data)
7473 struct frame *f;
7474 int save_match_data;
7475{
7476 Lisp_Object window;
7477 register struct window *w;
7478
e1477f43
GM
7479 /* If called recursively during a menu update, do nothing. This can
7480 happen when, for instance, an activate-menubar-hook causes a
7481 redisplay. */
7482 if (inhibit_menubar_update)
7483 return;
7484
5f5c8ee5
GM
7485 window = FRAME_SELECTED_WINDOW (f);
7486 w = XWINDOW (window);
2311178e 7487
40ae145b 7488#if 0 /* The if statement below this if statement used to include the
a5f08374
RS
7489 condition !NILP (w->update_mode_line), rather than using
7490 update_mode_lines directly, and this if statement may have
7491 been added to make that condition work. Now the if
2311178e 7492 statement below matches its comment, this isn't needed. */
5f5c8ee5
GM
7493 if (update_mode_lines)
7494 w->update_mode_line = Qt;
a5f08374 7495#endif
5f5c8ee5
GM
7496
7497 if (FRAME_WINDOW_P (f)
7498 ?
e0f712ba 7499#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
2311178e 7500 FRAME_EXTERNAL_MENU_BAR (f)
5f5c8ee5
GM
7501#else
7502 FRAME_MENU_BAR_LINES (f) > 0
7503#endif
7504 : FRAME_MENU_BAR_LINES (f) > 0)
7505 {
7506 /* If the user has switched buffers or windows, we need to
7507 recompute to reflect the new bindings. But we'll
7508 recompute when update_mode_lines is set too; that means
7509 that people can use force-mode-line-update to request
7510 that the menu bar be recomputed. The adverse effect on
7511 the rest of the redisplay algorithm is about the same as
7512 windows_or_buffers_changed anyway. */
7513 if (windows_or_buffers_changed
a5f08374
RS
7514 /* This used to test w->update_mode_line, but we believe
7515 there is no need to recompute the menu in that case. */
7516 || update_mode_lines
5f5c8ee5
GM
7517 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
7518 < BUF_MODIFF (XBUFFER (w->buffer)))
7519 != !NILP (w->last_had_star))
7520 || ((!NILP (Vtransient_mark_mode)
7521 && !NILP (XBUFFER (w->buffer)->mark_active))
7522 != !NILP (w->region_showing)))
7523 {
7524 struct buffer *prev = current_buffer;
331379bf 7525 int count = SPECPDL_INDEX ();
5f5c8ee5 7526
e1477f43
GM
7527 specbind (Qinhibit_menubar_update, Qt);
7528
5f5c8ee5
GM
7529 set_buffer_internal_1 (XBUFFER (w->buffer));
7530 if (save_match_data)
7531 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
7532 if (NILP (Voverriding_local_map_menu_flag))
7533 {
7534 specbind (Qoverriding_terminal_local_map, Qnil);
7535 specbind (Qoverriding_local_map, Qnil);
7536 }
7537
7538 /* Run the Lucid hook. */
65048e97 7539 safe_run_hooks (Qactivate_menubar_hook);
2311178e 7540
5f5c8ee5
GM
7541 /* If it has changed current-menubar from previous value,
7542 really recompute the menu-bar from the value. */
7543 if (! NILP (Vlucid_menu_bar_dirty_flag))
7544 call0 (Qrecompute_lucid_menubar);
2311178e 7545
5f5c8ee5
GM
7546 safe_run_hooks (Qmenu_bar_update_hook);
7547 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
2311178e 7548
5f5c8ee5 7549 /* Redisplay the menu bar in case we changed it. */
e0f712ba 7550#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
1a578e9b 7551 if (FRAME_WINDOW_P (f)
e0f712ba 7552#if defined (MAC_OS)
1a578e9b
AC
7553 /* All frames on Mac OS share the same menubar. So only the
7554 selected frame should be allowed to set it. */
7555 && f == SELECTED_FRAME ()
7556#endif
7557 )
5f5c8ee5
GM
7558 set_frame_menubar (f, 0, 0);
7559 else
7560 /* On a terminal screen, the menu bar is an ordinary screen
7561 line, and this makes it get updated. */
7562 w->update_mode_line = Qt;
7563#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
7564 /* In the non-toolkit version, the menu bar is an ordinary screen
7565 line, and this makes it get updated. */
7566 w->update_mode_line = Qt;
7567#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
7568
7569 unbind_to (count, Qnil);
7570 set_buffer_internal_1 (prev);
7571 }
7572 }
7573}
7574
7575
7576\f
7577/***********************************************************************
e037b9ec 7578 Tool-bars
5f5c8ee5
GM
7579 ***********************************************************************/
7580
7581#ifdef HAVE_WINDOW_SYSTEM
7582
e037b9ec 7583/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
7584 before we start to fill in any display lines. Called from
7585 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
7586 and restore it here. */
7587
7588static void
e037b9ec 7589update_tool_bar (f, save_match_data)
5f5c8ee5
GM
7590 struct frame *f;
7591 int save_match_data;
7592{
e037b9ec
GM
7593 if (WINDOWP (f->tool_bar_window)
7594 && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
5f5c8ee5
GM
7595 {
7596 Lisp_Object window;
7597 struct window *w;
7598
7599 window = FRAME_SELECTED_WINDOW (f);
7600 w = XWINDOW (window);
2311178e 7601
5f5c8ee5
GM
7602 /* If the user has switched buffers or windows, we need to
7603 recompute to reflect the new bindings. But we'll
7604 recompute when update_mode_lines is set too; that means
7605 that people can use force-mode-line-update to request
7606 that the menu bar be recomputed. The adverse effect on
7607 the rest of the redisplay algorithm is about the same as
7608 windows_or_buffers_changed anyway. */
7609 if (windows_or_buffers_changed
7610 || !NILP (w->update_mode_line)
7611 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
7612 < BUF_MODIFF (XBUFFER (w->buffer)))
7613 != !NILP (w->last_had_star))
7614 || ((!NILP (Vtransient_mark_mode)
7615 && !NILP (XBUFFER (w->buffer)->mark_active))
7616 != !NILP (w->region_showing)))
7617 {
7618 struct buffer *prev = current_buffer;
331379bf 7619 int count = SPECPDL_INDEX ();
a2889657 7620
5f5c8ee5
GM
7621 /* Set current_buffer to the buffer of the selected
7622 window of the frame, so that we get the right local
7623 keymaps. */
7624 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 7625
5f5c8ee5
GM
7626 /* Save match data, if we must. */
7627 if (save_match_data)
7628 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
7629
7630 /* Make sure that we don't accidentally use bogus keymaps. */
7631 if (NILP (Voverriding_local_map_menu_flag))
7632 {
7633 specbind (Qoverriding_terminal_local_map, Qnil);
7634 specbind (Qoverriding_local_map, Qnil);
1f40cad2 7635 }
1f40cad2 7636
e037b9ec 7637 /* Build desired tool-bar items from keymaps. */
7464726e
GM
7638 f->tool_bar_items
7639 = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
2311178e 7640
e037b9ec 7641 /* Redisplay the tool-bar in case we changed it. */
5f5c8ee5
GM
7642 w->update_mode_line = Qt;
7643
7644 unbind_to (count, Qnil);
7645 set_buffer_internal_1 (prev);
81d478f3 7646 }
a2889657
JB
7647 }
7648}
7649
6c4429a5 7650
e037b9ec 7651/* Set F->desired_tool_bar_string to a Lisp string representing frame
7464726e 7652 F's desired tool-bar contents. F->tool_bar_items must have
5f5c8ee5
GM
7653 been set up previously by calling prepare_menu_bars. */
7654
a2889657 7655static void
e037b9ec 7656build_desired_tool_bar_string (f)
5f5c8ee5 7657 struct frame *f;
a2889657 7658{
a23887b9 7659 int i, size, size_needed;
5f5c8ee5
GM
7660 struct gcpro gcpro1, gcpro2, gcpro3;
7661 Lisp_Object image, plist, props;
a2889657 7662
5f5c8ee5
GM
7663 image = plist = props = Qnil;
7664 GCPRO3 (image, plist, props);
a2889657 7665
e037b9ec 7666 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5 7667 Otherwise, make a new string. */
2311178e 7668
5f5c8ee5 7669 /* The size of the string we might be able to reuse. */
e037b9ec 7670 size = (STRINGP (f->desired_tool_bar_string)
2051c264 7671 ? SCHARS (f->desired_tool_bar_string)
5f5c8ee5
GM
7672 : 0);
7673
b94c0d9c 7674 /* We need one space in the string for each image. */
a23887b9 7675 size_needed = f->n_tool_bar_items;
2311178e 7676
b94c0d9c 7677 /* Reuse f->desired_tool_bar_string, if possible. */
cb2ddc53 7678 if (size < size_needed || NILP (f->desired_tool_bar_string))
6fc556fd
KR
7679 f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
7680 make_number (' '));
5f5c8ee5
GM
7681 else
7682 {
7683 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
7684 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 7685 props, f->desired_tool_bar_string);
5f5c8ee5 7686 }
a2889657 7687
5f5c8ee5 7688 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
7689 put a `menu_item' property on tool-bar items with a value that
7690 is the index of the item in F's tool-bar item vector. */
a23887b9 7691 for (i = 0; i < f->n_tool_bar_items; ++i)
a2889657 7692 {
7464726e 7693#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5f5c8ee5 7694
e037b9ec
GM
7695 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
7696 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
35a41507 7697 int hmargin, vmargin, relief, idx, end;
ecd01a0e 7698 extern Lisp_Object QCrelief, QCmargin, QCconversion, Qimage;
5f5c8ee5
GM
7699
7700 /* If image is a vector, choose the image according to the
7701 button state. */
e037b9ec 7702 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
7703 if (VECTORP (image))
7704 {
5f5c8ee5
GM
7705 if (enabled_p)
7706 idx = (selected_p
e037b9ec
GM
7707 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
7708 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
7709 else
7710 idx = (selected_p
e037b9ec
GM
7711 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
7712 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
2311178e 7713
37e4e482
GM
7714 xassert (ASIZE (image) >= idx);
7715 image = AREF (image, idx);
5f5c8ee5 7716 }
37e4e482
GM
7717 else
7718 idx = -1;
5f5c8ee5
GM
7719
7720 /* Ignore invalid image specifications. */
7721 if (!valid_image_p (image))
7722 continue;
7723
e037b9ec 7724 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
7725 plist = Fcopy_sequence (XCDR (image));
7726
7727 /* Compute margin and relief to draw. */
9f864bf9 7728 relief = (tool_bar_button_relief >= 0
c3d76173
GM
7729 ? tool_bar_button_relief
7730 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
35a41507
GM
7731 hmargin = vmargin = relief;
7732
7733 if (INTEGERP (Vtool_bar_button_margin)
7734 && XINT (Vtool_bar_button_margin) > 0)
7735 {
7736 hmargin += XFASTINT (Vtool_bar_button_margin);
7737 vmargin += XFASTINT (Vtool_bar_button_margin);
7738 }
7739 else if (CONSP (Vtool_bar_button_margin))
7740 {
7741 if (INTEGERP (XCAR (Vtool_bar_button_margin))
7742 && XINT (XCAR (Vtool_bar_button_margin)) > 0)
7743 hmargin += XFASTINT (XCAR (Vtool_bar_button_margin));
2311178e 7744
35a41507
GM
7745 if (INTEGERP (XCDR (Vtool_bar_button_margin))
7746 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
7747 vmargin += XFASTINT (XCDR (Vtool_bar_button_margin));
7748 }
2311178e 7749
e037b9ec 7750 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
7751 {
7752 /* Add a `:relief' property to the image spec if the item is
7753 selected. */
7754 if (selected_p)
7755 {
7756 plist = Fplist_put (plist, QCrelief, make_number (-relief));
35a41507
GM
7757 hmargin -= relief;
7758 vmargin -= relief;
5f5c8ee5
GM
7759 }
7760 }
7761 else
7762 {
7763 /* If image is selected, display it pressed, i.e. with a
7764 negative relief. If it's not selected, display it with a
7765 raised relief. */
7766 plist = Fplist_put (plist, QCrelief,
7767 (selected_p
7768 ? make_number (-relief)
7769 : make_number (relief)));
35a41507
GM
7770 hmargin -= relief;
7771 vmargin -= relief;
5f5c8ee5
GM
7772 }
7773
7774 /* Put a margin around the image. */
35a41507
GM
7775 if (hmargin || vmargin)
7776 {
7777 if (hmargin == vmargin)
7778 plist = Fplist_put (plist, QCmargin, make_number (hmargin));
7779 else
7780 plist = Fplist_put (plist, QCmargin,
7781 Fcons (make_number (hmargin),
7782 make_number (vmargin)));
7783 }
2311178e 7784
37e4e482
GM
7785 /* If button is not enabled, and we don't have special images
7786 for the disabled state, make the image appear disabled by
5f5c8ee5 7787 applying an appropriate algorithm to it. */
37e4e482 7788 if (!enabled_p && idx < 0)
ecd01a0e 7789 plist = Fplist_put (plist, QCconversion, Qdisabled);
2311178e 7790
5f5c8ee5
GM
7791 /* Put a `display' text property on the string for the image to
7792 display. Put a `menu-item' property on the string that gives
e037b9ec 7793 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
7794 vector. */
7795 image = Fcons (Qimage, plist);
7796 props = list4 (Qdisplay, image,
a23887b9
GM
7797 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS));
7798
7799 /* Let the last image hide all remaining spaces in the tool bar
7800 string. The string can be longer than needed when we reuse a
7801 previous string. */
7802 if (i + 1 == f->n_tool_bar_items)
2051c264 7803 end = SCHARS (f->desired_tool_bar_string);
a23887b9
GM
7804 else
7805 end = i + 1;
7806 Fadd_text_properties (make_number (i), make_number (end),
e037b9ec 7807 props, f->desired_tool_bar_string);
5f5c8ee5 7808#undef PROP
a2889657
JB
7809 }
7810
5f5c8ee5
GM
7811 UNGCPRO;
7812}
7813
7814
e037b9ec 7815/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
7816
7817static void
e037b9ec 7818display_tool_bar_line (it)
5f5c8ee5
GM
7819 struct it *it;
7820{
7821 struct glyph_row *row = it->glyph_row;
7822 int max_x = it->last_visible_x;
7823 struct glyph *last;
2311178e 7824
5f5c8ee5
GM
7825 prepare_desired_row (row);
7826 row->y = it->current_y;
90aa2856
GM
7827
7828 /* Note that this isn't made use of if the face hasn't a box,
7829 so there's no need to check the face here. */
7830 it->start_of_box_run_p = 1;
2311178e 7831
5f5c8ee5 7832 while (it->current_x < max_x)
a2889657 7833 {
5f5c8ee5 7834 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 7835
5f5c8ee5
GM
7836 /* Get the next display element. */
7837 if (!get_next_display_element (it))
7838 break;
73af359d 7839
5f5c8ee5
GM
7840 /* Produce glyphs. */
7841 x_before = it->current_x;
7842 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
7843 PRODUCE_GLYPHS (it);
daa37602 7844
5f5c8ee5
GM
7845 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
7846 i = 0;
7847 x = x_before;
7848 while (i < nglyphs)
7849 {
7850 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 7851
5f5c8ee5
GM
7852 if (x + glyph->pixel_width > max_x)
7853 {
7854 /* Glyph doesn't fit on line. */
7855 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
7856 it->current_x = x;
7857 goto out;
7858 }
daa37602 7859
5f5c8ee5
GM
7860 ++it->hpos;
7861 x += glyph->pixel_width;
7862 ++i;
7863 }
7864
7865 /* Stop at line ends. */
7866 if (ITERATOR_AT_END_OF_LINE_P (it))
7867 break;
7868
cafafe0b 7869 set_iterator_to_next (it, 1);
a2889657 7870 }
a2889657 7871
5f5c8ee5 7872 out:;
a2889657 7873
5f5c8ee5
GM
7874 row->displays_text_p = row->used[TEXT_AREA] != 0;
7875 extend_face_to_end_of_line (it);
7876 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
7877 last->right_box_line_p = 1;
90aa2856
GM
7878 if (last == row->glyphs[TEXT_AREA])
7879 last->left_box_line_p = 1;
5f5c8ee5 7880 compute_line_metrics (it);
2311178e 7881
e037b9ec 7882 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
7883 if (!row->displays_text_p)
7884 {
312246d1
GM
7885 row->height = row->phys_height = it->last_visible_y - row->y;
7886 row->ascent = row->phys_ascent = 0;
5f5c8ee5 7887 }
2311178e 7888
5f5c8ee5
GM
7889 row->full_width_p = 1;
7890 row->continued_p = 0;
7891 row->truncated_on_left_p = 0;
7892 row->truncated_on_right_p = 0;
7893
7894 it->current_x = it->hpos = 0;
7895 it->current_y += row->height;
7896 ++it->vpos;
7897 ++it->glyph_row;
a2889657 7898}
96a410bc 7899
5f5c8ee5 7900
e037b9ec 7901/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 7902 items of frame F visible. */
96a410bc 7903
d39b6696 7904static int
e037b9ec 7905tool_bar_lines_needed (f)
5f5c8ee5 7906 struct frame *f;
d39b6696 7907{
e037b9ec 7908 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5 7909 struct it it;
2311178e 7910
e037b9ec
GM
7911 /* Initialize an iterator for iteration over
7912 F->desired_tool_bar_string in the tool-bar window of frame F. */
7913 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
7914 it.first_visible_x = 0;
7915 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
e037b9ec 7916 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
7917
7918 while (!ITERATOR_AT_END_P (&it))
7919 {
7920 it.glyph_row = w->desired_matrix->rows;
7921 clear_glyph_row (it.glyph_row);
e037b9ec 7922 display_tool_bar_line (&it);
5f5c8ee5
GM
7923 }
7924
7925 return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
d39b6696 7926}
96a410bc 7927
5f5c8ee5 7928
57c28064
GM
7929DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
7930 0, 1, 0,
7ee72033
MB
7931 doc: /* Return the number of lines occupied by the tool bar of FRAME. */)
7932 (frame)
57c28064
GM
7933 Lisp_Object frame;
7934{
7935 struct frame *f;
7936 struct window *w;
7937 int nlines = 0;
7938
7939 if (NILP (frame))
7940 frame = selected_frame;
7941 else
b7826503 7942 CHECK_FRAME (frame);
57c28064 7943 f = XFRAME (frame);
2311178e 7944
57c28064
GM
7945 if (WINDOWP (f->tool_bar_window)
7946 || (w = XWINDOW (f->tool_bar_window),
7947 XFASTINT (w->height) > 0))
7948 {
7949 update_tool_bar (f, 1);
7950 if (f->n_tool_bar_items)
7951 {
7952 build_desired_tool_bar_string (f);
7953 nlines = tool_bar_lines_needed (f);
7954 }
7955 }
7956
7957 return make_number (nlines);
7958}
7959
7960
e037b9ec 7961/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
7962 height should be changed. */
7963
7964static int
e037b9ec 7965redisplay_tool_bar (f)
5f5c8ee5 7966 struct frame *f;
96a410bc 7967{
5f5c8ee5
GM
7968 struct window *w;
7969 struct it it;
7970 struct glyph_row *row;
7971 int change_height_p = 0;
2311178e 7972
e037b9ec
GM
7973 /* If frame hasn't a tool-bar window or if it is zero-height, don't
7974 do anything. This means you must start with tool-bar-lines
5f5c8ee5 7975 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
7976 can turn off tool-bars by specifying tool-bar-lines zero. */
7977 if (!WINDOWP (f->tool_bar_window)
7978 || (w = XWINDOW (f->tool_bar_window),
5f5c8ee5
GM
7979 XFASTINT (w->height) == 0))
7980 return 0;
96a410bc 7981
e037b9ec
GM
7982 /* Set up an iterator for the tool-bar window. */
7983 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
7984 it.first_visible_x = 0;
7985 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
7986 row = it.glyph_row;
3450d04c 7987
e037b9ec
GM
7988 /* Build a string that represents the contents of the tool-bar. */
7989 build_desired_tool_bar_string (f);
7990 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 7991
e037b9ec 7992 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 7993 while (it.current_y < it.last_visible_y)
e037b9ec 7994 display_tool_bar_line (&it);
3450d04c 7995
e037b9ec 7996 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
7997 window, so don't do it. */
7998 w->desired_matrix->no_scrolling_p = 1;
7999 w->must_be_updated_p = 1;
3450d04c 8000
e037b9ec 8001 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
8002 {
8003 int nlines;
6e33e6f0
GM
8004
8005 /* If we couldn't display everything, change the tool-bar's
8006 height. */
8007 if (IT_STRING_CHARPOS (it) < it.end_charpos)
8008 change_height_p = 1;
2311178e 8009
5f5c8ee5
GM
8010 /* If there are blank lines at the end, except for a partially
8011 visible blank line at the end that is smaller than
e037b9ec 8012 CANON_Y_UNIT, change the tool-bar's height. */
5f5c8ee5
GM
8013 row = it.glyph_row - 1;
8014 if (!row->displays_text_p
8015 && row->height >= CANON_Y_UNIT (f))
8016 change_height_p = 1;
8017
e037b9ec
GM
8018 /* If row displays tool-bar items, but is partially visible,
8019 change the tool-bar's height. */
5f5c8ee5
GM
8020 if (row->displays_text_p
8021 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
8022 change_height_p = 1;
8023
e037b9ec 8024 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
8025 frame parameter. */
8026 if (change_height_p
e037b9ec 8027 && (nlines = tool_bar_lines_needed (f),
5f5c8ee5
GM
8028 nlines != XFASTINT (w->height)))
8029 {
e037b9ec 8030 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5 8031 Lisp_Object frame;
e85ee976 8032 int old_height = XFASTINT (w->height);
2311178e 8033
5f5c8ee5
GM
8034 XSETFRAME (frame, f);
8035 clear_glyph_matrix (w->desired_matrix);
8036 Fmodify_frame_parameters (frame,
e037b9ec 8037 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
8038 make_number (nlines)),
8039 Qnil));
e85ee976
GM
8040 if (XFASTINT (w->height) != old_height)
8041 fonts_changed_p = 1;
5f5c8ee5
GM
8042 }
8043 }
3450d04c 8044
5f5c8ee5 8045 return change_height_p;
96a410bc 8046}
90adcf20 8047
5f5c8ee5 8048
e037b9ec
GM
8049/* Get information about the tool-bar item which is displayed in GLYPH
8050 on frame F. Return in *PROP_IDX the index where tool-bar item
7464726e 8051 properties start in F->tool_bar_items. Value is zero if
e037b9ec 8052 GLYPH doesn't display a tool-bar item. */
5f5c8ee5
GM
8053
8054int
e037b9ec 8055tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
8056 struct frame *f;
8057 struct glyph *glyph;
8058 int *prop_idx;
90adcf20 8059{
5f5c8ee5
GM
8060 Lisp_Object prop;
8061 int success_p;
be676094
GM
8062 int charpos;
8063
8064 /* This function can be called asynchronously, which means we must
8065 exclude any possibility that Fget_text_property signals an
8066 error. */
2051c264 8067 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
be676094 8068 charpos = max (0, charpos);
2311178e 8069
5f5c8ee5
GM
8070 /* Get the text property `menu-item' at pos. The value of that
8071 property is the start index of this item's properties in
7464726e 8072 F->tool_bar_items. */
be676094 8073 prop = Fget_text_property (make_number (charpos),
e037b9ec 8074 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
8075 if (INTEGERP (prop))
8076 {
8077 *prop_idx = XINT (prop);
8078 success_p = 1;
8079 }
8080 else
8081 success_p = 0;
90adcf20 8082
5f5c8ee5
GM
8083 return success_p;
8084}
2311178e 8085
5f5c8ee5 8086#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 8087
feb0c42f 8088
5f5c8ee5
GM
8089\f
8090/************************************************************************
8091 Horizontal scrolling
8092 ************************************************************************/
feb0c42f 8093
5f5c8ee5
GM
8094static int hscroll_window_tree P_ ((Lisp_Object));
8095static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 8096
5f5c8ee5
GM
8097/* For all leaf windows in the window tree rooted at WINDOW, set their
8098 hscroll value so that PT is (i) visible in the window, and (ii) so
8099 that it is not within a certain margin at the window's left and
8100 right border. Value is non-zero if any window's hscroll has been
8101 changed. */
8102
8103static int
8104hscroll_window_tree (window)
8105 Lisp_Object window;
8106{
8107 int hscrolled_p = 0;
e76d28d5 8108 int hscroll_relative_p = FLOATP (Vhscroll_step);
1df7e8f0
EZ
8109 int hscroll_step_abs = 0;
8110 double hscroll_step_rel = 0;
8111
8112 if (hscroll_relative_p)
8113 {
e76d28d5 8114 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
1df7e8f0
EZ
8115 if (hscroll_step_rel < 0)
8116 {
8117 hscroll_relative_p = 0;
8118 hscroll_step_abs = 0;
8119 }
8120 }
e76d28d5 8121 else if (INTEGERP (Vhscroll_step))
1df7e8f0 8122 {
e76d28d5 8123 hscroll_step_abs = XINT (Vhscroll_step);
1df7e8f0
EZ
8124 if (hscroll_step_abs < 0)
8125 hscroll_step_abs = 0;
8126 }
8127 else
8128 hscroll_step_abs = 0;
8129
5f5c8ee5 8130 while (WINDOWP (window))
90adcf20 8131 {
5f5c8ee5 8132 struct window *w = XWINDOW (window);
1df7e8f0 8133
5f5c8ee5
GM
8134 if (WINDOWP (w->hchild))
8135 hscrolled_p |= hscroll_window_tree (w->hchild);
8136 else if (WINDOWP (w->vchild))
8137 hscrolled_p |= hscroll_window_tree (w->vchild);
8138 else if (w->cursor.vpos >= 0)
8139 {
e76d28d5 8140 int h_margin, text_area_x, text_area_y;
5f5c8ee5 8141 int text_area_width, text_area_height;
92a90e89
GM
8142 struct glyph_row *current_cursor_row
8143 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
8144 struct glyph_row *desired_cursor_row
8145 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
8146 struct glyph_row *cursor_row
8147 = (desired_cursor_row->enabled_p
8148 ? desired_cursor_row
8149 : current_cursor_row);
a2725ab2 8150
5f5c8ee5
GM
8151 window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
8152 &text_area_width, &text_area_height);
90adcf20 8153
5f5c8ee5 8154 /* Scroll when cursor is inside this scroll margin. */
e76d28d5 8155 h_margin = hscroll_margin * CANON_X_UNIT (XFRAME (w->frame));
1df7e8f0 8156
5f5c8ee5 8157 if ((XFASTINT (w->hscroll)
e76d28d5 8158 && w->cursor.x <= h_margin)
92a90e89
GM
8159 || (cursor_row->enabled_p
8160 && cursor_row->truncated_on_right_p
e76d28d5 8161 && (w->cursor.x >= text_area_width - h_margin)))
08b610e4 8162 {
5f5c8ee5
GM
8163 struct it it;
8164 int hscroll;
8165 struct buffer *saved_current_buffer;
8166 int pt;
1df7e8f0 8167 int wanted_x;
5f5c8ee5
GM
8168
8169 /* Find point in a display of infinite width. */
8170 saved_current_buffer = current_buffer;
8171 current_buffer = XBUFFER (w->buffer);
1df7e8f0 8172
5f5c8ee5
GM
8173 if (w == XWINDOW (selected_window))
8174 pt = BUF_PT (current_buffer);
8175 else
08b610e4 8176 {
5f5c8ee5
GM
8177 pt = marker_position (w->pointm);
8178 pt = max (BEGV, pt);
8179 pt = min (ZV, pt);
8180 }
8181
8182 /* Move iterator to pt starting at cursor_row->start in
8183 a line with infinite width. */
8184 init_to_row_start (&it, w, cursor_row);
8185 it.last_visible_x = INFINITY;
8186 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
8187 current_buffer = saved_current_buffer;
8188
1df7e8f0
EZ
8189 /* Position cursor in window. */
8190 if (!hscroll_relative_p && hscroll_step_abs == 0)
8191 hscroll = max (0, it.current_x - text_area_width / 2)
8192 / CANON_X_UNIT (it.f);
e76d28d5 8193 else if (w->cursor.x >= text_area_width - h_margin)
1df7e8f0
EZ
8194 {
8195 if (hscroll_relative_p)
8196 wanted_x = text_area_width * (1 - hscroll_step_rel)
e76d28d5 8197 - h_margin;
1df7e8f0
EZ
8198 else
8199 wanted_x = text_area_width
8200 - hscroll_step_abs * CANON_X_UNIT (it.f)
e76d28d5 8201 - h_margin;
1df7e8f0
EZ
8202 hscroll
8203 = max (0, it.current_x - wanted_x) / CANON_X_UNIT (it.f);
8204 }
8205 else
8206 {
8207 if (hscroll_relative_p)
8208 wanted_x = text_area_width * hscroll_step_rel
e76d28d5 8209 + h_margin;
1df7e8f0
EZ
8210 else
8211 wanted_x = hscroll_step_abs * CANON_X_UNIT (it.f)
e76d28d5 8212 + h_margin;
1df7e8f0
EZ
8213 hscroll
8214 = max (0, it.current_x - wanted_x) / CANON_X_UNIT (it.f);
8215 }
3172f70b 8216 hscroll = max (hscroll, XFASTINT (w->min_hscroll));
5f5c8ee5
GM
8217
8218 /* Don't call Fset_window_hscroll if value hasn't
8219 changed because it will prevent redisplay
8220 optimizations. */
8221 if (XFASTINT (w->hscroll) != hscroll)
8222 {
3172f70b
GM
8223 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
8224 w->hscroll = make_number (hscroll);
5f5c8ee5 8225 hscrolled_p = 1;
08b610e4 8226 }
08b610e4 8227 }
08b610e4 8228 }
a2725ab2 8229
5f5c8ee5 8230 window = w->next;
90adcf20 8231 }
cd6dfed6 8232
5f5c8ee5
GM
8233 /* Value is non-zero if hscroll of any leaf window has been changed. */
8234 return hscrolled_p;
8235}
8236
8237
8238/* Set hscroll so that cursor is visible and not inside horizontal
8239 scroll margins for all windows in the tree rooted at WINDOW. See
8240 also hscroll_window_tree above. Value is non-zero if any window's
8241 hscroll has been changed. If it has, desired matrices on the frame
8242 of WINDOW are cleared. */
8243
8244static int
8245hscroll_windows (window)
8246 Lisp_Object window;
8247{
d475bcb8 8248 int hscrolled_p;
2311178e 8249
d475bcb8
GM
8250 if (automatic_hscrolling_p)
8251 {
8252 hscrolled_p = hscroll_window_tree (window);
8253 if (hscrolled_p)
8254 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
8255 }
8256 else
8257 hscrolled_p = 0;
5f5c8ee5 8258 return hscrolled_p;
90adcf20 8259}
5f5c8ee5
GM
8260
8261
90adcf20 8262\f
5f5c8ee5
GM
8263/************************************************************************
8264 Redisplay
8265 ************************************************************************/
8266
8267/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
8268 to a non-zero value. This is sometimes handy to have in a debugger
8269 session. */
8270
8271#if GLYPH_DEBUG
a2889657 8272
5f5c8ee5
GM
8273/* First and last unchanged row for try_window_id. */
8274
8275int debug_first_unchanged_at_end_vpos;
8276int debug_last_unchanged_at_beg_vpos;
8277
8278/* Delta vpos and y. */
8279
8280int debug_dvpos, debug_dy;
8281
8282/* Delta in characters and bytes for try_window_id. */
8283
8284int debug_delta, debug_delta_bytes;
8285
8286/* Values of window_end_pos and window_end_vpos at the end of
8287 try_window_id. */
8288
31ade731 8289EMACS_INT debug_end_pos, debug_end_vpos;
5f5c8ee5
GM
8290
8291/* Append a string to W->desired_matrix->method. FMT is a printf
8292 format string. A1...A9 are a supplement for a variable-length
8293 argument list. If trace_redisplay_p is non-zero also printf the
8294 resulting string to stderr. */
8295
8296static void
8297debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
8298 struct window *w;
8299 char *fmt;
8300 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
8301{
8302 char buffer[512];
8303 char *method = w->desired_matrix->method;
8304 int len = strlen (method);
8305 int size = sizeof w->desired_matrix->method;
8306 int remaining = size - len - 1;
8307
8308 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
8309 if (len && remaining)
8310 {
8311 method[len] = '|';
8312 --remaining, ++len;
8313 }
2311178e 8314
5f5c8ee5
GM
8315 strncpy (method + len, buffer, remaining);
8316
8317 if (trace_redisplay_p)
8318 fprintf (stderr, "%p (%s): %s\n",
8319 w,
8320 ((BUFFERP (w->buffer)
8321 && STRINGP (XBUFFER (w->buffer)->name))
2051c264 8322 ? (char *) SDATA (XBUFFER (w->buffer)->name)
5f5c8ee5
GM
8323 : "no buffer"),
8324 buffer);
8325}
a2889657 8326
5f5c8ee5 8327#endif /* GLYPH_DEBUG */
90adcf20 8328
a2889657 8329
5f5c8ee5
GM
8330/* Value is non-zero if all changes in window W, which displays
8331 current_buffer, are in the text between START and END. START is a
8332 buffer position, END is given as a distance from Z. Used in
8333 redisplay_internal for display optimization. */
8334
8335static INLINE int
8336text_outside_line_unchanged_p (w, start, end)
8337 struct window *w;
8338 int start, end;
8339{
8340 int unchanged_p = 1;
2311178e 8341
5f5c8ee5
GM
8342 /* If text or overlays have changed, see where. */
8343 if (XFASTINT (w->last_modified) < MODIFF
8344 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
8345 {
8346 /* Gap in the line? */
8347 if (GPT < start || Z - GPT < end)
8348 unchanged_p = 0;
8349
8350 /* Changes start in front of the line, or end after it? */
8351 if (unchanged_p
9142dd5b
GM
8352 && (BEG_UNCHANGED < start - 1
8353 || END_UNCHANGED < end))
5f5c8ee5 8354 unchanged_p = 0;
2311178e 8355
5f5c8ee5
GM
8356 /* If selective display, can't optimize if changes start at the
8357 beginning of the line. */
8358 if (unchanged_p
8359 && INTEGERP (current_buffer->selective_display)
8360 && XINT (current_buffer->selective_display) > 0
9142dd5b 8361 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5 8362 unchanged_p = 0;
47d57b22
GM
8363
8364 /* If there are overlays at the start or end of the line, these
8365 may have overlay strings with newlines in them. A change at
8366 START, for instance, may actually concern the display of such
8367 overlay strings as well, and they are displayed on different
8368 lines. So, quickly rule out this case. (For the future, it
8369 might be desirable to implement something more telling than
8370 just BEG/END_UNCHANGED.) */
8371 if (unchanged_p)
8372 {
8373 if (BEG + BEG_UNCHANGED == start
8374 && overlay_touches_p (start))
8375 unchanged_p = 0;
8376 if (END_UNCHANGED == end
8377 && overlay_touches_p (Z - end))
8378 unchanged_p = 0;
8379 }
5f5c8ee5
GM
8380 }
8381
8382 return unchanged_p;
8383}
8384
8385
8386/* Do a frame update, taking possible shortcuts into account. This is
8387 the main external entry point for redisplay.
8388
8389 If the last redisplay displayed an echo area message and that message
8390 is no longer requested, we clear the echo area or bring back the
8391 mini-buffer if that is in use. */
20de20dc 8392
a2889657
JB
8393void
8394redisplay ()
e9874cee
RS
8395{
8396 redisplay_internal (0);
8397}
8398
47d57b22 8399
260a86a0
KH
8400/* Return 1 if point moved out of or into a composition. Otherwise
8401 return 0. PREV_BUF and PREV_PT are the last point buffer and
8402 position. BUF and PT are the current point buffer and position. */
8403
8404int
8405check_point_in_composition (prev_buf, prev_pt, buf, pt)
8406 struct buffer *prev_buf, *buf;
8407 int prev_pt, pt;
8408{
8409 int start, end;
8410 Lisp_Object prop;
8411 Lisp_Object buffer;
8412
8413 XSETBUFFER (buffer, buf);
8414 /* Check a composition at the last point if point moved within the
8415 same buffer. */
8416 if (prev_buf == buf)
8417 {
8418 if (prev_pt == pt)
8419 /* Point didn't move. */
8420 return 0;
2311178e 8421
260a86a0
KH
8422 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
8423 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
8424 && COMPOSITION_VALID_P (start, end, prop)
8425 && start < prev_pt && end > prev_pt)
8426 /* The last point was within the composition. Return 1 iff
8427 point moved out of the composition. */
8428 return (pt <= start || pt >= end);
8429 }
8430
8431 /* Check a composition at the current point. */
8432 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
8433 && find_composition (pt, -1, &start, &end, &prop, buffer)
8434 && COMPOSITION_VALID_P (start, end, prop)
8435 && start < pt && end > pt);
8436}
5f5c8ee5 8437
47d57b22 8438
9142dd5b
GM
8439/* Reconsider the setting of B->clip_changed which is displayed
8440 in window W. */
8441
8442static INLINE void
8443reconsider_clip_changes (w, b)
8444 struct window *w;
8445 struct buffer *b;
8446{
c62c1bb5 8447 if (b->clip_changed
9142dd5b
GM
8448 && !NILP (w->window_end_valid)
8449 && w->current_matrix->buffer == b
8450 && w->current_matrix->zv == BUF_ZV (b)
8451 && w->current_matrix->begv == BUF_BEGV (b))
8452 b->clip_changed = 0;
260a86a0
KH
8453
8454 /* If display wasn't paused, and W is not a tool bar window, see if
8455 point has been moved into or out of a composition. In that case,
8456 we set b->clip_changed to 1 to force updating the screen. If
8457 b->clip_changed has already been set to 1, we can skip this
8458 check. */
8459 if (!b->clip_changed
8460 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
8461 {
8462 int pt;
8463
8464 if (w == XWINDOW (selected_window))
8465 pt = BUF_PT (current_buffer);
8466 else
8467 pt = marker_position (w->pointm);
8468
8469 if ((w->current_matrix->buffer != XBUFFER (w->buffer)
6fc556fd 8470 || pt != XINT (w->last_point))
260a86a0 8471 && check_point_in_composition (w->current_matrix->buffer,
6fc556fd 8472 XINT (w->last_point),
260a86a0
KH
8473 XBUFFER (w->buffer), pt))
8474 b->clip_changed = 1;
8475 }
9142dd5b 8476}
aac2d8b2
RS
8477\f
8478#define STOP_POLLING \
8479do { if (! polling_stopped_here) stop_polling (); \
8480 polling_stopped_here = 1; } while (0)
8481
8482#define RESUME_POLLING \
8483do { if (polling_stopped_here) start_polling (); \
8484 polling_stopped_here = 0; } while (0)
9142dd5b
GM
8485
8486
5f5c8ee5
GM
8487/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
8488 response to any user action; therefore, we should preserve the echo
8489 area. (Actually, our caller does that job.) Perhaps in the future
8490 avoid recentering windows if it is not necessary; currently that
8491 causes some problems. */
e9874cee
RS
8492
8493static void
8494redisplay_internal (preserve_echo_area)
8495 int preserve_echo_area;
a2889657 8496{
5f5c8ee5
GM
8497 struct window *w = XWINDOW (selected_window);
8498 struct frame *f = XFRAME (w->frame);
8499 int pause;
a2889657 8500 int must_finish = 0;
5f5c8ee5 8501 struct text_pos tlbufpos, tlendpos;
89819bdd 8502 int number_of_visible_frames;
28514cd9 8503 int count;
886bd6f2 8504 struct frame *sf = SELECTED_FRAME ();
aac2d8b2 8505 int polling_stopped_here = 0;
a2889657 8506
5f5c8ee5
GM
8507 /* Non-zero means redisplay has to consider all windows on all
8508 frames. Zero means, only selected_window is considered. */
8509 int consider_all_windows_p;
2311178e 8510
5f5c8ee5
GM
8511 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
8512
8513 /* No redisplay if running in batch mode or frame is not yet fully
8514 initialized, or redisplay is explicitly turned off by setting
8515 Vinhibit_redisplay. */
8516 if (noninteractive
8517 || !NILP (Vinhibit_redisplay)
8518 || !f->glyphs_initialized_p)
a2889657
JB
8519 return;
8520
5f5c8ee5
GM
8521 /* The flag redisplay_performed_directly_p is set by
8522 direct_output_for_insert when it already did the whole screen
8523 update necessary. */
8524 if (redisplay_performed_directly_p)
8525 {
8526 redisplay_performed_directly_p = 0;
8527 if (!hscroll_windows (selected_window))
8528 return;
8529 }
8530
15f0cf78
RS
8531#ifdef USE_X_TOOLKIT
8532 if (popup_activated ())
8533 return;
8534#endif
8535
28514cd9 8536 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 8537 if (redisplaying_p)
735c094c
KH
8538 return;
8539
28514cd9
GM
8540 /* Record a function that resets redisplaying_p to its old value
8541 when we leave this function. */
331379bf 8542 count = SPECPDL_INDEX ();
28514cd9
GM
8543 record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
8544 ++redisplaying_p;
26683087 8545 specbind (Qinhibit_free_realized_faces, Qnil);
2311178e 8546
8b32d885 8547 retry:
bd9d0f3f 8548 pause = 0;
9142dd5b
GM
8549 reconsider_clip_changes (w, current_buffer);
8550
5f5c8ee5
GM
8551 /* If new fonts have been loaded that make a glyph matrix adjustment
8552 necessary, do it. */
8553 if (fonts_changed_p)
8554 {
8555 adjust_glyphs (NULL);
8556 ++windows_or_buffers_changed;
8557 fonts_changed_p = 0;
8558 }
8559
6961e0c1
GM
8560 /* If face_change_count is non-zero, init_iterator will free all
8561 realized faces, which includes the faces referenced from current
8562 matrices. So, we can't reuse current matrices in this case. */
8563 if (face_change_count)
8564 ++windows_or_buffers_changed;
8565
886bd6f2
GM
8566 if (! FRAME_WINDOW_P (sf)
8567 && previous_terminal_frame != sf)
20de20dc 8568 {
5f5c8ee5
GM
8569 /* Since frames on an ASCII terminal share the same display
8570 area, displaying a different frame means redisplay the whole
8571 thing. */
20de20dc 8572 windows_or_buffers_changed++;
886bd6f2
GM
8573 SET_FRAME_GARBAGED (sf);
8574 XSETFRAME (Vterminal_frame, sf);
20de20dc 8575 }
886bd6f2 8576 previous_terminal_frame = sf;
20de20dc 8577
5f5c8ee5
GM
8578 /* Set the visible flags for all frames. Do this before checking
8579 for resized or garbaged frames; they want to know if their frames
8580 are visible. See the comment in frame.h for
8581 FRAME_SAMPLE_VISIBILITY. */
d724d989 8582 {
35f56f96 8583 Lisp_Object tail, frame;
d724d989 8584
89819bdd
RS
8585 number_of_visible_frames = 0;
8586
35f56f96 8587 FOR_EACH_FRAME (tail, frame)
f82aff7c 8588 {
5f5c8ee5 8589 struct frame *f = XFRAME (frame);
2311178e 8590
5f5c8ee5
GM
8591 FRAME_SAMPLE_VISIBILITY (f);
8592 if (FRAME_VISIBLE_P (f))
8593 ++number_of_visible_frames;
8594 clear_desired_matrices (f);
f82aff7c 8595 }
d724d989
JB
8596 }
8597
44fa5b1e 8598 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 8599 do_pending_window_change (1);
a2889657 8600
5f5c8ee5 8601 /* Clear frames marked as garbaged. */
44fa5b1e 8602 if (frame_garbaged)
c6e89d6c 8603 clear_garbaged_frames ();
a2889657 8604
e037b9ec 8605 /* Build menubar and tool-bar items. */
f82aff7c
RS
8606 prepare_menu_bars ();
8607
28995e67 8608 if (windows_or_buffers_changed)
a2889657
JB
8609 update_mode_lines++;
8610
538f13d4
RS
8611 /* Detect case that we need to write or remove a star in the mode line. */
8612 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
8613 {
8614 w->update_mode_line = Qt;
8615 if (buffer_shared > 1)
8616 update_mode_lines++;
8617 }
8618
5f5c8ee5 8619 /* If %c is in the mode line, update it if needed. */
28995e67
RS
8620 if (!NILP (w->column_number_displayed)
8621 /* This alternative quickly identifies a common case
8622 where no change is needed. */
8623 && !(PT == XFASTINT (w->last_point)
8850a573
RS
8624 && XFASTINT (w->last_modified) >= MODIFF
8625 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
8626 && (XFASTINT (w->column_number_displayed)
8627 != (int) current_column ())) /* iftc */
8628 w->update_mode_line = Qt;
28995e67 8629
44fa5b1e 8630 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 8631
5f5c8ee5
GM
8632 /* The variable buffer_shared is set in redisplay_window and
8633 indicates that we redisplay a buffer in different windows. See
8634 there. */
5fb96e96
RS
8635 consider_all_windows_p = (update_mode_lines || buffer_shared > 1
8636 || cursor_type_changed);
a2889657
JB
8637
8638 /* If specs for an arrow have changed, do thorough redisplay
8639 to ensure we remove any arrow that should no longer exist. */
d45de95b 8640 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 8641 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 8642 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 8643
90adcf20
RS
8644 /* Normally the message* functions will have already displayed and
8645 updated the echo area, but the frame may have been trashed, or
8646 the update may have been preempted, so display the echo area
6e019995 8647 again here. Checking message_cleared_p captures the case that
c6e89d6c 8648 the echo area should be cleared. */
96d5e9a0
GM
8649 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
8650 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
3fa69ee7
GM
8651 || (message_cleared_p
8652 && minibuf_level == 0
8653 /* If the mini-window is currently selected, this means the
8654 echo-area doesn't show through. */
8655 && !MINI_WINDOW_P (XWINDOW (selected_window))))
90adcf20 8656 {
c6e89d6c 8657 int window_height_changed_p = echo_area_display (0);
90adcf20 8658 must_finish = 1;
6e019995
GM
8659
8660 /* If we don't display the current message, don't clear the
8661 message_cleared_p flag, because, if we did, we wouldn't clear
8662 the echo area in the next redisplay which doesn't preserve
8663 the echo area. */
8664 if (!display_last_displayed_message_p)
8665 message_cleared_p = 0;
2311178e 8666
c6e89d6c
GM
8667 if (fonts_changed_p)
8668 goto retry;
8669 else if (window_height_changed_p)
8670 {
8671 consider_all_windows_p = 1;
8672 ++update_mode_lines;
8673 ++windows_or_buffers_changed;
2311178e 8674
9142dd5b
GM
8675 /* If window configuration was changed, frames may have been
8676 marked garbaged. Clear them or we will experience
8677 surprises wrt scrolling. */
8678 if (frame_garbaged)
8679 clear_garbaged_frames ();
c6e89d6c 8680 }
90adcf20 8681 }
97a36635 8682 else if (EQ (selected_window, minibuf_window)
dd2eb166
GM
8683 && (current_buffer->clip_changed
8684 || XFASTINT (w->last_modified) < MODIFF
8685 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 8686 && resize_mini_window (w, 0))
c6e89d6c
GM
8687 {
8688 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
8689 showing if its contents might have changed. */
8690 must_finish = 1;
8691 consider_all_windows_p = 1;
c6e89d6c 8692 ++windows_or_buffers_changed;
dd2eb166 8693 ++update_mode_lines;
2311178e 8694
9142dd5b
GM
8695 /* If window configuration was changed, frames may have been
8696 marked garbaged. Clear them or we will experience
8697 surprises wrt scrolling. */
8698 if (frame_garbaged)
8699 clear_garbaged_frames ();
c6e89d6c 8700 }
2311178e 8701
90adcf20 8702
5f5c8ee5
GM
8703 /* If showing the region, and mark has changed, we must redisplay
8704 the whole window. The assignment to this_line_start_pos prevents
8705 the optimization directly below this if-statement. */
bd66d1ba
RS
8706 if (((!NILP (Vtransient_mark_mode)
8707 && !NILP (XBUFFER (w->buffer)->mark_active))
8708 != !NILP (w->region_showing))
82d04750
JB
8709 || (!NILP (w->region_showing)
8710 && !EQ (w->region_showing,
8711 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
8712 CHARPOS (this_line_start_pos) = 0;
8713
8714 /* Optimize the case that only the line containing the cursor in the
8715 selected window has changed. Variables starting with this_ are
8716 set in display_line and record information about the line
8717 containing the cursor. */
8718 tlbufpos = this_line_start_pos;
8719 tlendpos = this_line_end_pos;
8720 if (!consider_all_windows_p
8721 && CHARPOS (tlbufpos) > 0
8722 && NILP (w->update_mode_line)
73af359d 8723 && !current_buffer->clip_changed
c62c1bb5 8724 && !current_buffer->prevent_redisplay_optimizations_p
44fa5b1e 8725 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 8726 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 8727 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
8728 && this_line_buffer == current_buffer
8729 && current_buffer == XBUFFER (w->buffer)
265a9e55 8730 && NILP (w->force_start)
acda20e1 8731 && NILP (w->optional_new_start)
5f5c8ee5
GM
8732 /* Point must be on the line that we have info recorded about. */
8733 && PT >= CHARPOS (tlbufpos)
8734 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
8735 /* All text outside that line, including its final newline,
8736 must be unchanged */
5f5c8ee5
GM
8737 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
8738 CHARPOS (tlendpos)))
8739 {
8740 if (CHARPOS (tlbufpos) > BEGV
8741 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
8742 && (CHARPOS (tlbufpos) == ZV
8743 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
8744 /* Former continuation line has disappeared by becoming empty */
8745 goto cancel;
8746 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 8747 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
8748 || MINI_WINDOW_P (w))
8749 {
1c9241f5
KH
8750 /* We have to handle the case of continuation around a
8751 wide-column character (See the comment in indent.c around
8752 line 885).
8753
8754 For instance, in the following case:
8755
8756 -------- Insert --------
8757 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
8758 J_I_ ==> J_I_ `^^' are cursors.
8759 ^^ ^^
8760 -------- --------
8761
8762 As we have to redraw the line above, we should goto cancel. */
8763
5f5c8ee5
GM
8764 struct it it;
8765 int line_height_before = this_line_pixel_height;
8766
8767 /* Note that start_display will handle the case that the
8768 line starting at tlbufpos is a continuation lines. */
8769 start_display (&it, w, tlbufpos);
8770
8771 /* Implementation note: It this still necessary? */
8772 if (it.current_x != this_line_start_x)
1c9241f5
KH
8773 goto cancel;
8774
5f5c8ee5
GM
8775 TRACE ((stderr, "trying display optimization 1\n"));
8776 w->cursor.vpos = -1;
a2889657 8777 overlay_arrow_seen = 0;
5f5c8ee5
GM
8778 it.vpos = this_line_vpos;
8779 it.current_y = this_line_y;
8780 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
8781 display_line (&it);
8782
a2889657 8783 /* If line contains point, is not continued,
5f5c8ee5 8784 and ends at same distance from eob as before, we win */
2311178e 8785 if (w->cursor.vpos >= 0
5f5c8ee5
GM
8786 /* Line is not continued, otherwise this_line_start_pos
8787 would have been set to 0 in display_line. */
8788 && CHARPOS (this_line_start_pos)
8789 /* Line ends as before. */
8790 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
8791 /* Line has same height as before. Otherwise other lines
8792 would have to be shifted up or down. */
8793 && this_line_pixel_height == line_height_before)
a2889657 8794 {
5f5c8ee5
GM
8795 /* If this is not the window's last line, we must adjust
8796 the charstarts of the lines below. */
8797 if (it.current_y < it.last_visible_y)
8798 {
8799 struct glyph_row *row
8800 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
8801 int delta, delta_bytes;
2311178e 8802
5f5c8ee5
GM
8803 if (Z - CHARPOS (tlendpos) == ZV)
8804 {
8805 /* This line ends at end of (accessible part of)
8806 buffer. There is no newline to count. */
8807 delta = (Z
8808 - CHARPOS (tlendpos)
8809 - MATRIX_ROW_START_CHARPOS (row));
8810 delta_bytes = (Z_BYTE
8811 - BYTEPOS (tlendpos)
8812 - MATRIX_ROW_START_BYTEPOS (row));
8813 }
8814 else
8815 {
8816 /* This line ends in a newline. Must take
8817 account of the newline and the rest of the
8818 text that follows. */
8819 delta = (Z
8820 - CHARPOS (tlendpos)
8821 - MATRIX_ROW_START_CHARPOS (row));
8822 delta_bytes = (Z_BYTE
8823 - BYTEPOS (tlendpos)
8824 - MATRIX_ROW_START_BYTEPOS (row));
8825 }
2311178e 8826
f2d86d7a
GM
8827 increment_matrix_positions (w->current_matrix,
8828 this_line_vpos + 1,
8829 w->current_matrix->nrows,
8830 delta, delta_bytes);
85bcef6c 8831 }
46db8486 8832
5f5c8ee5
GM
8833 /* If this row displays text now but previously didn't,
8834 or vice versa, w->window_end_vpos may have to be
8835 adjusted. */
8836 if ((it.glyph_row - 1)->displays_text_p)
8837 {
8838 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
8839 XSETINT (w->window_end_vpos, this_line_vpos);
8840 }
8841 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
8842 && this_line_vpos > 0)
8843 XSETINT (w->window_end_vpos, this_line_vpos - 1);
8844 w->window_end_valid = Qnil;
2311178e 8845
5f5c8ee5
GM
8846 /* Update hint: No need to try to scroll in update_window. */
8847 w->desired_matrix->no_scrolling_p = 1;
8848
8849#if GLYPH_DEBUG
8850 *w->desired_matrix->method = 0;
8851 debug_method_add (w, "optimization 1");
8852#endif
a2889657
JB
8853 goto update;
8854 }
8855 else
8856 goto cancel;
8857 }
5f5c8ee5
GM
8858 else if (/* Cursor position hasn't changed. */
8859 PT == XFASTINT (w->last_point)
b6f0fe04
RS
8860 /* Make sure the cursor was last displayed
8861 in this window. Otherwise we have to reposition it. */
5f5c8ee5
GM
8862 && 0 <= w->cursor.vpos
8863 && XINT (w->height) > w->cursor.vpos)
a2889657
JB
8864 {
8865 if (!must_finish)
8866 {
c6e89d6c 8867 do_pending_window_change (1);
5f5c8ee5 8868
2311178e 8869 /* We used to always goto end_of_redisplay here, but this
5f5c8ee5
GM
8870 isn't enough if we have a blinking cursor. */
8871 if (w->cursor_off_p == w->last_cursor_off_p)
8872 goto end_of_redisplay;
a2889657
JB
8873 }
8874 goto update;
8875 }
8b51f1e3
KH
8876 /* If highlighting the region, or if the cursor is in the echo area,
8877 then we can't just move the cursor. */
bd66d1ba
RS
8878 else if (! (!NILP (Vtransient_mark_mode)
8879 && !NILP (current_buffer->mark_active))
97a36635 8880 && (EQ (selected_window, current_buffer->last_selected_window)
293a54ce 8881 || highlight_nonselected_windows)
8b51f1e3 8882 && NILP (w->region_showing)
8f897821 8883 && NILP (Vshow_trailing_whitespace)
8b51f1e3 8884 && !cursor_in_echo_area)
a2889657 8885 {
5f5c8ee5
GM
8886 struct it it;
8887 struct glyph_row *row;
8888
8889 /* Skip from tlbufpos to PT and see where it is. Note that
8890 PT may be in invisible text. If so, we will end at the
8891 next visible position. */
8892 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
8893 NULL, DEFAULT_FACE_ID);
8894 it.current_x = this_line_start_x;
8895 it.current_y = this_line_y;
8896 it.vpos = this_line_vpos;
2311178e 8897
5f5c8ee5
GM
8898 /* The call to move_it_to stops in front of PT, but
8899 moves over before-strings. */
8900 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
8901
8902 if (it.vpos == this_line_vpos
8903 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
8904 row->enabled_p))
a2889657 8905 {
5f5c8ee5
GM
8906 xassert (this_line_vpos == it.vpos);
8907 xassert (this_line_y == it.current_y);
8908 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
ade0bee1
GM
8909#if GLYPH_DEBUG
8910 *w->desired_matrix->method = 0;
8911 debug_method_add (w, "optimization 3");
8912#endif
a2889657
JB
8913 goto update;
8914 }
8915 else
8916 goto cancel;
8917 }
5f5c8ee5 8918
a2889657 8919 cancel:
5f5c8ee5
GM
8920 /* Text changed drastically or point moved off of line. */
8921 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
8922 }
8923
5f5c8ee5
GM
8924 CHARPOS (this_line_start_pos) = 0;
8925 consider_all_windows_p |= buffer_shared > 1;
8926 ++clear_face_cache_count;
a2889657 8927
2311178e 8928
bd9d0f3f
GM
8929 /* Build desired matrices, and update the display. If
8930 consider_all_windows_p is non-zero, do it for all windows on all
8931 frames. Otherwise do it for selected_window, only. */
463f6b91 8932
5f5c8ee5 8933 if (consider_all_windows_p)
a2889657 8934 {
35f56f96 8935 Lisp_Object tail, frame;
0528abe1
GM
8936 int i, n = 0, size = 50;
8937 struct frame **updated
8938 = (struct frame **) alloca (size * sizeof *updated);
a2889657 8939
5f5c8ee5
GM
8940 /* Clear the face cache eventually. */
8941 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 8942 {
5f5c8ee5 8943 clear_face_cache (0);
463f6b91
RS
8944 clear_face_cache_count = 0;
8945 }
31b24551 8946
5f5c8ee5
GM
8947 /* Recompute # windows showing selected buffer. This will be
8948 incremented each time such a window is displayed. */
a2889657
JB
8949 buffer_shared = 0;
8950
35f56f96 8951 FOR_EACH_FRAME (tail, frame)
30c566e4 8952 {
5f5c8ee5 8953 struct frame *f = XFRAME (frame);
2311178e 8954
886bd6f2 8955 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 8956 {
ae02e06a 8957#ifdef HAVE_WINDOW_SYSTEM
bb336f8d
RS
8958 if (clear_face_cache_count % 50 == 0
8959 && FRAME_WINDOW_P (f))
8960 clear_image_cache (f, 0);
ae02e06a 8961#endif /* HAVE_WINDOW_SYSTEM */
bb336f8d 8962
5f5c8ee5
GM
8963 /* Mark all the scroll bars to be removed; we'll redeem
8964 the ones we want when we redisplay their windows. */
9769686d 8965 if (condemn_scroll_bars_hook)
504454e8 8966 condemn_scroll_bars_hook (f);
30c566e4 8967
f21ef775 8968 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 8969 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 8970
5f5c8ee5
GM
8971 /* Any scroll bars which redisplay_windows should have
8972 nuked should now go away. */
9769686d 8973 if (judge_scroll_bars_hook)
504454e8 8974 judge_scroll_bars_hook (f);
bd9d0f3f
GM
8975
8976 /* If fonts changed, display again. */
b60c9653
RS
8977 /* ??? rms: I suspect it is a mistake to jump all the way
8978 back to retry here. It should just retry this frame. */
bd9d0f3f
GM
8979 if (fonts_changed_p)
8980 goto retry;
2311178e 8981
bd9d0f3f
GM
8982 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
8983 {
8984 /* See if we have to hscroll. */
8985 if (hscroll_windows (f->root_window))
8986 goto retry;
8987
8988 /* Prevent various kinds of signals during display
8989 update. stdio is not robust about handling
8990 signals, which can cause an apparent I/O
8991 error. */
8992 if (interrupt_input)
8993 unrequest_sigio ();
aac2d8b2 8994 STOP_POLLING;
bd9d0f3f
GM
8995
8996 /* Update the display. */
8997 set_window_update_flags (XWINDOW (f->root_window), 1);
8998 pause |= update_frame (f, 0, 0);
8999 if (pause)
9000 break;
9001
0528abe1
GM
9002 if (n == size)
9003 {
9004 int nbytes = size * sizeof *updated;
9005 struct frame **p = (struct frame **) alloca (2 * nbytes);
9006 bcopy (updated, p, nbytes);
9007 size *= 2;
9008 }
2311178e 9009
0528abe1 9010 updated[n++] = f;
bd9d0f3f 9011 }
9769686d 9012 }
30c566e4 9013 }
0528abe1
GM
9014
9015 /* Do the mark_window_display_accurate after all windows have
9016 been redisplayed because this call resets flags in buffers
9017 which are needed for proper redisplay. */
9018 for (i = 0; i < n; ++i)
9019 {
9020 struct frame *f = updated[i];
9021 mark_window_display_accurate (f->root_window, 1);
9022 if (frame_up_to_date_hook)
9023 frame_up_to_date_hook (f);
9024 }
a2889657 9025 }
bd9d0f3f
GM
9026 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
9027 {
9028 Lisp_Object mini_window;
9029 struct frame *mini_frame;
5f5c8ee5 9030
82a7ab23 9031 displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
7033d6df
RS
9032 /* Use list_of_error, not Qerror, so that
9033 we catch only errors and don't run the debugger. */
9034 internal_condition_case_1 (redisplay_window_1, selected_window,
9035 list_of_error,
82a7ab23 9036 redisplay_window_error);
2311178e 9037
bd9d0f3f 9038 /* Compare desired and current matrices, perform output. */
7d0393cf 9039
26683087 9040 update:
bd9d0f3f
GM
9041 /* If fonts changed, display again. */
9042 if (fonts_changed_p)
92a90e89 9043 goto retry;
a2889657 9044
bd9d0f3f
GM
9045 /* Prevent various kinds of signals during display update.
9046 stdio is not robust about handling signals,
9047 which can cause an apparent I/O error. */
9048 if (interrupt_input)
9049 unrequest_sigio ();
aac2d8b2 9050 STOP_POLLING;
1af9f229 9051
bd9d0f3f 9052 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
5f5c8ee5 9053 {
92a90e89
GM
9054 if (hscroll_windows (selected_window))
9055 goto retry;
2311178e 9056
5f5c8ee5 9057 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 9058 pause = update_frame (sf, 0, 0);
5f5c8ee5 9059 }
d724d989 9060
8de2d90b 9061 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
9062 function. If the echo area is on another frame, that may
9063 have put text on a frame other than the selected one, so the
9064 above call to update_frame would not have caught it. Catch
8de2d90b 9065 it here. */
bd9d0f3f
GM
9066 mini_window = FRAME_MINIBUF_WINDOW (sf);
9067 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
2311178e 9068
bd9d0f3f
GM
9069 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
9070 {
9071 XWINDOW (mini_window)->must_be_updated_p = 1;
9072 pause |= update_frame (mini_frame, 0, 0);
9073 if (!pause && hscroll_windows (mini_window))
9074 goto retry;
9075 }
6e8290aa 9076 }
a2889657 9077
5f5c8ee5
GM
9078 /* If display was paused because of pending input, make sure we do a
9079 thorough update the next time. */
a2889657
JB
9080 if (pause)
9081 {
5f5c8ee5
GM
9082 /* Prevent the optimization at the beginning of
9083 redisplay_internal that tries a single-line update of the
9084 line containing the cursor in the selected window. */
9085 CHARPOS (this_line_start_pos) = 0;
9086
9087 /* Let the overlay arrow be updated the next time. */
265a9e55 9088 if (!NILP (last_arrow_position))
a2889657
JB
9089 {
9090 last_arrow_position = Qt;
9091 last_arrow_string = Qt;
9092 }
2311178e 9093
5f5c8ee5
GM
9094 /* If we pause after scrolling, some rows in the current
9095 matrices of some windows are not valid. */
9096 if (!WINDOW_FULL_WIDTH_P (w)
9097 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
9098 update_mode_lines = 1;
9099 }
43c09969 9100 else
a2889657 9101 {
43c09969 9102 if (!consider_all_windows_p)
a2889657 9103 {
43c09969
GM
9104 /* This has already been done above if
9105 consider_all_windows_p is set. */
9106 mark_window_display_accurate_1 (w, 1);
2311178e 9107
927c5b3b
GM
9108 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
9109 last_arrow_string = Voverlay_arrow_string;
2311178e 9110
efc63ef0 9111 if (frame_up_to_date_hook != 0)
43c09969 9112 frame_up_to_date_hook (sf);
a2889657 9113 }
15e26c76 9114
a2889657
JB
9115 update_mode_lines = 0;
9116 windows_or_buffers_changed = 0;
5fb96e96 9117 cursor_type_changed = 0;
a2889657
JB
9118 }
9119
5f5c8ee5
GM
9120 /* Start SIGIO interrupts coming again. Having them off during the
9121 code above makes it less likely one will discard output, but not
9122 impossible, since there might be stuff in the system buffer here.
a2889657 9123 But it is much hairier to try to do anything about that. */
a2889657
JB
9124 if (interrupt_input)
9125 request_sigio ();
aac2d8b2 9126 RESUME_POLLING;
a2889657 9127
5f5c8ee5
GM
9128 /* If a frame has become visible which was not before, redisplay
9129 again, so that we display it. Expose events for such a frame
9130 (which it gets when becoming visible) don't call the parts of
9131 redisplay constructing glyphs, so simply exposing a frame won't
9132 display anything in this case. So, we have to display these
9133 frames here explicitly. */
11c52c4f
RS
9134 if (!pause)
9135 {
9136 Lisp_Object tail, frame;
9137 int new_count = 0;
9138
9139 FOR_EACH_FRAME (tail, frame)
9140 {
9141 int this_is_visible = 0;
8e83f802
RS
9142
9143 if (XFRAME (frame)->visible)
9144 this_is_visible = 1;
9145 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
9146 if (XFRAME (frame)->visible)
9147 this_is_visible = 1;
11c52c4f
RS
9148
9149 if (this_is_visible)
9150 new_count++;
9151 }
9152
89819bdd 9153 if (new_count != number_of_visible_frames)
11c52c4f
RS
9154 windows_or_buffers_changed++;
9155 }
9156
44fa5b1e 9157 /* Change frame size now if a change is pending. */
c6e89d6c 9158 do_pending_window_change (1);
d8e242fd 9159
8b32d885
RS
9160 /* If we just did a pending size change, or have additional
9161 visible frames, redisplay again. */
3c8c72e0 9162 if (windows_or_buffers_changed && !pause)
8b32d885 9163 goto retry;
5f5c8ee5 9164
1987b083 9165 end_of_redisplay:
28514cd9 9166 unbind_to (count, Qnil);
aac2d8b2 9167 RESUME_POLLING;
a2889657
JB
9168}
9169
5f5c8ee5
GM
9170
9171/* Redisplay, but leave alone any recent echo area message unless
9172 another message has been requested in its place.
a2889657
JB
9173
9174 This is useful in situations where you need to redisplay but no
9175 user action has occurred, making it inappropriate for the message
9176 area to be cleared. See tracking_off and
9bf76936
GM
9177 wait_reading_process_input for examples of these situations.
9178
9179 FROM_WHERE is an integer saying from where this function was
9180 called. This is useful for debugging. */
a2889657 9181
8991bb31 9182void
9bf76936
GM
9183redisplay_preserve_echo_area (from_where)
9184 int from_where;
a2889657 9185{
9bf76936
GM
9186 TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where));
9187
c6e89d6c 9188 if (!NILP (echo_area_buffer[1]))
a2889657 9189 {
c6e89d6c
GM
9190 /* We have a previously displayed message, but no current
9191 message. Redisplay the previous message. */
9192 display_last_displayed_message_p = 1;
e9874cee 9193 redisplay_internal (1);
c6e89d6c 9194 display_last_displayed_message_p = 0;
a2889657
JB
9195 }
9196 else
e9874cee 9197 redisplay_internal (1);
a2889657
JB
9198}
9199
5f5c8ee5 9200
28514cd9 9201/* Function registered with record_unwind_protect in
acfca545
RS
9202 redisplay_internal. Reset redisplaying_p to the value it had
9203 before redisplay_internal was called, and clear
26683087 9204 prevent_freeing_realized_faces_p. */
28514cd9
GM
9205
9206static Lisp_Object
9207unwind_redisplay (old_redisplaying_p)
9208 Lisp_Object old_redisplaying_p;
9209{
9210 redisplaying_p = XFASTINT (old_redisplaying_p);
c6e89d6c 9211 return Qnil;
28514cd9
GM
9212}
9213
9214
43c09969
GM
9215/* Mark the display of window W as accurate or inaccurate. If
9216 ACCURATE_P is non-zero mark display of W as accurate. If
9217 ACCURATE_P is zero, arrange for W to be redisplayed the next time
9218 redisplay_internal is called. */
5f5c8ee5 9219
43c09969
GM
9220static void
9221mark_window_display_accurate_1 (w, accurate_p)
9222 struct window *w;
5f5c8ee5 9223 int accurate_p;
a2889657 9224{
43c09969 9225 if (BUFFERP (w->buffer))
a2889657 9226 {
43c09969 9227 struct buffer *b = XBUFFER (w->buffer);
2311178e 9228
43c09969
GM
9229 w->last_modified
9230 = make_number (accurate_p ? BUF_MODIFF (b) : 0);
9231 w->last_overlay_modified
9232 = make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
9233 w->last_had_star
9234 = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b) ? Qt : Qnil;
a2889657 9235
43c09969 9236 if (accurate_p)
bd66d1ba 9237 {
43c09969
GM
9238 b->clip_changed = 0;
9239 b->prevent_redisplay_optimizations_p = 0;
9240
9241 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
9242 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
9243 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
9244 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
2311178e 9245
43c09969
GM
9246 w->current_matrix->buffer = b;
9247 w->current_matrix->begv = BUF_BEGV (b);
9248 w->current_matrix->zv = BUF_ZV (b);
2311178e 9249
43c09969
GM
9250 w->last_cursor = w->cursor;
9251 w->last_cursor_off_p = w->cursor_off_p;
2311178e 9252
43c09969
GM
9253 if (w == XWINDOW (selected_window))
9254 w->last_point = make_number (BUF_PT (b));
9255 else
9256 w->last_point = make_number (XMARKER (w->pointm)->charpos);
bd66d1ba 9257 }
43c09969 9258 }
bd66d1ba 9259
43c09969
GM
9260 if (accurate_p)
9261 {
d2f84654 9262 w->window_end_valid = w->buffer;
99332eb6 9263#if 0 /* This is incorrect with variable-height lines. */
2913a9c0
GM
9264 xassert (XINT (w->window_end_vpos)
9265 < (XINT (w->height)
9266 - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
99332eb6 9267#endif
a2889657 9268 w->update_mode_line = Qnil;
43c09969
GM
9269 }
9270}
9271
9272
9273/* Mark the display of windows in the window tree rooted at WINDOW as
9274 accurate or inaccurate. If ACCURATE_P is non-zero mark display of
9275 windows as accurate. If ACCURATE_P is zero, arrange for windows to
9276 be redisplayed the next time redisplay_internal is called. */
9277
9278void
9279mark_window_display_accurate (window, accurate_p)
9280 Lisp_Object window;
9281 int accurate_p;
9282{
9283 struct window *w;
2311178e 9284
43c09969
GM
9285 for (; !NILP (window); window = w->next)
9286 {
9287 w = XWINDOW (window);
9288 mark_window_display_accurate_1 (w, accurate_p);
a2889657 9289
265a9e55 9290 if (!NILP (w->vchild))
5f5c8ee5 9291 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 9292 if (!NILP (w->hchild))
5f5c8ee5 9293 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
9294 }
9295
5f5c8ee5 9296 if (accurate_p)
a2889657 9297 {
d45de95b 9298 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
9299 last_arrow_string = Voverlay_arrow_string;
9300 }
9301 else
9302 {
5f5c8ee5
GM
9303 /* Force a thorough redisplay the next time by setting
9304 last_arrow_position and last_arrow_string to t, which is
4b41cebb 9305 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
9306 last_arrow_position = Qt;
9307 last_arrow_string = Qt;
9308 }
9309}
5f5c8ee5
GM
9310
9311
9312/* Return value in display table DP (Lisp_Char_Table *) for character
9313 C. Since a display table doesn't have any parent, we don't have to
9314 follow parent. Do not call this function directly but use the
9315 macro DISP_CHAR_VECTOR. */
9316
9317Lisp_Object
9318disp_char_vector (dp, c)
9319 struct Lisp_Char_Table *dp;
9320 int c;
9321{
9322 int code[4], i;
9323 Lisp_Object val;
9324
9325 if (SINGLE_BYTE_CHAR_P (c))
9326 return (dp->contents[c]);
2311178e 9327
c5924f47 9328 SPLIT_CHAR (c, code[0], code[1], code[2]);
260a86a0
KH
9329 if (code[1] < 32)
9330 code[1] = -1;
9331 else if (code[2] < 32)
9332 code[2] = -1;
2311178e 9333
5f5c8ee5
GM
9334 /* Here, the possible range of code[0] (== charset ID) is
9335 128..max_charset. Since the top level char table contains data
9336 for multibyte characters after 256th element, we must increment
9337 code[0] by 128 to get a correct index. */
9338 code[0] += 128;
9339 code[3] = -1; /* anchor */
9340
9341 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
9342 {
9343 val = dp->contents[code[i]];
9344 if (!SUB_CHAR_TABLE_P (val))
9345 return (NILP (val) ? dp->defalt : val);
9346 }
2311178e 9347
5f5c8ee5
GM
9348 /* Here, val is a sub char table. We return the default value of
9349 it. */
9350 return (dp->defalt);
9351}
9352
9353
a2889657 9354\f
5f5c8ee5
GM
9355/***********************************************************************
9356 Window Redisplay
9357 ***********************************************************************/
a2725ab2 9358
5f5c8ee5 9359/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
9360
9361static void
5f5c8ee5
GM
9362redisplay_windows (window)
9363 Lisp_Object window;
90adcf20 9364{
5f5c8ee5
GM
9365 while (!NILP (window))
9366 {
9367 struct window *w = XWINDOW (window);
2311178e 9368
5f5c8ee5
GM
9369 if (!NILP (w->hchild))
9370 redisplay_windows (w->hchild);
9371 else if (!NILP (w->vchild))
9372 redisplay_windows (w->vchild);
9373 else
82a7ab23
RS
9374 {
9375 displayed_buffer = XBUFFER (w->buffer);
7033d6df
RS
9376 /* Use list_of_error, not Qerror, so that
9377 we catch only errors and don't run the debugger. */
2311178e 9378 internal_condition_case_1 (redisplay_window_0, window,
7033d6df 9379 list_of_error,
82a7ab23
RS
9380 redisplay_window_error);
9381 }
a2725ab2 9382
5f5c8ee5
GM
9383 window = w->next;
9384 }
9385}
9386
82a7ab23
RS
9387static Lisp_Object
9388redisplay_window_error ()
9389{
9390 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
9391 return Qnil;
9392}
9393
9394static Lisp_Object
9395redisplay_window_0 (window)
9396 Lisp_Object window;
9397{
9398 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
9399 redisplay_window (window, 0);
9400 return Qnil;
9401}
5f5c8ee5 9402
82a7ab23
RS
9403static Lisp_Object
9404redisplay_window_1 (window)
9405 Lisp_Object window;
9406{
9407 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
9408 redisplay_window (window, 1);
9409 return Qnil;
9410}
9411\f
5f5c8ee5
GM
9412/* Set cursor position of W. PT is assumed to be displayed in ROW.
9413 DELTA is the number of bytes by which positions recorded in ROW
9414 differ from current buffer positions. */
9415
9416void
9417set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
9418 struct window *w;
9419 struct glyph_row *row;
9420 struct glyph_matrix *matrix;
9421 int delta, delta_bytes, dy, dvpos;
9422{
9423 struct glyph *glyph = row->glyphs[TEXT_AREA];
9424 struct glyph *end = glyph + row->used[TEXT_AREA];
9425 int x = row->x;
9426 int pt_old = PT - delta;
9427
9428 /* Skip over glyphs not having an object at the start of the row.
9429 These are special glyphs like truncation marks on terminal
9430 frames. */
9431 if (row->displays_text_p)
9432 while (glyph < end
6fc556fd 9433 && INTEGERP (glyph->object)
5f5c8ee5
GM
9434 && glyph->charpos < 0)
9435 {
9436 x += glyph->pixel_width;
9437 ++glyph;
9438 }
9439
9440 while (glyph < end
6fc556fd 9441 && !INTEGERP (glyph->object)
5f5c8ee5
GM
9442 && (!BUFFERP (glyph->object)
9443 || glyph->charpos < pt_old))
9444 {
9445 x += glyph->pixel_width;
9446 ++glyph;
9447 }
9448
9449 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
9450 w->cursor.x = x;
9451 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
9452 w->cursor.y = row->y + dy;
9453
9454 if (w == XWINDOW (selected_window))
9455 {
9456 if (!row->continued_p
9457 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
9458 && row->x == 0)
9459 {
9460 this_line_buffer = XBUFFER (w->buffer);
2311178e 9461
5f5c8ee5
GM
9462 CHARPOS (this_line_start_pos)
9463 = MATRIX_ROW_START_CHARPOS (row) + delta;
9464 BYTEPOS (this_line_start_pos)
9465 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
2311178e 9466
5f5c8ee5
GM
9467 CHARPOS (this_line_end_pos)
9468 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
9469 BYTEPOS (this_line_end_pos)
9470 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
2311178e 9471
5f5c8ee5
GM
9472 this_line_y = w->cursor.y;
9473 this_line_pixel_height = row->height;
9474 this_line_vpos = w->cursor.vpos;
9475 this_line_start_x = row->x;
9476 }
9477 else
9478 CHARPOS (this_line_start_pos) = 0;
9479 }
9480}
9481
9482
9483/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
9484 start STARTP. Sets the window start of WINDOW to that position.
9485
9486 We assume that the window's buffer is really current. */
5f5c8ee5
GM
9487
9488static INLINE struct text_pos
9489run_window_scroll_functions (window, startp)
9490 Lisp_Object window;
9491 struct text_pos startp;
9492{
9493 struct window *w = XWINDOW (window);
9494 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
9495
9496 if (current_buffer != XBUFFER (w->buffer))
9497 abort ();
9498
5f5c8ee5
GM
9499 if (!NILP (Vwindow_scroll_functions))
9500 {
2311178e 9501 run_hook_with_args_2 (Qwindow_scroll_functions, window,
5f5c8ee5
GM
9502 make_number (CHARPOS (startp)));
9503 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
9504 /* In case the hook functions switch buffers. */
9505 if (current_buffer != XBUFFER (w->buffer))
9506 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 9507 }
90adcf20 9508
5f5c8ee5
GM
9509 return startp;
9510}
9511
9512
ddf6b9a3
RS
9513/* Make sure the line containing the cursor is fully visible.
9514 A value of 1 means there is nothing to be done.
9515 (Either the line is fully visible, or it cannot be made so,
9516 or we cannot tell.)
9517 A value of 0 means the caller should do scrolling
9518 as if point had gone off the screen. */
5f5c8ee5 9519
cb617e7c 9520static int
5f5c8ee5
GM
9521make_cursor_line_fully_visible (w)
9522 struct window *w;
9523{
9524 struct glyph_matrix *matrix;
9525 struct glyph_row *row;
478d746b 9526 int window_height;
2311178e 9527
5f5c8ee5
GM
9528 /* It's not always possible to find the cursor, e.g, when a window
9529 is full of overlay strings. Don't do anything in that case. */
9530 if (w->cursor.vpos < 0)
cb617e7c 9531 return 1;
2311178e 9532
5f5c8ee5
GM
9533 matrix = w->desired_matrix;
9534 row = MATRIX_ROW (matrix, w->cursor.vpos);
9535
acda20e1 9536 /* If the cursor row is not partially visible, there's nothing to do. */
b28cb6ed 9537 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
cb617e7c 9538 return 1;
b28cb6ed
GM
9539
9540 /* If the row the cursor is in is taller than the window's height,
9541 it's not clear what to do, so do nothing. */
9542 window_height = window_box_height (w);
9543 if (row->height >= window_height)
cb617e7c 9544 return 1;
b28cb6ed 9545
ddf6b9a3
RS
9546 return 0;
9547
9548#if 0
9549 /* This code used to try to scroll the window just enough to make
9550 the line visible. It returned 0 to say that the caller should
9551 allocate larger glyph matrices. */
9552
b28cb6ed 9553 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
5f5c8ee5
GM
9554 {
9555 int dy = row->height - row->visible_height;
9556 w->vscroll = 0;
9557 w->cursor.y += dy;
9558 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
9559 }
b28cb6ed 9560 else /* MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) */
5f5c8ee5
GM
9561 {
9562 int dy = - (row->height - row->visible_height);
9563 w->vscroll = dy;
9564 w->cursor.y += dy;
9565 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
9566 }
2311178e 9567
5f5c8ee5
GM
9568 /* When we change the cursor y-position of the selected window,
9569 change this_line_y as well so that the display optimization for
9570 the cursor line of the selected window in redisplay_internal uses
9571 the correct y-position. */
9572 if (w == XWINDOW (selected_window))
9573 this_line_y = w->cursor.y;
cb617e7c
GM
9574
9575 /* If vscrolling requires a larger glyph matrix, arrange for a fresh
9576 redisplay with larger matrices. */
9577 if (matrix->nrows < required_matrix_height (w))
9578 {
9579 fonts_changed_p = 1;
9580 return 0;
9581 }
9582
9583 return 1;
ddf6b9a3 9584#endif /* 0 */
5f5c8ee5
GM
9585}
9586
9587
9588/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
9589 non-zero means only WINDOW is redisplayed in redisplay_internal.
9590 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
9591 in redisplay_window to bring a partially visible line into view in
9592 the case that only the cursor has moved.
9593
9594 Value is
9595
9596 1 if scrolling succeeded
2311178e 9597
5f5c8ee5 9598 0 if scrolling didn't find point.
2311178e 9599
5f5c8ee5
GM
9600 -1 if new fonts have been loaded so that we must interrupt
9601 redisplay, adjust glyph matrices, and try again. */
9602
cb617e7c
GM
9603enum
9604{
9605 SCROLLING_SUCCESS,
9606 SCROLLING_FAILED,
9607 SCROLLING_NEED_LARGER_MATRICES
9608};
9609
5f5c8ee5
GM
9610static int
9611try_scrolling (window, just_this_one_p, scroll_conservatively,
9612 scroll_step, temp_scroll_step)
9613 Lisp_Object window;
9614 int just_this_one_p;
31ade731 9615 EMACS_INT scroll_conservatively, scroll_step;
5f5c8ee5
GM
9616 int temp_scroll_step;
9617{
9618 struct window *w = XWINDOW (window);
9619 struct frame *f = XFRAME (w->frame);
9620 struct text_pos scroll_margin_pos;
9621 struct text_pos pos;
9622 struct text_pos startp;
9623 struct it it;
9624 Lisp_Object window_end;
9625 int this_scroll_margin;
9626 int dy = 0;
9627 int scroll_max;
b8a63ccb 9628 int rc;
5f5c8ee5
GM
9629 int amount_to_scroll = 0;
9630 Lisp_Object aggressive;
9631 int height;
9632
9633#if GLYPH_DEBUG
9634 debug_method_add (w, "try_scrolling");
78614721 9635#endif
5f5c8ee5
GM
9636
9637 SET_TEXT_POS_FROM_MARKER (startp, w->start);
2311178e 9638
5f5c8ee5
GM
9639 /* Compute scroll margin height in pixels. We scroll when point is
9640 within this distance from the top or bottom of the window. */
9641 if (scroll_margin > 0)
90adcf20 9642 {
5f5c8ee5
GM
9643 this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
9644 this_scroll_margin *= CANON_Y_UNIT (f);
9645 }
9646 else
9647 this_scroll_margin = 0;
9648
9649 /* Compute how much we should try to scroll maximally to bring point
9650 into view. */
0894e696
SM
9651 if (scroll_step || scroll_conservatively || temp_scroll_step)
9652 scroll_max = max (scroll_step,
9653 max (scroll_conservatively, temp_scroll_step));
5f5c8ee5
GM
9654 else if (NUMBERP (current_buffer->scroll_down_aggressively)
9655 || NUMBERP (current_buffer->scroll_up_aggressively))
9656 /* We're trying to scroll because of aggressive scrolling
9657 but no scroll_step is set. Choose an arbitrary one. Maybe
9658 there should be a variable for this. */
9659 scroll_max = 10;
9660 else
9661 scroll_max = 0;
9662 scroll_max *= CANON_Y_UNIT (f);
9663
9664 /* Decide whether we have to scroll down. Start at the window end
9665 and move this_scroll_margin up to find the position of the scroll
9666 margin. */
9667 window_end = Fwindow_end (window, Qt);
9668 CHARPOS (scroll_margin_pos) = XINT (window_end);
9669 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
9670 if (this_scroll_margin)
9671 {
9672 start_display (&it, w, scroll_margin_pos);
9673 move_it_vertically (&it, - this_scroll_margin);
9674 scroll_margin_pos = it.current.pos;
9675 }
9676
9677 if (PT >= CHARPOS (scroll_margin_pos))
9678 {
9679 int y0;
2311178e 9680
ddf6b9a3 9681 too_near_end:
5f5c8ee5
GM
9682 /* Point is in the scroll margin at the bottom of the window, or
9683 below. Compute a new window start that makes point visible. */
47589c8c 9684
5f5c8ee5
GM
9685 /* Compute the distance from the scroll margin to PT.
9686 Give up if the distance is greater than scroll_max. */
9687 start_display (&it, w, scroll_margin_pos);
9688 y0 = it.current_y;
9689 move_it_to (&it, PT, 0, it.last_visible_y, -1,
9690 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
539e92ad
GM
9691
9692 /* To make point visible, we have to move the window start
9693 down so that the line the cursor is in is visible, which
9694 means we have to add in the height of the cursor line. */
9695 dy = line_bottom_y (&it) - y0;
2311178e 9696
5f5c8ee5 9697 if (dy > scroll_max)
cb617e7c 9698 return SCROLLING_FAILED;
2311178e 9699
5f5c8ee5
GM
9700 /* Move the window start down. If scrolling conservatively,
9701 move it just enough down to make point visible. If
9702 scroll_step is set, move it down by scroll_step. */
9703 start_display (&it, w, startp);
9704
9705 if (scroll_conservatively)
e89aaabd
GM
9706 amount_to_scroll
9707 = max (max (dy, CANON_Y_UNIT (f)),
9708 CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
5f5c8ee5
GM
9709 else if (scroll_step || temp_scroll_step)
9710 amount_to_scroll = scroll_max;
9711 else
90adcf20 9712 {
46226c1d 9713 aggressive = current_buffer->scroll_up_aggressively;
5f5c8ee5 9714 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 9715 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
9716 if (NUMBERP (aggressive))
9717 amount_to_scroll = XFLOATINT (aggressive) * height;
9718 }
a2725ab2 9719
5f5c8ee5 9720 if (amount_to_scroll <= 0)
cb617e7c 9721 return SCROLLING_FAILED;
a2725ab2 9722
5f5c8ee5
GM
9723 move_it_vertically (&it, amount_to_scroll);
9724 startp = it.current.pos;
9725 }
9726 else
9727 {
9728 /* See if point is inside the scroll margin at the top of the
9729 window. */
9730 scroll_margin_pos = startp;
9731 if (this_scroll_margin)
9732 {
9733 start_display (&it, w, startp);
9734 move_it_vertically (&it, this_scroll_margin);
9735 scroll_margin_pos = it.current.pos;
9736 }
9737
9738 if (PT < CHARPOS (scroll_margin_pos))
9739 {
9740 /* Point is in the scroll margin at the top of the window or
9741 above what is displayed in the window. */
9742 int y0;
2311178e 9743
5f5c8ee5
GM
9744 /* Compute the vertical distance from PT to the scroll
9745 margin position. Give up if distance is greater than
9746 scroll_max. */
9747 SET_TEXT_POS (pos, PT, PT_BYTE);
9748 start_display (&it, w, pos);
9749 y0 = it.current_y;
9750 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
9751 it.last_visible_y, -1,
9752 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
9753 dy = it.current_y - y0;
9754 if (dy > scroll_max)
cb617e7c 9755 return SCROLLING_FAILED;
2311178e 9756
5f5c8ee5
GM
9757 /* Compute new window start. */
9758 start_display (&it, w, startp);
2311178e 9759
5f5c8ee5 9760 if (scroll_conservatively)
0894e696
SM
9761 amount_to_scroll =
9762 max (dy, CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
5f5c8ee5
GM
9763 else if (scroll_step || temp_scroll_step)
9764 amount_to_scroll = scroll_max;
538f13d4 9765 else
5f5c8ee5 9766 {
46226c1d 9767 aggressive = current_buffer->scroll_down_aggressively;
5f5c8ee5 9768 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 9769 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
9770 if (NUMBERP (aggressive))
9771 amount_to_scroll = XFLOATINT (aggressive) * height;
9772 }
a2725ab2 9773
5f5c8ee5 9774 if (amount_to_scroll <= 0)
cb617e7c 9775 return SCROLLING_FAILED;
2311178e 9776
5f5c8ee5
GM
9777 move_it_vertically (&it, - amount_to_scroll);
9778 startp = it.current.pos;
90adcf20
RS
9779 }
9780 }
a2889657 9781
5f5c8ee5
GM
9782 /* Run window scroll functions. */
9783 startp = run_window_scroll_functions (window, startp);
90adcf20 9784
5f5c8ee5
GM
9785 /* Display the window. Give up if new fonts are loaded, or if point
9786 doesn't appear. */
9787 if (!try_window (window, startp))
cb617e7c 9788 rc = SCROLLING_NEED_LARGER_MATRICES;
5f5c8ee5
GM
9789 else if (w->cursor.vpos < 0)
9790 {
9791 clear_glyph_matrix (w->desired_matrix);
cb617e7c 9792 rc = SCROLLING_FAILED;
5f5c8ee5
GM
9793 }
9794 else
9795 {
9796 /* Maybe forget recorded base line for line number display. */
2311178e 9797 if (!just_this_one_p
5f5c8ee5 9798 || current_buffer->clip_changed
9142dd5b 9799 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5 9800 w->base_line_number = Qnil;
2311178e 9801
ddf6b9a3
RS
9802 /* If cursor ends up on a partially visible line,
9803 treat that as being off the bottom of the screen. */
9804 if (! make_cursor_line_fully_visible (w))
ef3c2c73
RS
9805 {
9806 clear_glyph_matrix (w->desired_matrix);
9807 goto too_near_end;
9808 }
ddf6b9a3 9809 rc = SCROLLING_SUCCESS;
5f5c8ee5
GM
9810 }
9811
9812 return rc;
a2889657
JB
9813}
9814
5f5c8ee5
GM
9815
9816/* Compute a suitable window start for window W if display of W starts
9817 on a continuation line. Value is non-zero if a new window start
9818 was computed.
9819
9820 The new window start will be computed, based on W's width, starting
9821 from the start of the continued line. It is the start of the
9822 screen line with the minimum distance from the old start W->start. */
9823
9824static int
9825compute_window_start_on_continuation_line (w)
9826 struct window *w;
1f1ff51d 9827{
5f5c8ee5
GM
9828 struct text_pos pos, start_pos;
9829 int window_start_changed_p = 0;
1f1ff51d 9830
5f5c8ee5 9831 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 9832
5f5c8ee5 9833 /* If window start is on a continuation line... Window start may be
2311178e 9834 < BEGV in case there's invisible text at the start of the
5f5c8ee5
GM
9835 buffer (M-x rmail, for example). */
9836 if (CHARPOS (start_pos) > BEGV
9837 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 9838 {
5f5c8ee5
GM
9839 struct it it;
9840 struct glyph_row *row;
f3751a65
GM
9841
9842 /* Handle the case that the window start is out of range. */
9843 if (CHARPOS (start_pos) < BEGV)
9844 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
9845 else if (CHARPOS (start_pos) > ZV)
9846 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
2311178e 9847
5f5c8ee5
GM
9848 /* Find the start of the continued line. This should be fast
9849 because scan_buffer is fast (newline cache). */
045dee35 9850 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
9851 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
9852 row, DEFAULT_FACE_ID);
9853 reseat_at_previous_visible_line_start (&it);
9854
9855 /* If the line start is "too far" away from the window start,
9856 say it takes too much time to compute a new window start. */
9857 if (CHARPOS (start_pos) - IT_CHARPOS (it)
9858 < XFASTINT (w->height) * XFASTINT (w->width))
9859 {
9860 int min_distance, distance;
2311178e 9861
5f5c8ee5
GM
9862 /* Move forward by display lines to find the new window
9863 start. If window width was enlarged, the new start can
9864 be expected to be > the old start. If window width was
9865 decreased, the new window start will be < the old start.
9866 So, we're looking for the display line start with the
9867 minimum distance from the old window start. */
9868 pos = it.current.pos;
9869 min_distance = INFINITY;
9870 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
9871 distance < min_distance)
9872 {
9873 min_distance = distance;
9874 pos = it.current.pos;
9875 move_it_by_lines (&it, 1, 0);
9876 }
2311178e 9877
5f5c8ee5
GM
9878 /* Set the window start there. */
9879 SET_MARKER_FROM_TEXT_POS (w->start, pos);
9880 window_start_changed_p = 1;
9881 }
1f1ff51d 9882 }
2311178e 9883
5f5c8ee5 9884 return window_start_changed_p;
1f1ff51d
KH
9885}
9886
5f5c8ee5 9887
1dd5768b 9888/* Try cursor movement in case text has not changed in window WINDOW,
47589c8c
GM
9889 with window start STARTP. Value is
9890
cb617e7c 9891 CURSOR_MOVEMENT_SUCCESS if successful
2311178e 9892
cb617e7c
GM
9893 CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used
9894
9895 CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the
9896 display. *SCROLL_STEP is set to 1, under certain circumstances, if
9897 we want to scroll as if scroll-step were set to 1. See the code.
9898
9899 CURSOR_MOVEMENT_NEED_LARGER_MATRICES if we need larger matrices, in
9900 which case we have to abort this redisplay, and adjust matrices
9901 first. */
9902
2311178e 9903enum
cb617e7c
GM
9904{
9905 CURSOR_MOVEMENT_SUCCESS,
9906 CURSOR_MOVEMENT_CANNOT_BE_USED,
9907 CURSOR_MOVEMENT_MUST_SCROLL,
9908 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
9909};
47589c8c
GM
9910
9911static int
9912try_cursor_movement (window, startp, scroll_step)
9913 Lisp_Object window;
9914 struct text_pos startp;
9915 int *scroll_step;
9916{
9917 struct window *w = XWINDOW (window);
9918 struct frame *f = XFRAME (w->frame);
cb617e7c 9919 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
2311178e 9920
69d1f7c9 9921#if GLYPH_DEBUG
76cb5e06
GM
9922 if (inhibit_try_cursor_movement)
9923 return rc;
9924#endif
9925
47589c8c
GM
9926 /* Handle case where text has not changed, only point, and it has
9927 not moved off the frame. */
9928 if (/* Point may be in this window. */
9929 PT >= CHARPOS (startp)
47589c8c
GM
9930 /* Selective display hasn't changed. */
9931 && !current_buffer->clip_changed
4db87380
GM
9932 /* Function force-mode-line-update is used to force a thorough
9933 redisplay. It sets either windows_or_buffers_changed or
9934 update_mode_lines. So don't take a shortcut here for these
9935 cases. */
9936 && !update_mode_lines
9937 && !windows_or_buffers_changed
5fb96e96 9938 && !cursor_type_changed
2311178e 9939 /* Can't use this case if highlighting a region. When a
47589c8c
GM
9940 region exists, cursor movement has to do more than just
9941 set the cursor. */
9942 && !(!NILP (Vtransient_mark_mode)
9943 && !NILP (current_buffer->mark_active))
9944 && NILP (w->region_showing)
9945 && NILP (Vshow_trailing_whitespace)
9946 /* Right after splitting windows, last_point may be nil. */
9947 && INTEGERP (w->last_point)
9948 /* This code is not used for mini-buffer for the sake of the case
9949 of redisplaying to replace an echo area message; since in
9950 that case the mini-buffer contents per se are usually
9951 unchanged. This code is of no real use in the mini-buffer
9952 since the handling of this_line_start_pos, etc., in redisplay
9953 handles the same cases. */
9954 && !EQ (window, minibuf_window)
9955 /* When splitting windows or for new windows, it happens that
9956 redisplay is called with a nil window_end_vpos or one being
9957 larger than the window. This should really be fixed in
9958 window.c. I don't have this on my list, now, so we do
9959 approximately the same as the old redisplay code. --gerd. */
9960 && INTEGERP (w->window_end_vpos)
9961 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
9962 && (FRAME_WINDOW_P (f)
9963 || !MARKERP (Voverlay_arrow_position)
9964 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
9965 {
9966 int this_scroll_margin;
8ee5b6a3 9967 struct glyph_row *row = NULL;
47589c8c
GM
9968
9969#if GLYPH_DEBUG
9970 debug_method_add (w, "cursor movement");
9971#endif
9972
9973 /* Scroll if point within this distance from the top or bottom
9974 of the window. This is a pixel value. */
9975 this_scroll_margin = max (0, scroll_margin);
9976 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
9977 this_scroll_margin *= CANON_Y_UNIT (f);
9978
9979 /* Start with the row the cursor was displayed during the last
9980 not paused redisplay. Give up if that row is not valid. */
bd9d0f3f
GM
9981 if (w->last_cursor.vpos < 0
9982 || w->last_cursor.vpos >= w->current_matrix->nrows)
cb617e7c 9983 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
9984 else
9985 {
9986 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
9987 if (row->mode_line_p)
9988 ++row;
9989 if (!row->enabled_p)
cb617e7c 9990 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
9991 }
9992
cb617e7c 9993 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
47589c8c
GM
9994 {
9995 int scroll_p = 0;
68c5d1db 9996 int last_y = window_text_bottom_y (w) - this_scroll_margin;
2311178e 9997
47589c8c
GM
9998 if (PT > XFASTINT (w->last_point))
9999 {
10000 /* Point has moved forward. */
47589c8c
GM
10001 while (MATRIX_ROW_END_CHARPOS (row) < PT
10002 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
10003 {
10004 xassert (row->enabled_p);
10005 ++row;
10006 }
10007
10008 /* The end position of a row equals the start position
10009 of the next row. If PT is there, we would rather
cafafe0b
GM
10010 display it in the next line. */
10011 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
10012 && MATRIX_ROW_END_CHARPOS (row) == PT
10013 && !cursor_row_p (w, row))
10014 ++row;
47589c8c
GM
10015
10016 /* If within the scroll margin, scroll. Note that
10017 MATRIX_ROW_BOTTOM_Y gives the pixel position at which
10018 the next line would be drawn, and that
10019 this_scroll_margin can be zero. */
10020 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
10021 || PT > MATRIX_ROW_END_CHARPOS (row)
10022 /* Line is completely visible last line in window
10023 and PT is to be set in the next line. */
10024 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
10025 && PT == MATRIX_ROW_END_CHARPOS (row)
10026 && !row->ends_at_zv_p
10027 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
10028 scroll_p = 1;
10029 }
10030 else if (PT < XFASTINT (w->last_point))
10031 {
10032 /* Cursor has to be moved backward. Note that PT >=
10033 CHARPOS (startp) because of the outer
10034 if-statement. */
10035 while (!row->mode_line_p
10036 && (MATRIX_ROW_START_CHARPOS (row) > PT
10037 || (MATRIX_ROW_START_CHARPOS (row) == PT
10038 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
10039 && (row->y > this_scroll_margin
10040 || CHARPOS (startp) == BEGV))
10041 {
10042 xassert (row->enabled_p);
10043 --row;
10044 }
10045
10046 /* Consider the following case: Window starts at BEGV,
10047 there is invisible, intangible text at BEGV, so that
10048 display starts at some point START > BEGV. It can
10049 happen that we are called with PT somewhere between
10050 BEGV and START. Try to handle that case. */
10051 if (row < w->current_matrix->rows
10052 || row->mode_line_p)
10053 {
10054 row = w->current_matrix->rows;
10055 if (row->mode_line_p)
10056 ++row;
10057 }
10058
10059 /* Due to newlines in overlay strings, we may have to
10060 skip forward over overlay strings. */
68c5d1db
GM
10061 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
10062 && MATRIX_ROW_END_CHARPOS (row) == PT
10063 && !cursor_row_p (w, row))
47589c8c 10064 ++row;
2311178e 10065
47589c8c
GM
10066 /* If within the scroll margin, scroll. */
10067 if (row->y < this_scroll_margin
10068 && CHARPOS (startp) != BEGV)
10069 scroll_p = 1;
10070 }
10071
10072 if (PT < MATRIX_ROW_START_CHARPOS (row)
10073 || PT > MATRIX_ROW_END_CHARPOS (row))
10074 {
10075 /* if PT is not in the glyph row, give up. */
cb617e7c 10076 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c 10077 }
440fc135 10078 else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
47589c8c 10079 {
8de4aaf8
GM
10080 if (PT == MATRIX_ROW_END_CHARPOS (row)
10081 && !row->ends_at_zv_p
10082 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
cb617e7c 10083 rc = CURSOR_MOVEMENT_MUST_SCROLL;
3f7e3031 10084 else if (row->height > window_box_height (w))
440fc135 10085 {
8de4aaf8
GM
10086 /* If we end up in a partially visible line, let's
10087 make it fully visible, except when it's taller
10088 than the window, in which case we can't do much
10089 about it. */
440fc135 10090 *scroll_step = 1;
cb617e7c 10091 rc = CURSOR_MOVEMENT_MUST_SCROLL;
440fc135
GM
10092 }
10093 else
10094 {
10095 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
10096 try_window (window, startp);
cb617e7c 10097 if (!make_cursor_line_fully_visible (w))
ddf6b9a3 10098 rc = CURSOR_MOVEMENT_MUST_SCROLL;
cb617e7c
GM
10099 else
10100 rc = CURSOR_MOVEMENT_SUCCESS;
440fc135 10101 }
47589c8c
GM
10102 }
10103 else if (scroll_p)
cb617e7c 10104 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
10105 else
10106 {
10107 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
cb617e7c 10108 rc = CURSOR_MOVEMENT_SUCCESS;
47589c8c
GM
10109 }
10110 }
10111 }
10112
10113 return rc;
10114}
10115
10116
5f5c8ee5 10117/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
b60c9653
RS
10118 selected_window is redisplayed.
10119
10120 We can return without actually redisplaying the window if
10121 fonts_changed_p is nonzero. In that case, redisplay_internal will
10122 retry. */
90adcf20 10123
a2889657 10124static void
5f5c8ee5 10125redisplay_window (window, just_this_one_p)
a2889657 10126 Lisp_Object window;
5f5c8ee5 10127 int just_this_one_p;
a2889657 10128{
5f5c8ee5
GM
10129 struct window *w = XWINDOW (window);
10130 struct frame *f = XFRAME (w->frame);
10131 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 10132 struct buffer *old = current_buffer;
5f5c8ee5 10133 struct text_pos lpoint, opoint, startp;
e481f960 10134 int update_mode_line;
5f5c8ee5
GM
10135 int tem;
10136 struct it it;
10137 /* Record it now because it's overwritten. */
10138 int current_matrix_up_to_date_p = 0;
c62c1bb5
RS
10139 /* This is less strict than current_matrix_up_to_date_p.
10140 It indictes that the buffer contents and narrowing are unchanged. */
10141 int buffer_unchanged_p = 0;
5f5c8ee5 10142 int temp_scroll_step = 0;
331379bf 10143 int count = SPECPDL_INDEX ();
47589c8c 10144 int rc;
ddf6b9a3 10145 int centering_position;
a2889657 10146
5f5c8ee5
GM
10147 SET_TEXT_POS (lpoint, PT, PT_BYTE);
10148 opoint = lpoint;
a2889657 10149
5f5c8ee5
GM
10150 /* W must be a leaf window here. */
10151 xassert (!NILP (w->buffer));
10152#if GLYPH_DEBUG
10153 *w->desired_matrix->method = 0;
10154#endif
2e54982e
RS
10155
10156 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
10157
10158 reconsider_clip_changes (w, buffer);
2311178e
TTN
10159
10160 /* Has the mode line to be updated? */
5f5c8ee5
GM
10161 update_mode_line = (!NILP (w->update_mode_line)
10162 || update_mode_lines
c62c1bb5
RS
10163 || buffer->clip_changed
10164 || buffer->prevent_redisplay_optimizations_p);
8de2d90b
JB
10165
10166 if (MINI_WINDOW_P (w))
10167 {
5f5c8ee5 10168 if (w == XWINDOW (echo_area_window)
c6e89d6c 10169 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
10170 {
10171 if (update_mode_line)
10172 /* We may have to update a tty frame's menu bar or a
e037b9ec 10173 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
10174 goto finish_menu_bars;
10175 else
10176 /* We've already displayed the echo area glyphs in this window. */
10177 goto finish_scroll_bars;
10178 }
73af359d 10179 else if (w != XWINDOW (minibuf_window))
8de2d90b 10180 {
5f5c8ee5
GM
10181 /* W is a mini-buffer window, but it's not the currently
10182 active one, so clear it. */
10183 int yb = window_text_bottom_y (w);
10184 struct glyph_row *row;
10185 int y;
10186
10187 for (y = 0, row = w->desired_matrix->rows;
10188 y < yb;
10189 y += row->height, ++row)
10190 blank_row (w, row, y);
88f22aff 10191 goto finish_scroll_bars;
8de2d90b 10192 }
c095a1dd
GM
10193
10194 clear_glyph_matrix (w->desired_matrix);
8de2d90b 10195 }
a2889657 10196
5f5c8ee5
GM
10197 /* Otherwise set up data on this window; select its buffer and point
10198 value. */
6a93695f
GM
10199 /* Really select the buffer, for the sake of buffer-local
10200 variables. */
10201 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5
GM
10202 SET_TEXT_POS (opoint, PT, PT_BYTE);
10203
10204 current_matrix_up_to_date_p
10205 = (!NILP (w->window_end_valid)
10206 && !current_buffer->clip_changed
c62c1bb5 10207 && !current_buffer->prevent_redisplay_optimizations_p
5f5c8ee5
GM
10208 && XFASTINT (w->last_modified) >= MODIFF
10209 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 10210
c62c1bb5
RS
10211 buffer_unchanged_p
10212 = (!NILP (w->window_end_valid)
10213 && !current_buffer->clip_changed
3f1258d0 10214 && XFASTINT (w->last_modified) >= MODIFF
c62c1bb5
RS
10215 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
10216
5f5c8ee5
GM
10217 /* When windows_or_buffers_changed is non-zero, we can't rely on
10218 the window end being valid, so set it to nil there. */
10219 if (windows_or_buffers_changed)
10220 {
10221 /* If window starts on a continuation line, maybe adjust the
10222 window start in case the window's width changed. */
10223 if (XMARKER (w->start)->buffer == current_buffer)
10224 compute_window_start_on_continuation_line (w);
2311178e 10225
5f5c8ee5
GM
10226 w->window_end_valid = Qnil;
10227 }
12adba34 10228
5f5c8ee5
GM
10229 /* Some sanity checks. */
10230 CHECK_WINDOW_END (w);
10231 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 10232 abort ();
5f5c8ee5 10233 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 10234 abort ();
a2889657 10235
28995e67
RS
10236 /* If %c is in mode line, update it if needed. */
10237 if (!NILP (w->column_number_displayed)
10238 /* This alternative quickly identifies a common case
10239 where no change is needed. */
10240 && !(PT == XFASTINT (w->last_point)
8850a573
RS
10241 && XFASTINT (w->last_modified) >= MODIFF
10242 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
10243 && (XFASTINT (w->column_number_displayed)
10244 != (int) current_column ())) /* iftc */
10245 update_mode_line = 1;
28995e67 10246
5f5c8ee5
GM
10247 /* Count number of windows showing the selected buffer. An indirect
10248 buffer counts as its base buffer. */
10249 if (!just_this_one_p)
42640f83
RS
10250 {
10251 struct buffer *current_base, *window_base;
10252 current_base = current_buffer;
10253 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
10254 if (current_base->base_buffer)
10255 current_base = current_base->base_buffer;
10256 if (window_base->base_buffer)
10257 window_base = window_base->base_buffer;
10258 if (current_base == window_base)
10259 buffer_shared++;
10260 }
a2889657 10261
5f5c8ee5
GM
10262 /* Point refers normally to the selected window. For any other
10263 window, set up appropriate value. */
a2889657
JB
10264 if (!EQ (window, selected_window))
10265 {
12adba34
RS
10266 int new_pt = XMARKER (w->pointm)->charpos;
10267 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 10268 if (new_pt < BEGV)
a2889657 10269 {
f67a0f51 10270 new_pt = BEGV;
12adba34
RS
10271 new_pt_byte = BEGV_BYTE;
10272 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 10273 }
f67a0f51 10274 else if (new_pt > (ZV - 1))
a2889657 10275 {
f67a0f51 10276 new_pt = ZV;
12adba34
RS
10277 new_pt_byte = ZV_BYTE;
10278 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 10279 }
2311178e 10280
f67a0f51 10281 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 10282 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
10283 }
10284
f4faa47c 10285 /* If any of the character widths specified in the display table
5f5c8ee5
GM
10286 have changed, invalidate the width run cache. It's true that
10287 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
10288 redisplay goes (non-fatally) haywire when the display table is
10289 changed, so why should we worry about doing any better? */
10290 if (current_buffer->width_run_cache)
10291 {
f908610f 10292 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
10293
10294 if (! disptab_matches_widthtab (disptab,
10295 XVECTOR (current_buffer->width_table)))
10296 {
10297 invalidate_region_cache (current_buffer,
10298 current_buffer->width_run_cache,
10299 BEG, Z);
10300 recompute_width_table (current_buffer, disptab);
10301 }
10302 }
10303
a2889657 10304 /* If window-start is screwed up, choose a new one. */
a2889657
JB
10305 if (XMARKER (w->start)->buffer != current_buffer)
10306 goto recenter;
10307
5f5c8ee5 10308 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 10309
cf0df6ab
RS
10310 /* If someone specified a new starting point but did not insist,
10311 check whether it can be used. */
cfad01b4
GM
10312 if (!NILP (w->optional_new_start)
10313 && CHARPOS (startp) >= BEGV
10314 && CHARPOS (startp) <= ZV)
cf0df6ab
RS
10315 {
10316 w->optional_new_start = Qnil;
5f5c8ee5
GM
10317 start_display (&it, w, startp);
10318 move_it_to (&it, PT, 0, it.last_visible_y, -1,
10319 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
10320 if (IT_CHARPOS (it) == PT)
cf0df6ab
RS
10321 w->force_start = Qt;
10322 }
10323
8de2d90b 10324 /* Handle case where place to start displaying has been specified,
aa6d10fa 10325 unless the specified location is outside the accessible range. */
9472f927
GM
10326 if (!NILP (w->force_start)
10327 || w->frozen_window_start_p)
a2889657 10328 {
b60c9653
RS
10329 /* We set this later on if we have to adjust point. */
10330 int new_vpos = -1;
10331
e63574d7 10332 w->force_start = Qnil;
5f5c8ee5 10333 w->vscroll = 0;
b5174a51 10334 w->window_end_valid = Qnil;
5f5c8ee5
GM
10335
10336 /* Forget any recorded base line for line number display. */
c62c1bb5 10337 if (!buffer_unchanged_p)
5f5c8ee5
GM
10338 w->base_line_number = Qnil;
10339
75c43375
RS
10340 /* Redisplay the mode line. Select the buffer properly for that.
10341 Also, run the hook window-scroll-functions
10342 because we have scrolled. */
e63574d7
RS
10343 /* Note, we do this after clearing force_start because
10344 if there's an error, it is better to forget about force_start
10345 than to get into an infinite loop calling the hook functions
10346 and having them get more errors. */
75c43375
RS
10347 if (!update_mode_line
10348 || ! NILP (Vwindow_scroll_functions))
e481f960 10349 {
e481f960
RS
10350 update_mode_line = 1;
10351 w->update_mode_line = Qt;
5f5c8ee5 10352 startp = run_window_scroll_functions (window, startp);
e481f960 10353 }
2311178e 10354
ac90c44f
GM
10355 w->last_modified = make_number (0);
10356 w->last_overlay_modified = make_number (0);
5f5c8ee5
GM
10357 if (CHARPOS (startp) < BEGV)
10358 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
10359 else if (CHARPOS (startp) > ZV)
10360 SET_TEXT_POS (startp, ZV, ZV_BYTE);
2311178e
TTN
10361
10362 /* Redisplay, then check if cursor has been set during the
5f5c8ee5
GM
10363 redisplay. Give up if new fonts were loaded. */
10364 if (!try_window (window, startp))
10365 {
10366 w->force_start = Qt;
10367 clear_glyph_matrix (w->desired_matrix);
b60c9653 10368 goto need_larger_matrices;
5f5c8ee5
GM
10369 }
10370
9472f927 10371 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5 10372 {
b28cb6ed
GM
10373 /* If point does not appear, try to move point so it does
10374 appear. The desired matrix has been built above, so we
10375 can use it here. */
b60c9653
RS
10376 new_vpos = window_box_height (w) / 2;
10377 }
10378
10379 if (!make_cursor_line_fully_visible (w))
10380 {
10381 /* Point does appear, but on a line partly visible at end of window.
10382 Move it back to a fully-visible line. */
10383 new_vpos = window_box_height (w);
10384 }
10385
10386 /* If we need to move point for either of the above reasons,
10387 now actually do it. */
10388 if (new_vpos >= 0)
10389 {
b28cb6ed
GM
10390 struct glyph_row *row;
10391
b28cb6ed 10392 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
b60c9653 10393 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos)
5f5c8ee5
GM
10394 ++row;
10395
10396 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
10397 MATRIX_ROW_START_BYTEPOS (row));
10398
90adcf20 10399 if (w != XWINDOW (selected_window))
12adba34 10400 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
10401 else if (current_buffer == old)
10402 SET_TEXT_POS (lpoint, PT, PT_BYTE);
10403
10404 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
2311178e 10405
5f5c8ee5
GM
10406 /* If we are highlighting the region, then we just changed
10407 the region, so redisplay to show it. */
df0b5ea1
RS
10408 if (!NILP (Vtransient_mark_mode)
10409 && !NILP (current_buffer->mark_active))
6f27fa9b 10410 {
5f5c8ee5
GM
10411 clear_glyph_matrix (w->desired_matrix);
10412 if (!try_window (window, startp))
cb617e7c 10413 goto need_larger_matrices;
6f27fa9b 10414 }
a2889657 10415 }
5f5c8ee5 10416
5f5c8ee5
GM
10417#if GLYPH_DEBUG
10418 debug_method_add (w, "forced window start");
10419#endif
a2889657
JB
10420 goto done;
10421 }
10422
5f5c8ee5 10423 /* Handle case where text has not changed, only point, and it has
3f029ea0
RS
10424 not moved off the frame, and we are not retrying after hscroll.
10425 (current_matrix_up_to_date_p is nonzero when retrying.) */
10426 if (current_matrix_up_to_date_p
47589c8c 10427 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
cb617e7c 10428 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
a2889657 10429 {
cb617e7c
GM
10430 switch (rc)
10431 {
10432 case CURSOR_MOVEMENT_SUCCESS:
10433 goto done;
2311178e 10434
b60c9653 10435#if 0 /* try_cursor_movement never returns this value. */
cb617e7c
GM
10436 case CURSOR_MOVEMENT_NEED_LARGER_MATRICES:
10437 goto need_larger_matrices;
b60c9653 10438#endif
2311178e 10439
cb617e7c
GM
10440 case CURSOR_MOVEMENT_MUST_SCROLL:
10441 goto try_to_scroll;
2311178e 10442
cb617e7c
GM
10443 default:
10444 abort ();
10445 }
a2889657
JB
10446 }
10447 /* If current starting point was originally the beginning of a line
10448 but no longer is, find a new starting point. */
265a9e55 10449 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
10450 && !(CHARPOS (startp) <= BEGV
10451 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 10452 {
5f5c8ee5
GM
10453#if GLYPH_DEBUG
10454 debug_method_add (w, "recenter 1");
10455#endif
a2889657
JB
10456 goto recenter;
10457 }
2311178e 10458
27d16f05
GM
10459 /* Try scrolling with try_window_id. Value is > 0 if update has
10460 been done, it is -1 if we know that the same window start will
10461 not work. It is 0 if unsuccessful for some other reason. */
10462 else if ((tem = try_window_id (w)) != 0)
a2889657 10463 {
5f5c8ee5 10464#if GLYPH_DEBUG
ef121659 10465 debug_method_add (w, "try_window_id %d", tem);
5f5c8ee5
GM
10466#endif
10467
10468 if (fonts_changed_p)
cb617e7c 10469 goto need_larger_matrices;
a2889657
JB
10470 if (tem > 0)
10471 goto done;
ef121659 10472
5f5c8ee5
GM
10473 /* Otherwise try_window_id has returned -1 which means that we
10474 don't want the alternative below this comment to execute. */
a2889657 10475 }
5f5c8ee5
GM
10476 else if (CHARPOS (startp) >= BEGV
10477 && CHARPOS (startp) <= ZV
10478 && PT >= CHARPOS (startp)
10479 && (CHARPOS (startp) < ZV
e9874cee 10480 /* Avoid starting at end of buffer. */
5f5c8ee5 10481 || CHARPOS (startp) == BEGV
8850a573
RS
10482 || (XFASTINT (w->last_modified) >= MODIFF
10483 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 10484 {
5f5c8ee5
GM
10485#if GLYPH_DEBUG
10486 debug_method_add (w, "same window start");
10487#endif
2311178e 10488
5f5c8ee5
GM
10489 /* Try to redisplay starting at same place as before.
10490 If point has not moved off frame, accept the results. */
10491 if (!current_matrix_up_to_date_p
10492 /* Don't use try_window_reusing_current_matrix in this case
15e26c76
GM
10493 because a window scroll function can have changed the
10494 buffer. */
5f5c8ee5
GM
10495 || !NILP (Vwindow_scroll_functions)
10496 || MINI_WINDOW_P (w)
10497 || !try_window_reusing_current_matrix (w))
10498 {
10499 IF_DEBUG (debug_method_add (w, "1"));
10500 try_window (window, startp);
10501 }
10502
10503 if (fonts_changed_p)
cb617e7c 10504 goto need_larger_matrices;
2311178e 10505
5f5c8ee5 10506 if (w->cursor.vpos >= 0)
aa6d10fa 10507 {
2311178e 10508 if (!just_this_one_p
5f5c8ee5 10509 || current_buffer->clip_changed
9142dd5b 10510 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
10511 /* Forget any recorded base line for line number display. */
10512 w->base_line_number = Qnil;
2311178e 10513
cb617e7c 10514 if (!make_cursor_line_fully_visible (w))
ef3c2c73 10515 clear_glyph_matrix (w->desired_matrix);
ddf6b9a3 10516 /* Drop through and scroll. */
ef3c2c73
RS
10517 else
10518 goto done;
aa6d10fa 10519 }
a2889657 10520 else
5f5c8ee5 10521 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
10522 }
10523
5f5c8ee5
GM
10524 try_to_scroll:
10525
ac90c44f
GM
10526 w->last_modified = make_number (0);
10527 w->last_overlay_modified = make_number (0);
5f5c8ee5 10528
e481f960
RS
10529 /* Redisplay the mode line. Select the buffer properly for that. */
10530 if (!update_mode_line)
10531 {
e481f960
RS
10532 update_mode_line = 1;
10533 w->update_mode_line = Qt;
10534 }
a2889657 10535
5f5c8ee5
GM
10536 /* Try to scroll by specified few lines. */
10537 if ((scroll_conservatively
10538 || scroll_step
10539 || temp_scroll_step
10540 || NUMBERP (current_buffer->scroll_up_aggressively)
10541 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 10542 && !current_buffer->clip_changed
2311178e 10543 && CHARPOS (startp) >= BEGV
5f5c8ee5 10544 && CHARPOS (startp) <= ZV)
0789adb2 10545 {
5f5c8ee5
GM
10546 /* The function returns -1 if new fonts were loaded, 1 if
10547 successful, 0 if not successful. */
10548 int rc = try_scrolling (window, just_this_one_p,
10549 scroll_conservatively,
10550 scroll_step,
10551 temp_scroll_step);
cb617e7c
GM
10552 switch (rc)
10553 {
10554 case SCROLLING_SUCCESS:
10555 goto done;
2311178e 10556
cb617e7c
GM
10557 case SCROLLING_NEED_LARGER_MATRICES:
10558 goto need_larger_matrices;
2311178e 10559
cb617e7c
GM
10560 case SCROLLING_FAILED:
10561 break;
2311178e 10562
cb617e7c
GM
10563 default:
10564 abort ();
10565 }
5f5c8ee5 10566 }
f9c8af06 10567
5f5c8ee5 10568 /* Finally, just choose place to start which centers point */
5936754e 10569
5f5c8ee5 10570 recenter:
ddf6b9a3
RS
10571 centering_position = window_box_height (w) / 2;
10572
10573 point_at_top:
10574 /* Jump here with centering_position already set to 0. */
44173109 10575
5f5c8ee5
GM
10576#if GLYPH_DEBUG
10577 debug_method_add (w, "recenter");
10578#endif
0789adb2 10579
5f5c8ee5 10580 /* w->vscroll = 0; */
0789adb2 10581
5f5c8ee5 10582 /* Forget any previously recorded base line for line number display. */
c62c1bb5 10583 if (!buffer_unchanged_p)
5f5c8ee5
GM
10584 w->base_line_number = Qnil;
10585
10586 /* Move backward half the height of the window. */
10587 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
10588 it.current_y = it.last_visible_y;
ddf6b9a3 10589 move_it_vertically_backward (&it, centering_position);
5f5c8ee5
GM
10590 xassert (IT_CHARPOS (it) >= BEGV);
10591
10592 /* The function move_it_vertically_backward may move over more
10593 than the specified y-distance. If it->w is small, e.g. a
10594 mini-buffer window, we may end up in front of the window's
10595 display area. Start displaying at the start of the line
10596 containing PT in this case. */
10597 if (it.current_y <= 0)
10598 {
10599 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
10600 move_it_vertically (&it, 0);
10601 xassert (IT_CHARPOS (it) <= PT);
10602 it.current_y = 0;
0789adb2
RS
10603 }
10604
5f5c8ee5 10605 it.current_x = it.hpos = 0;
2311178e 10606
5f5c8ee5
GM
10607 /* Set startp here explicitly in case that helps avoid an infinite loop
10608 in case the window-scroll-functions functions get errors. */
10609 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
10610
10611 /* Run scroll hooks. */
10612 startp = run_window_scroll_functions (window, it.current.pos);
10613
10614 /* Redisplay the window. */
10615 if (!current_matrix_up_to_date_p
10616 || windows_or_buffers_changed
5fb96e96 10617 || cursor_type_changed
5f5c8ee5
GM
10618 /* Don't use try_window_reusing_current_matrix in this case
10619 because it can have changed the buffer. */
10620 || !NILP (Vwindow_scroll_functions)
10621 || !just_this_one_p
10622 || MINI_WINDOW_P (w)
10623 || !try_window_reusing_current_matrix (w))
10624 try_window (window, startp);
10625
10626 /* If new fonts have been loaded (due to fontsets), give up. We
10627 have to start a new redisplay since we need to re-adjust glyph
10628 matrices. */
10629 if (fonts_changed_p)
cb617e7c 10630 goto need_larger_matrices;
5f5c8ee5
GM
10631
10632 /* If cursor did not appear assume that the middle of the window is
10633 in the first line of the window. Do it again with the next line.
10634 (Imagine a window of height 100, displaying two lines of height
10635 60. Moving back 50 from it->last_visible_y will end in the first
10636 line.) */
10637 if (w->cursor.vpos < 0)
a2889657 10638 {
5f5c8ee5
GM
10639 if (!NILP (w->window_end_valid)
10640 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 10641 {
5f5c8ee5
GM
10642 clear_glyph_matrix (w->desired_matrix);
10643 move_it_by_lines (&it, 1, 0);
10644 try_window (window, it.current.pos);
a2889657 10645 }
5f5c8ee5 10646 else if (PT < IT_CHARPOS (it))
a2889657 10647 {
5f5c8ee5
GM
10648 clear_glyph_matrix (w->desired_matrix);
10649 move_it_by_lines (&it, -1, 0);
10650 try_window (window, it.current.pos);
10651 }
10652 else
10653 {
10654 /* Not much we can do about it. */
a2889657 10655 }
a2889657 10656 }
010494d0 10657
5f5c8ee5
GM
10658 /* Consider the following case: Window starts at BEGV, there is
10659 invisible, intangible text at BEGV, so that display starts at
10660 some point START > BEGV. It can happen that we are called with
10661 PT somewhere between BEGV and START. Try to handle that case. */
10662 if (w->cursor.vpos < 0)
835766b6 10663 {
5f5c8ee5
GM
10664 struct glyph_row *row = w->current_matrix->rows;
10665 if (row->mode_line_p)
10666 ++row;
10667 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 10668 }
2311178e 10669
cb617e7c 10670 if (!make_cursor_line_fully_visible (w))
ddf6b9a3
RS
10671 {
10672 /* If centering point failed to make the whole line visible,
10673 put point at the top instead. That has to make the whole line
10674 visible, if it can be done. */
10675 centering_position = 0;
10676 goto point_at_top;
10677 }
b5174a51 10678
74d481ac
GM
10679 done:
10680
5f5c8ee5
GM
10681 SET_TEXT_POS_FROM_MARKER (startp, w->start);
10682 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
10683 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
10684 ? Qt : Qnil);
a2889657 10685
5f5c8ee5 10686 /* Display the mode line, if we must. */
e481f960 10687 if ((update_mode_line
aa6d10fa 10688 /* If window not full width, must redo its mode line
2311178e 10689 if (a) the window to its side is being redone and
5f5c8ee5
GM
10690 (b) we do a frame-based redisplay. This is a consequence
10691 of how inverted lines are drawn in frame-based redisplay. */
2311178e 10692 || (!just_this_one_p
5f5c8ee5
GM
10693 && !FRAME_WINDOW_P (f)
10694 && !WINDOW_FULL_WIDTH_P (w))
10695 /* Line number to display. */
155ef550 10696 || INTEGERP (w->base_line_pos)
5f5c8ee5 10697 /* Column number is displayed and different from the one displayed. */
155ef550 10698 || (!NILP (w->column_number_displayed)
2311178e
TTN
10699 && (XFASTINT (w->column_number_displayed)
10700 != (int) current_column ()))) /* iftc */
5f5c8ee5
GM
10701 /* This means that the window has a mode line. */
10702 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 10703 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 10704 {
5f5c8ee5
GM
10705 display_mode_lines (w);
10706
10707 /* If mode line height has changed, arrange for a thorough
10708 immediate redisplay using the correct mode line height. */
10709 if (WINDOW_WANTS_MODELINE_P (w)
10710 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 10711 {
5f5c8ee5
GM
10712 fonts_changed_p = 1;
10713 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
10714 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 10715 }
2311178e 10716
5f5c8ee5
GM
10717 /* If top line height has changed, arrange for a thorough
10718 immediate redisplay using the correct mode line height. */
045dee35
GM
10719 if (WINDOW_WANTS_HEADER_LINE_P (w)
10720 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
10721 {
10722 fonts_changed_p = 1;
045dee35
GM
10723 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
10724 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
10725 }
10726
10727 if (fonts_changed_p)
cb617e7c 10728 goto need_larger_matrices;
5ba50c51 10729 }
5f5c8ee5
GM
10730
10731 if (!line_number_displayed
10732 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
10733 {
10734 w->base_line_pos = Qnil;
10735 w->base_line_number = Qnil;
10736 }
a2889657 10737
5f5c8ee5 10738 finish_menu_bars:
2311178e 10739
7ce2c095 10740 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 10741 if (update_mode_line
5f5c8ee5
GM
10742 && EQ (FRAME_SELECTED_WINDOW (f), window))
10743 {
10744 int redisplay_menu_p = 0;
10745
10746 if (FRAME_WINDOW_P (f))
10747 {
e0f712ba 10748#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
5f5c8ee5 10749 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 10750#else
5f5c8ee5 10751 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 10752#endif
5f5c8ee5
GM
10753 }
10754 else
10755 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
10756
10757 if (redisplay_menu_p)
10758 display_menu_bar (w);
10759
10760#ifdef HAVE_WINDOW_SYSTEM
e037b9ec
GM
10761 if (WINDOWP (f->tool_bar_window)
10762 && (FRAME_TOOL_BAR_LINES (f) > 0
10763 || auto_resize_tool_bars_p))
10764 redisplay_tool_bar (f);
5f5c8ee5
GM
10765#endif
10766 }
7ce2c095 10767
b60c9653
RS
10768 /* We go to this label, with fonts_changed_p nonzero,
10769 if it is necessary to try again using larger glyph matrices.
10770 We have to redeem the scroll bar even in this case,
10771 because the loop in redisplay_internal expects that. */
cb617e7c
GM
10772 need_larger_matrices:
10773 ;
88f22aff 10774 finish_scroll_bars:
5f5c8ee5 10775
88f22aff 10776 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 10777 {
b1d1124b 10778 int start, end, whole;
30c566e4 10779
b1d1124b 10780 /* Calculate the start and end positions for the current window.
3505ea70
JB
10781 At some point, it would be nice to choose between scrollbars
10782 which reflect the whole buffer size, with special markers
10783 indicating narrowing, and scrollbars which reflect only the
10784 visible region.
10785
5f5c8ee5 10786 Note that mini-buffers sometimes aren't displaying any text. */
c6e89d6c 10787 if (!MINI_WINDOW_P (w)
5f5c8ee5 10788 || (w == XWINDOW (minibuf_window)
c6e89d6c 10789 && NILP (echo_area_buffer[0])))
b1d1124b 10790 {
8a9311d7 10791 whole = ZV - BEGV;
4d641a15 10792 start = marker_position (w->start) - BEGV;
b1d1124b
JB
10793 /* I don't think this is guaranteed to be right. For the
10794 moment, we'll pretend it is. */
5f5c8ee5 10795 end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
3505ea70 10796
2311178e 10797 if (end < start)
5f5c8ee5 10798 end = start;
2311178e 10799 if (whole < (end - start))
5f5c8ee5 10800 whole = end - start;
b1d1124b
JB
10801 }
10802 else
10803 start = end = whole = 0;
30c566e4 10804
88f22aff 10805 /* Indicate what this scroll bar ought to be displaying now. */
504454e8 10806 set_vertical_scroll_bar_hook (w, end - start, whole, start);
30c566e4 10807
5f5c8ee5
GM
10808 /* Note that we actually used the scroll bar attached to this
10809 window, so it shouldn't be deleted at the end of redisplay. */
504454e8 10810 redeem_scroll_bar_hook (w);
30c566e4 10811 }
b1d1124b 10812
5f5c8ee5
GM
10813 /* Restore current_buffer and value of point in it. */
10814 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
6a93695f 10815 set_buffer_internal_1 (old);
5f5c8ee5 10816 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
10817
10818 unbind_to (count, Qnil);
a2889657 10819}
a2889657 10820
5f5c8ee5
GM
10821
10822/* Build the complete desired matrix of WINDOW with a window start
10823 buffer position POS. Value is non-zero if successful. It is zero
10824 if fonts were loaded during redisplay which makes re-adjusting
10825 glyph matrices necessary. */
10826
10827int
a2889657
JB
10828try_window (window, pos)
10829 Lisp_Object window;
5f5c8ee5
GM
10830 struct text_pos pos;
10831{
10832 struct window *w = XWINDOW (window);
10833 struct it it;
10834 struct glyph_row *last_text_row = NULL;
9cbab4ff 10835
5f5c8ee5
GM
10836 /* Make POS the new window start. */
10837 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 10838
5f5c8ee5
GM
10839 /* Mark cursor position as unknown. No overlay arrow seen. */
10840 w->cursor.vpos = -1;
a2889657 10841 overlay_arrow_seen = 0;
642eefc6 10842
5f5c8ee5
GM
10843 /* Initialize iterator and info to start at POS. */
10844 start_display (&it, w, pos);
a2889657 10845
5f5c8ee5
GM
10846 /* Display all lines of W. */
10847 while (it.current_y < it.last_visible_y)
10848 {
10849 if (display_line (&it))
10850 last_text_row = it.glyph_row - 1;
10851 if (fonts_changed_p)
10852 return 0;
10853 }
a2889657 10854
5f5c8ee5
GM
10855 /* If bottom moved off end of frame, change mode line percentage. */
10856 if (XFASTINT (w->window_end_pos) <= 0
10857 && Z != IT_CHARPOS (it))
a2889657
JB
10858 w->update_mode_line = Qt;
10859
5f5c8ee5
GM
10860 /* Set window_end_pos to the offset of the last character displayed
10861 on the window from the end of current_buffer. Set
10862 window_end_vpos to its row number. */
10863 if (last_text_row)
10864 {
10865 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
10866 w->window_end_bytepos
10867 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
10868 w->window_end_pos
10869 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10870 w->window_end_vpos
10871 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
10872 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
10873 ->displays_text_p);
10874 }
10875 else
10876 {
10877 w->window_end_bytepos = 0;
ac90c44f 10878 w->window_end_pos = w->window_end_vpos = make_number (0);
5f5c8ee5 10879 }
2311178e 10880
a2889657
JB
10881 /* But that is not valid info until redisplay finishes. */
10882 w->window_end_valid = Qnil;
5f5c8ee5 10883 return 1;
a2889657 10884}
5f5c8ee5
GM
10885
10886
a2889657 10887\f
5f5c8ee5
GM
10888/************************************************************************
10889 Window redisplay reusing current matrix when buffer has not changed
10890 ************************************************************************/
10891
10892/* Try redisplay of window W showing an unchanged buffer with a
10893 different window start than the last time it was displayed by
10894 reusing its current matrix. Value is non-zero if successful.
10895 W->start is the new window start. */
a2889657
JB
10896
10897static int
5f5c8ee5
GM
10898try_window_reusing_current_matrix (w)
10899 struct window *w;
a2889657 10900{
5f5c8ee5
GM
10901 struct frame *f = XFRAME (w->frame);
10902 struct glyph_row *row, *bottom_row;
10903 struct it it;
10904 struct run run;
10905 struct text_pos start, new_start;
10906 int nrows_scrolled, i;
10907 struct glyph_row *last_text_row;
10908 struct glyph_row *last_reused_text_row;
10909 struct glyph_row *start_row;
10910 int start_vpos, min_y, max_y;
75c5350a 10911
69d1f7c9 10912#if GLYPH_DEBUG
76cb5e06
GM
10913 if (inhibit_try_window_reusing)
10914 return 0;
10915#endif
10916
d18354b6
GM
10917 if (/* This function doesn't handle terminal frames. */
10918 !FRAME_WINDOW_P (f)
10919 /* Don't try to reuse the display if windows have been split
10920 or such. */
5fb96e96
RS
10921 || windows_or_buffers_changed
10922 || cursor_type_changed)
5f5c8ee5 10923 return 0;
a2889657 10924
5f5c8ee5
GM
10925 /* Can't do this if region may have changed. */
10926 if ((!NILP (Vtransient_mark_mode)
10927 && !NILP (current_buffer->mark_active))
8f897821
GM
10928 || !NILP (w->region_showing)
10929 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 10930 return 0;
a2889657 10931
5f5c8ee5 10932 /* If top-line visibility has changed, give up. */
045dee35
GM
10933 if (WINDOW_WANTS_HEADER_LINE_P (w)
10934 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
10935 return 0;
10936
10937 /* Give up if old or new display is scrolled vertically. We could
10938 make this function handle this, but right now it doesn't. */
10939 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10940 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
10941 return 0;
10942
10943 /* The variable new_start now holds the new window start. The old
10944 start `start' can be determined from the current matrix. */
10945 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
10946 start = start_row->start.pos;
10947 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 10948
5f5c8ee5
GM
10949 /* Clear the desired matrix for the display below. */
10950 clear_glyph_matrix (w->desired_matrix);
2311178e 10951
5f5c8ee5
GM
10952 if (CHARPOS (new_start) <= CHARPOS (start))
10953 {
10954 int first_row_y;
2311178e 10955
607ec83c
GM
10956 /* Don't use this method if the display starts with an ellipsis
10957 displayed for invisible text. It's not easy to handle that case
10958 below, and it's certainly not worth the effort since this is
10959 not a frequent case. */
10960 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
10961 return 0;
10962
5f5c8ee5 10963 IF_DEBUG (debug_method_add (w, "twu1"));
2311178e 10964
5f5c8ee5
GM
10965 /* Display up to a row that can be reused. The variable
10966 last_text_row is set to the last row displayed that displays
b48f74cb
GM
10967 text. Note that it.vpos == 0 if or if not there is a
10968 header-line; it's not the same as the MATRIX_ROW_VPOS! */
5f5c8ee5
GM
10969 start_display (&it, w, new_start);
10970 first_row_y = it.current_y;
10971 w->cursor.vpos = -1;
10972 last_text_row = last_reused_text_row = NULL;
2311178e 10973
5f5c8ee5
GM
10974 while (it.current_y < it.last_visible_y
10975 && IT_CHARPOS (it) < CHARPOS (start)
10976 && !fonts_changed_p)
10977 if (display_line (&it))
10978 last_text_row = it.glyph_row - 1;
10979
10980 /* A value of current_y < last_visible_y means that we stopped
10981 at the previous window start, which in turn means that we
10982 have at least one reusable row. */
10983 if (it.current_y < it.last_visible_y)
a2889657 10984 {
b48f74cb 10985 /* IT.vpos always starts from 0; it counts text lines. */
5f5c8ee5 10986 nrows_scrolled = it.vpos;
2311178e 10987
5f5c8ee5
GM
10988 /* Find PT if not already found in the lines displayed. */
10989 if (w->cursor.vpos < 0)
a2889657 10990 {
5f5c8ee5 10991 int dy = it.current_y - first_row_y;
2311178e 10992
5f5c8ee5 10993 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
0df56f4d
GM
10994 row = row_containing_pos (w, PT, row, NULL, dy);
10995 if (row)
10996 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
10997 dy, nrows_scrolled);
10998 else
5f5c8ee5
GM
10999 {
11000 clear_glyph_matrix (w->desired_matrix);
11001 return 0;
11002 }
a2889657 11003 }
5f5c8ee5
GM
11004
11005 /* Scroll the display. Do it before the current matrix is
11006 changed. The problem here is that update has not yet
11007 run, i.e. part of the current matrix is not up to date.
11008 scroll_run_hook will clear the cursor, and use the
11009 current matrix to get the height of the row the cursor is
11010 in. */
11011 run.current_y = first_row_y;
11012 run.desired_y = it.current_y;
11013 run.height = it.last_visible_y - it.current_y;
b48f74cb
GM
11014
11015 if (run.height > 0 && run.current_y != run.desired_y)
a2889657 11016 {
5f5c8ee5
GM
11017 update_begin (f);
11018 rif->update_window_begin_hook (w);
64d1e7d3 11019 rif->clear_mouse_face (w);
5f5c8ee5 11020 rif->scroll_run_hook (w, &run);
64d1e7d3 11021 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5 11022 update_end (f);
a2889657 11023 }
5f5c8ee5
GM
11024
11025 /* Shift current matrix down by nrows_scrolled lines. */
11026 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
11027 rotate_matrix (w->current_matrix,
11028 start_vpos,
11029 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
11030 nrows_scrolled);
2311178e 11031
9c8b8382 11032 /* Disable lines that must be updated. */
5f5c8ee5 11033 for (i = 0; i < it.vpos; ++i)
b48f74cb 11034 (start_row + i)->enabled_p = 0;
9c8b8382 11035
5f5c8ee5 11036 /* Re-compute Y positions. */
045dee35 11037 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5 11038 max_y = it.last_visible_y;
b48f74cb
GM
11039 for (row = start_row + nrows_scrolled;
11040 row < bottom_row;
11041 ++row)
d2f84654 11042 {
5f5c8ee5 11043 row->y = it.current_y;
75c5350a 11044 row->visible_height = row->height;
5f5c8ee5
GM
11045
11046 if (row->y < min_y)
75c5350a
GM
11047 row->visible_height -= min_y - row->y;
11048 if (row->y + row->height > max_y)
11049 row->visible_height -= row->y + row->height - max_y;
2311178e 11050
5f5c8ee5 11051 it.current_y += row->height;
5f5c8ee5
GM
11052
11053 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
11054 last_reused_text_row = row;
11055 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
11056 break;
d2f84654 11057 }
2311178e 11058
9c8b8382
GM
11059 /* Disable lines in the current matrix which are now
11060 below the window. */
bafb434c 11061 for (++row; row < bottom_row; ++row)
9c8b8382 11062 row->enabled_p = 0;
a2889657 11063 }
5f5c8ee5
GM
11064
11065 /* Update window_end_pos etc.; last_reused_text_row is the last
11066 reused row from the current matrix containing text, if any.
11067 The value of last_text_row is the last displayed line
11068 containing text. */
11069 if (last_reused_text_row)
a2889657 11070 {
5f5c8ee5
GM
11071 w->window_end_bytepos
11072 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
ac90c44f
GM
11073 w->window_end_pos
11074 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
11075 w->window_end_vpos
11076 = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
11077 w->current_matrix));
a2889657 11078 }
5f5c8ee5
GM
11079 else if (last_text_row)
11080 {
11081 w->window_end_bytepos
11082 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
11083 w->window_end_pos
11084 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
11085 w->window_end_vpos
11086 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
11087 }
11088 else
11089 {
11090 /* This window must be completely empty. */
11091 w->window_end_bytepos = 0;
ac90c44f 11092 w->window_end_pos = w->window_end_vpos = make_number (0);
5f5c8ee5
GM
11093 }
11094 w->window_end_valid = Qnil;
a2889657 11095
5f5c8ee5
GM
11096 /* Update hint: don't try scrolling again in update_window. */
11097 w->desired_matrix->no_scrolling_p = 1;
2311178e 11098
5f5c8ee5
GM
11099#if GLYPH_DEBUG
11100 debug_method_add (w, "try_window_reusing_current_matrix 1");
11101#endif
11102 return 1;
a2889657 11103 }
5f5c8ee5
GM
11104 else if (CHARPOS (new_start) > CHARPOS (start))
11105 {
11106 struct glyph_row *pt_row, *row;
11107 struct glyph_row *first_reusable_row;
11108 struct glyph_row *first_row_to_display;
11109 int dy;
11110 int yb = window_text_bottom_y (w);
11111
5f5c8ee5
GM
11112 /* Find the row starting at new_start, if there is one. Don't
11113 reuse a partially visible line at the end. */
b48f74cb 11114 first_reusable_row = start_row;
5f5c8ee5
GM
11115 while (first_reusable_row->enabled_p
11116 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
11117 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
11118 < CHARPOS (new_start)))
11119 ++first_reusable_row;
11120
11121 /* Give up if there is no row to reuse. */
11122 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
11123 || !first_reusable_row->enabled_p
11124 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
11125 != CHARPOS (new_start)))
5f5c8ee5
GM
11126 return 0;
11127
5f5c8ee5
GM
11128 /* We can reuse fully visible rows beginning with
11129 first_reusable_row to the end of the window. Set
11130 first_row_to_display to the first row that cannot be reused.
11131 Set pt_row to the row containing point, if there is any. */
5f5c8ee5 11132 pt_row = NULL;
ac90c44f
GM
11133 for (first_row_to_display = first_reusable_row;
11134 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
11135 ++first_row_to_display)
5f5c8ee5 11136 {
4bde0ebb
GM
11137 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
11138 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
5f5c8ee5 11139 pt_row = first_row_to_display;
5f5c8ee5 11140 }
a2889657 11141
5f5c8ee5
GM
11142 /* Start displaying at the start of first_row_to_display. */
11143 xassert (first_row_to_display->y < yb);
11144 init_to_row_start (&it, w, first_row_to_display);
607ec83c 11145
b48f74cb
GM
11146 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
11147 - start_vpos);
5f5c8ee5
GM
11148 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
11149 - nrows_scrolled);
b48f74cb
GM
11150 it.current_y = (first_row_to_display->y - first_reusable_row->y
11151 + WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
11152
11153 /* Display lines beginning with first_row_to_display in the
11154 desired matrix. Set last_text_row to the last row displayed
11155 that displays text. */
11156 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
11157 if (pt_row == NULL)
11158 w->cursor.vpos = -1;
11159 last_text_row = NULL;
11160 while (it.current_y < it.last_visible_y && !fonts_changed_p)
11161 if (display_line (&it))
11162 last_text_row = it.glyph_row - 1;
11163
11164 /* Give up If point isn't in a row displayed or reused. */
11165 if (w->cursor.vpos < 0)
11166 {
11167 clear_glyph_matrix (w->desired_matrix);
11168 return 0;
11169 }
12adba34 11170
5f5c8ee5
GM
11171 /* If point is in a reused row, adjust y and vpos of the cursor
11172 position. */
11173 if (pt_row)
11174 {
11175 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
11176 w->current_matrix);
11177 w->cursor.y -= first_reusable_row->y;
a2889657
JB
11178 }
11179
5f5c8ee5
GM
11180 /* Scroll the display. */
11181 run.current_y = first_reusable_row->y;
045dee35 11182 run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5 11183 run.height = it.last_visible_y - run.current_y;
4da61803 11184 dy = run.current_y - run.desired_y;
2311178e 11185
5f5c8ee5
GM
11186 if (run.height)
11187 {
11188 struct frame *f = XFRAME (WINDOW_FRAME (w));
11189 update_begin (f);
11190 rif->update_window_begin_hook (w);
64d1e7d3 11191 rif->clear_mouse_face (w);
5f5c8ee5 11192 rif->scroll_run_hook (w, &run);
64d1e7d3 11193 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
11194 update_end (f);
11195 }
a2889657 11196
5f5c8ee5
GM
11197 /* Adjust Y positions of reused rows. */
11198 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
045dee35 11199 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5 11200 max_y = it.last_visible_y;
b48f74cb 11201 for (row = first_reusable_row; row < first_row_to_display; ++row)
5f5c8ee5
GM
11202 {
11203 row->y -= dy;
75c5350a 11204 row->visible_height = row->height;
5f5c8ee5 11205 if (row->y < min_y)
75c5350a
GM
11206 row->visible_height -= min_y - row->y;
11207 if (row->y + row->height > max_y)
11208 row->visible_height -= row->y + row->height - max_y;
5f5c8ee5 11209 }
a2889657 11210
5f5c8ee5
GM
11211 /* Scroll the current matrix. */
11212 xassert (nrows_scrolled > 0);
11213 rotate_matrix (w->current_matrix,
11214 start_vpos,
11215 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
11216 -nrows_scrolled);
11217
ac90c44f
GM
11218 /* Disable rows not reused. */
11219 for (row -= nrows_scrolled; row < bottom_row; ++row)
11220 row->enabled_p = 0;
11221
5f5c8ee5
GM
11222 /* Adjust window end. A null value of last_text_row means that
11223 the window end is in reused rows which in turn means that
11224 only its vpos can have changed. */
11225 if (last_text_row)
11226 {
11227 w->window_end_bytepos
11228 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
11229 w->window_end_pos
11230 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
11231 w->window_end_vpos
11232 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
11233 }
11234 else
a2889657 11235 {
ac90c44f
GM
11236 w->window_end_vpos
11237 = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 11238 }
2311178e 11239
5f5c8ee5
GM
11240 w->window_end_valid = Qnil;
11241 w->desired_matrix->no_scrolling_p = 1;
11242
11243#if GLYPH_DEBUG
11244 debug_method_add (w, "try_window_reusing_current_matrix 2");
11245#endif
11246 return 1;
a2889657 11247 }
2311178e 11248
5f5c8ee5
GM
11249 return 0;
11250}
a2889657 11251
a2889657 11252
5f5c8ee5
GM
11253\f
11254/************************************************************************
11255 Window redisplay reusing current matrix when buffer has changed
11256 ************************************************************************/
11257
1ec185cb
GM
11258static struct glyph_row *find_last_unchanged_at_beg_row P_ ((struct window *));
11259static struct glyph_row *find_first_unchanged_at_end_row P_ ((struct window *,
5f5c8ee5
GM
11260 int *, int *));
11261static struct glyph_row *
11262find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
11263 struct glyph_row *));
11264
11265
11266/* Return the last row in MATRIX displaying text. If row START is
11267 non-null, start searching with that row. IT gives the dimensions
11268 of the display. Value is null if matrix is empty; otherwise it is
11269 a pointer to the row found. */
11270
11271static struct glyph_row *
11272find_last_row_displaying_text (matrix, it, start)
11273 struct glyph_matrix *matrix;
11274 struct it *it;
11275 struct glyph_row *start;
11276{
11277 struct glyph_row *row, *row_found;
11278
11279 /* Set row_found to the last row in IT->w's current matrix
11280 displaying text. The loop looks funny but think of partially
11281 visible lines. */
11282 row_found = NULL;
11283 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
11284 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
11285 {
11286 xassert (row->enabled_p);
11287 row_found = row;
11288 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
11289 break;
11290 ++row;
a2889657 11291 }
2311178e 11292
5f5c8ee5
GM
11293 return row_found;
11294}
11295
a2889657 11296
5f5c8ee5 11297/* Return the last row in the current matrix of W that is not affected
d43fbe9d
GM
11298 by changes at the start of current_buffer that occurred since W's
11299 current matrix was built. Value is null if no such row exists.
a2889657 11300
d43fbe9d
GM
11301 BEG_UNCHANGED us the number of characters unchanged at the start of
11302 current_buffer. BEG + BEG_UNCHANGED is the buffer position of the
11303 first changed character in current_buffer. Characters at positions <
11304 BEG + BEG_UNCHANGED are at the same buffer positions as they were
11305 when the current matrix was built. */
5f5c8ee5
GM
11306
11307static struct glyph_row *
1ec185cb 11308find_last_unchanged_at_beg_row (w)
5f5c8ee5
GM
11309 struct window *w;
11310{
9142dd5b 11311 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
11312 struct glyph_row *row;
11313 struct glyph_row *row_found = NULL;
11314 int yb = window_text_bottom_y (w);
11315
11316 /* Find the last row displaying unchanged text. */
11317 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
11318 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
11319 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 11320 {
5f5c8ee5
GM
11321 if (/* If row ends before first_changed_pos, it is unchanged,
11322 except in some case. */
11323 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
11324 /* When row ends in ZV and we write at ZV it is not
11325 unchanged. */
11326 && !row->ends_at_zv_p
11327 /* When first_changed_pos is the end of a continued line,
11328 row is not unchanged because it may be no longer
11329 continued. */
11330 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
11331 && row->continued_p))
11332 row_found = row;
11333
11334 /* Stop if last visible row. */
11335 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
11336 break;
2311178e 11337
5f5c8ee5 11338 ++row;
a2889657
JB
11339 }
11340
5f5c8ee5 11341 return row_found;
a2889657 11342}
5f5c8ee5
GM
11343
11344
11345/* Find the first glyph row in the current matrix of W that is not
2311178e 11346 affected by changes at the end of current_buffer since the
d43fbe9d
GM
11347 time W's current matrix was built.
11348
11349 Return in *DELTA the number of chars by which buffer positions in
11350 unchanged text at the end of current_buffer must be adjusted.
2311178e 11351
d43fbe9d
GM
11352 Return in *DELTA_BYTES the corresponding number of bytes.
11353
11354 Value is null if no such row exists, i.e. all rows are affected by
11355 changes. */
2311178e 11356
5f5c8ee5 11357static struct glyph_row *
1ec185cb 11358find_first_unchanged_at_end_row (w, delta, delta_bytes)
5f5c8ee5
GM
11359 struct window *w;
11360 int *delta, *delta_bytes;
a2889657 11361{
5f5c8ee5
GM
11362 struct glyph_row *row;
11363 struct glyph_row *row_found = NULL;
c581d710 11364
5f5c8ee5 11365 *delta = *delta_bytes = 0;
b2a76982 11366
1ec185cb
GM
11367 /* Display must not have been paused, otherwise the current matrix
11368 is not up to date. */
11369 if (NILP (w->window_end_valid))
11370 abort ();
2311178e 11371
1ec185cb 11372 /* A value of window_end_pos >= END_UNCHANGED means that the window
5f5c8ee5
GM
11373 end is in the range of changed text. If so, there is no
11374 unchanged row at the end of W's current matrix. */
9142dd5b 11375 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
11376 return NULL;
11377
11378 /* Set row to the last row in W's current matrix displaying text. */
11379 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
2311178e
TTN
11380
11381 /* If matrix is entirely empty, no unchanged row exists. */
5f5c8ee5
GM
11382 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
11383 {
11384 /* The value of row is the last glyph row in the matrix having a
11385 meaningful buffer position in it. The end position of row
11386 corresponds to window_end_pos. This allows us to translate
11387 buffer positions in the current matrix to current buffer
11388 positions for characters not in changed text. */
11389 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
11390 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
11391 int last_unchanged_pos, last_unchanged_pos_old;
11392 struct glyph_row *first_text_row
11393 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
11394
11395 *delta = Z - Z_old;
11396 *delta_bytes = Z_BYTE - Z_BYTE_old;
11397
11398 /* Set last_unchanged_pos to the buffer position of the last
11399 character in the buffer that has not been changed. Z is the
d43fbe9d
GM
11400 index + 1 of the last character in current_buffer, i.e. by
11401 subtracting END_UNCHANGED we get the index of the last
5f5c8ee5
GM
11402 unchanged character, and we have to add BEG to get its buffer
11403 position. */
9142dd5b 11404 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5 11405 last_unchanged_pos_old = last_unchanged_pos - *delta;
2311178e 11406
5f5c8ee5
GM
11407 /* Search backward from ROW for a row displaying a line that
11408 starts at a minimum position >= last_unchanged_pos_old. */
1ec185cb 11409 for (; row > first_text_row; --row)
5f5c8ee5 11410 {
1ec185cb
GM
11411 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
11412 abort ();
2311178e 11413
5f5c8ee5
GM
11414 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
11415 row_found = row;
5f5c8ee5
GM
11416 }
11417 }
11418
1ec185cb
GM
11419 if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
11420 abort ();
2311178e 11421
5f5c8ee5 11422 return row_found;
c581d710
RS
11423}
11424
c581d710 11425
5f5c8ee5
GM
11426/* Make sure that glyph rows in the current matrix of window W
11427 reference the same glyph memory as corresponding rows in the
11428 frame's frame matrix. This function is called after scrolling W's
11429 current matrix on a terminal frame in try_window_id and
11430 try_window_reusing_current_matrix. */
11431
11432static void
11433sync_frame_with_window_matrix_rows (w)
11434 struct window *w;
c581d710 11435{
5f5c8ee5
GM
11436 struct frame *f = XFRAME (w->frame);
11437 struct glyph_row *window_row, *window_row_end, *frame_row;
11438
11439 /* Preconditions: W must be a leaf window and full-width. Its frame
11440 must have a frame matrix. */
11441 xassert (NILP (w->hchild) && NILP (w->vchild));
11442 xassert (WINDOW_FULL_WIDTH_P (w));
11443 xassert (!FRAME_WINDOW_P (f));
11444
11445 /* If W is a full-width window, glyph pointers in W's current matrix
11446 have, by definition, to be the same as glyph pointers in the
7d4cc828
GM
11447 corresponding frame matrix. Note that frame matrices have no
11448 marginal areas (see build_frame_matrix). */
5f5c8ee5
GM
11449 window_row = w->current_matrix->rows;
11450 window_row_end = window_row + w->current_matrix->nrows;
11451 frame_row = f->current_matrix->rows + XFASTINT (w->top);
11452 while (window_row < window_row_end)
659a218f 11453 {
7d4cc828
GM
11454 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
11455 struct glyph *end = window_row->glyphs[LAST_AREA];
11456
11457 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
11458 frame_row->glyphs[TEXT_AREA] = start;
11459 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
11460 frame_row->glyphs[LAST_AREA] = end;
f002db93
GM
11461
11462 /* Disable frame rows whose corresponding window rows have
11463 been disabled in try_window_id. */
11464 if (!window_row->enabled_p)
11465 frame_row->enabled_p = 0;
2311178e 11466
5f5c8ee5 11467 ++window_row, ++frame_row;
659a218f 11468 }
a2889657 11469}
5f5c8ee5
GM
11470
11471
e037b9ec
GM
11472/* Find the glyph row in window W containing CHARPOS. Consider all
11473 rows between START and END (not inclusive). END null means search
11474 all rows to the end of the display area of W. Value is the row
11475 containing CHARPOS or null. */
11476
0bef35bc 11477struct glyph_row *
0df56f4d 11478row_containing_pos (w, charpos, start, end, dy)
e037b9ec
GM
11479 struct window *w;
11480 int charpos;
11481 struct glyph_row *start, *end;
0df56f4d 11482 int dy;
e037b9ec
GM
11483{
11484 struct glyph_row *row = start;
11485 int last_y;
11486
11487 /* If we happen to start on a header-line, skip that. */
11488 if (row->mode_line_p)
11489 ++row;
2311178e 11490
e037b9ec
GM
11491 if ((end && row >= end) || !row->enabled_p)
11492 return NULL;
2311178e 11493
0df56f4d 11494 last_y = window_text_bottom_y (w) - dy;
2311178e 11495
e037b9ec 11496 while ((end == NULL || row < end)
0df56f4d 11497 && MATRIX_ROW_BOTTOM_Y (row) < last_y
e037b9ec 11498 && (MATRIX_ROW_END_CHARPOS (row) < charpos
e037b9ec 11499 || (MATRIX_ROW_END_CHARPOS (row) == charpos
0df56f4d
GM
11500 /* The end position of a row equals the start
11501 position of the next row. If CHARPOS is there, we
11502 would rather display it in the next line, except
11503 when this line ends in ZV. */
11504 && !row->ends_at_zv_p
11505 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))
e037b9ec 11506 ++row;
2311178e 11507
e037b9ec
GM
11508 /* Give up if CHARPOS not found. */
11509 if ((end && row >= end)
11510 || charpos < MATRIX_ROW_START_CHARPOS (row)
11511 || charpos > MATRIX_ROW_END_CHARPOS (row))
11512 row = NULL;
11513
11514 return row;
11515}
11516
11517
5f5c8ee5
GM
11518/* Try to redisplay window W by reusing its existing display. W's
11519 current matrix must be up to date when this function is called,
11520 i.e. window_end_valid must not be nil.
11521
11522 Value is
11523
11524 1 if display has been updated
11525 0 if otherwise unsuccessful
11526 -1 if redisplay with same window start is known not to succeed
11527
11528 The following steps are performed:
11529
11530 1. Find the last row in the current matrix of W that is not
11531 affected by changes at the start of current_buffer. If no such row
11532 is found, give up.
11533
11534 2. Find the first row in W's current matrix that is not affected by
11535 changes at the end of current_buffer. Maybe there is no such row.
11536
11537 3. Display lines beginning with the row + 1 found in step 1 to the
11538 row found in step 2 or, if step 2 didn't find a row, to the end of
11539 the window.
11540
11541 4. If cursor is not known to appear on the window, give up.
11542
11543 5. If display stopped at the row found in step 2, scroll the
11544 display and current matrix as needed.
11545
11546 6. Maybe display some lines at the end of W, if we must. This can
11547 happen under various circumstances, like a partially visible line
11548 becoming fully visible, or because newly displayed lines are displayed
11549 in smaller font sizes.
11550
11551 7. Update W's window end information. */
11552
12adba34 11553static int
5f5c8ee5 11554try_window_id (w)
12adba34 11555 struct window *w;
12adba34 11556{
5f5c8ee5
GM
11557 struct frame *f = XFRAME (w->frame);
11558 struct glyph_matrix *current_matrix = w->current_matrix;
11559 struct glyph_matrix *desired_matrix = w->desired_matrix;
11560 struct glyph_row *last_unchanged_at_beg_row;
11561 struct glyph_row *first_unchanged_at_end_row;
11562 struct glyph_row *row;
11563 struct glyph_row *bottom_row;
11564 int bottom_vpos;
11565 struct it it;
11566 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
11567 struct text_pos start_pos;
11568 struct run run;
11569 int first_unchanged_at_end_vpos = 0;
11570 struct glyph_row *last_text_row, *last_text_row_at_end;
11571 struct text_pos start;
27d16f05 11572 int first_changed_charpos, last_changed_charpos;
5f5c8ee5 11573
69d1f7c9 11574#if GLYPH_DEBUG
76cb5e06
GM
11575 if (inhibit_try_window_id)
11576 return 0;
11577#endif
11578
27d16f05
GM
11579 /* This is handy for debugging. */
11580#if 0
11581#define GIVE_UP(X) \
11582 do { \
11583 fprintf (stderr, "try_window_id give up %d\n", (X)); \
11584 return 0; \
11585 } while (0)
11586#else
62397849 11587#define GIVE_UP(X) return 0
27d16f05 11588#endif
2311178e 11589
5f5c8ee5
GM
11590 SET_TEXT_POS_FROM_MARKER (start, w->start);
11591
27d16f05
GM
11592 /* Don't use this for mini-windows because these can show
11593 messages and mini-buffers, and we don't handle that here. */
11594 if (MINI_WINDOW_P (w))
11595 GIVE_UP (1);
2311178e 11596
27d16f05 11597 /* This flag is used to prevent redisplay optimizations. */
5fb96e96 11598 if (windows_or_buffers_changed || cursor_type_changed)
27d16f05 11599 GIVE_UP (2);
2311178e 11600
c62c1bb5
RS
11601 /* Verify that narrowing has not changed.
11602 Also verify that we were not told to prevent redisplay optimizations.
11603 It would be nice to further
27d16f05 11604 reduce the number of cases where this prevents try_window_id. */
c62c1bb5
RS
11605 if (current_buffer->clip_changed
11606 || current_buffer->prevent_redisplay_optimizations_p)
27d16f05
GM
11607 GIVE_UP (3);
11608
11609 /* Window must either use window-based redisplay or be full width. */
11610 if (!FRAME_WINDOW_P (f)
11611 && (!line_ins_del_ok
11612 || !WINDOW_FULL_WIDTH_P (w)))
11613 GIVE_UP (4);
5f5c8ee5 11614
f5376658 11615 /* Give up if point is not known NOT to appear in W. */
27d16f05
GM
11616 if (PT < CHARPOS (start))
11617 GIVE_UP (5);
11618
11619 /* Another way to prevent redisplay optimizations. */
11620 if (XFASTINT (w->last_modified) == 0)
11621 GIVE_UP (6);
2311178e 11622
f5376658 11623 /* Verify that window is not hscrolled. */
27d16f05
GM
11624 if (XFASTINT (w->hscroll) != 0)
11625 GIVE_UP (7);
2311178e 11626
f5376658 11627 /* Verify that display wasn't paused. */
27d16f05
GM
11628 if (NILP (w->window_end_valid))
11629 GIVE_UP (8);
2311178e 11630
27d16f05
GM
11631 /* Can't use this if highlighting a region because a cursor movement
11632 will do more than just set the cursor. */
11633 if (!NILP (Vtransient_mark_mode)
11634 && !NILP (current_buffer->mark_active))
11635 GIVE_UP (9);
11636
11637 /* Likewise if highlighting trailing whitespace. */
11638 if (!NILP (Vshow_trailing_whitespace))
11639 GIVE_UP (11);
2311178e 11640
27d16f05
GM
11641 /* Likewise if showing a region. */
11642 if (!NILP (w->region_showing))
11643 GIVE_UP (10);
2311178e 11644
27d16f05
GM
11645 /* Can use this if overlay arrow position and or string have changed. */
11646 if (!EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
11647 || !EQ (last_arrow_string, Voverlay_arrow_string))
11648 GIVE_UP (12);
11649
2311178e 11650
5f5c8ee5
GM
11651 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
11652 only if buffer has really changed. The reason is that the gap is
11653 initially at Z for freshly visited files. The code below would
11654 set end_unchanged to 0 in that case. */
28ee91c0
GM
11655 if (MODIFF > SAVE_MODIFF
11656 /* This seems to happen sometimes after saving a buffer. */
11657 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
5f5c8ee5 11658 {
9142dd5b
GM
11659 if (GPT - BEG < BEG_UNCHANGED)
11660 BEG_UNCHANGED = GPT - BEG;
11661 if (Z - GPT < END_UNCHANGED)
11662 END_UNCHANGED = Z - GPT;
5f5c8ee5 11663 }
bf9249e3 11664
27d16f05
GM
11665 /* The position of the first and last character that has been changed. */
11666 first_changed_charpos = BEG + BEG_UNCHANGED;
11667 last_changed_charpos = Z - END_UNCHANGED;
11668
5f5c8ee5
GM
11669 /* If window starts after a line end, and the last change is in
11670 front of that newline, then changes don't affect the display.
f2d86d7a
GM
11671 This case happens with stealth-fontification. Note that although
11672 the display is unchanged, glyph positions in the matrix have to
11673 be adjusted, of course. */
5f5c8ee5 11674 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
27d16f05 11675 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
e60f4527 11676 && ((last_changed_charpos < CHARPOS (start)
27d16f05 11677 && CHARPOS (start) == BEGV)
e60f4527 11678 || (last_changed_charpos < CHARPOS (start) - 1
27d16f05
GM
11679 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
11680 {
11681 int Z_old, delta, Z_BYTE_old, delta_bytes;
11682 struct glyph_row *r0;
11683
11684 /* Compute how many chars/bytes have been added to or removed
11685 from the buffer. */
11686 Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
11687 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
11688 delta = Z - Z_old;
11689 delta_bytes = Z_BYTE - Z_BYTE_old;
2311178e 11690
27d16f05
GM
11691 /* Give up if PT is not in the window. Note that it already has
11692 been checked at the start of try_window_id that PT is not in
11693 front of the window start. */
11694 if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
11695 GIVE_UP (13);
11696
11697 /* If window start is unchanged, we can reuse the whole matrix
11698 as is, after adjusting glyph positions. No need to compute
11699 the window end again, since its offset from Z hasn't changed. */
11700 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
11701 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
11702 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes)
11703 {
11704 /* Adjust positions in the glyph matrix. */
11705 if (delta || delta_bytes)
11706 {
11707 struct glyph_row *r1
11708 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
11709 increment_matrix_positions (w->current_matrix,
11710 MATRIX_ROW_VPOS (r0, current_matrix),
11711 MATRIX_ROW_VPOS (r1, current_matrix),
11712 delta, delta_bytes);
11713 }
2311178e 11714
27d16f05 11715 /* Set the cursor. */
0df56f4d 11716 row = row_containing_pos (w, PT, r0, NULL, 0);
27d16f05
GM
11717 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
11718 return 1;
11719 }
5f5c8ee5
GM
11720 }
11721
27d16f05 11722 /* Handle the case that changes are all below what is displayed in
33ea6c4d 11723 the window, and that PT is in the window. This shortcut cannot
2b9c25e0
GM
11724 be taken if ZV is visible in the window, and text has been added
11725 there that is visible in the window. */
11726 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
33ea6c4d
GM
11727 /* ZV is not visible in the window, or there are no
11728 changes at ZV, actually. */
11729 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
11730 || first_changed_charpos == last_changed_charpos))
5f5c8ee5 11731 {
27d16f05 11732 struct glyph_row *r0;
ef121659 11733
27d16f05
GM
11734 /* Give up if PT is not in the window. Note that it already has
11735 been checked at the start of try_window_id that PT is not in
11736 front of the window start. */
11737 if (PT >= MATRIX_ROW_END_CHARPOS (row))
11738 GIVE_UP (14);
11739
11740 /* If window start is unchanged, we can reuse the whole matrix
11741 as is, without changing glyph positions since no text has
11742 been added/removed in front of the window end. */
11743 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
11744 if (TEXT_POS_EQUAL_P (start, r0->start.pos))
11745 {
11746 /* We have to compute the window end anew since text
11747 can have been added/removed after it. */
11748 w->window_end_pos
11749 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
11750 w->window_end_bytepos
11751 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
11752
11753 /* Set the cursor. */
0df56f4d 11754 row = row_containing_pos (w, PT, r0, NULL, 0);
27d16f05
GM
11755 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
11756 return 2;
11757 }
5f5c8ee5
GM
11758 }
11759
2b9c25e0 11760 /* Give up if window start is in the changed area.
2311178e 11761
2b9c25e0
GM
11762 The condition used to read
11763
11764 (BEG_UNCHANGED + END_UNCHANGED != Z - BEG && ...)
11765
11766 but why that was tested escapes me at the moment. */
11767 if (CHARPOS (start) >= first_changed_charpos
27d16f05
GM
11768 && CHARPOS (start) <= last_changed_charpos)
11769 GIVE_UP (15);
2311178e 11770
f5376658
RS
11771 /* Check that window start agrees with the start of the first glyph
11772 row in its current matrix. Check this after we know the window
11773 start is not in changed text, otherwise positions would not be
11774 comparable. */
27d16f05 11775 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
5f5c8ee5 11776 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
27d16f05 11777 GIVE_UP (16);
5f5c8ee5 11778
23e8bd86
GM
11779 /* Give up if the window ends in strings. Overlay strings
11780 at the end are difficult to handle, so don't try. */
11781 row = MATRIX_ROW (current_matrix, XFASTINT (w->window_end_vpos));
11782 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
11783 GIVE_UP (20);
11784
5f5c8ee5
GM
11785 /* Compute the position at which we have to start displaying new
11786 lines. Some of the lines at the top of the window might be
11787 reusable because they are not displaying changed text. Find the
11788 last row in W's current matrix not affected by changes at the
11789 start of current_buffer. Value is null if changes start in the
11790 first line of window. */
1ec185cb 11791 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
5f5c8ee5
GM
11792 if (last_unchanged_at_beg_row)
11793 {
67f1cf4c
GM
11794 /* Avoid starting to display in the moddle of a character, a TAB
11795 for instance. This is easier than to set up the iterator
11796 exactly, and it's not a frequent case, so the additional
11797 effort wouldn't really pay off. */
e74fb0f7
GM
11798 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
11799 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
67f1cf4c
GM
11800 && last_unchanged_at_beg_row > w->current_matrix->rows)
11801 --last_unchanged_at_beg_row;
11802
11803 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
27d16f05 11804 GIVE_UP (17);
47d57b22
GM
11805
11806 if (init_to_row_end (&it, w, last_unchanged_at_beg_row) == 0)
11807 GIVE_UP (18);
5f5c8ee5 11808 start_pos = it.current.pos;
2311178e 11809
5f5c8ee5
GM
11810 /* Start displaying new lines in the desired matrix at the same
11811 vpos we would use in the current matrix, i.e. below
11812 last_unchanged_at_beg_row. */
11813 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
11814 current_matrix);
11815 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
11816 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
11817
11818 xassert (it.hpos == 0 && it.current_x == 0);
11819 }
11820 else
11821 {
11822 /* There are no reusable lines at the start of the window.
11823 Start displaying in the first line. */
11824 start_display (&it, w, start);
11825 start_pos = it.current.pos;
11826 }
11827
5f5c8ee5
GM
11828 /* Find the first row that is not affected by changes at the end of
11829 the buffer. Value will be null if there is no unchanged row, in
11830 which case we must redisplay to the end of the window. delta
11831 will be set to the value by which buffer positions beginning with
11832 first_unchanged_at_end_row have to be adjusted due to text
11833 changes. */
11834 first_unchanged_at_end_row
1ec185cb 11835 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
5f5c8ee5
GM
11836 IF_DEBUG (debug_delta = delta);
11837 IF_DEBUG (debug_delta_bytes = delta_bytes);
2311178e 11838
5f5c8ee5
GM
11839 /* Set stop_pos to the buffer position up to which we will have to
11840 display new lines. If first_unchanged_at_end_row != NULL, this
11841 is the buffer position of the start of the line displayed in that
11842 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
11843 that we don't stop at a buffer position. */
11844 stop_pos = 0;
11845 if (first_unchanged_at_end_row)
11846 {
11847 xassert (last_unchanged_at_beg_row == NULL
11848 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
2311178e 11849
5f5c8ee5
GM
11850 /* If this is a continuation line, move forward to the next one
11851 that isn't. Changes in lines above affect this line.
11852 Caution: this may move first_unchanged_at_end_row to a row
11853 not displaying text. */
11854 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
11855 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
11856 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
11857 < it.last_visible_y))
11858 ++first_unchanged_at_end_row;
11859
11860 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
11861 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
11862 >= it.last_visible_y))
11863 first_unchanged_at_end_row = NULL;
11864 else
11865 {
11866 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
11867 + delta);
11868 first_unchanged_at_end_vpos
11869 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 11870 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
11871 }
11872 }
11873 else if (last_unchanged_at_beg_row == NULL)
23e8bd86 11874 GIVE_UP (19);
5f5c8ee5
GM
11875
11876
11877#if GLYPH_DEBUG
2311178e 11878
5f5c8ee5
GM
11879 /* Either there is no unchanged row at the end, or the one we have
11880 now displays text. This is a necessary condition for the window
11881 end pos calculation at the end of this function. */
11882 xassert (first_unchanged_at_end_row == NULL
11883 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
2311178e 11884
5f5c8ee5
GM
11885 debug_last_unchanged_at_beg_vpos
11886 = (last_unchanged_at_beg_row
11887 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
11888 : -1);
11889 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
2311178e 11890
5f5c8ee5
GM
11891#endif /* GLYPH_DEBUG != 0 */
11892
2311178e 11893
5f5c8ee5
GM
11894 /* Display new lines. Set last_text_row to the last new line
11895 displayed which has text on it, i.e. might end up as being the
11896 line where the window_end_vpos is. */
11897 w->cursor.vpos = -1;
11898 last_text_row = NULL;
11899 overlay_arrow_seen = 0;
11900 while (it.current_y < it.last_visible_y
11901 && !fonts_changed_p
11902 && (first_unchanged_at_end_row == NULL
11903 || IT_CHARPOS (it) < stop_pos))
11904 {
11905 if (display_line (&it))
11906 last_text_row = it.glyph_row - 1;
11907 }
11908
11909 if (fonts_changed_p)
11910 return -1;
11911
11912
11913 /* Compute differences in buffer positions, y-positions etc. for
11914 lines reused at the bottom of the window. Compute what we can
11915 scroll. */
ca42b2e8
GM
11916 if (first_unchanged_at_end_row
11917 /* No lines reused because we displayed everything up to the
11918 bottom of the window. */
11919 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
11920 {
11921 dvpos = (it.vpos
11922 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
11923 current_matrix));
11924 dy = it.current_y - first_unchanged_at_end_row->y;
11925 run.current_y = first_unchanged_at_end_row->y;
11926 run.desired_y = run.current_y + dy;
11927 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
11928 }
11929 else
ca42b2e8
GM
11930 {
11931 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
11932 first_unchanged_at_end_row = NULL;
11933 }
5f5c8ee5
GM
11934 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
11935
8f8ba186 11936
5f5c8ee5
GM
11937 /* Find the cursor if not already found. We have to decide whether
11938 PT will appear on this window (it sometimes doesn't, but this is
11939 not a very frequent case.) This decision has to be made before
11940 the current matrix is altered. A value of cursor.vpos < 0 means
11941 that PT is either in one of the lines beginning at
11942 first_unchanged_at_end_row or below the window. Don't care for
11943 lines that might be displayed later at the window end; as
11944 mentioned, this is not a frequent case. */
11945 if (w->cursor.vpos < 0)
11946 {
5f5c8ee5
GM
11947 /* Cursor in unchanged rows at the top? */
11948 if (PT < CHARPOS (start_pos)
11949 && last_unchanged_at_beg_row)
11950 {
e037b9ec
GM
11951 row = row_containing_pos (w, PT,
11952 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
0df56f4d 11953 last_unchanged_at_beg_row + 1, 0);
bfe0ee88
GM
11954 if (row)
11955 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
11956 }
11957
11958 /* Start from first_unchanged_at_end_row looking for PT. */
11959 else if (first_unchanged_at_end_row)
11960 {
e037b9ec 11961 row = row_containing_pos (w, PT - delta,
0df56f4d 11962 first_unchanged_at_end_row, NULL, 0);
e037b9ec 11963 if (row)
468155d7
GM
11964 set_cursor_from_row (w, row, w->current_matrix, delta,
11965 delta_bytes, dy, dvpos);
5f5c8ee5
GM
11966 }
11967
11968 /* Give up if cursor was not found. */
11969 if (w->cursor.vpos < 0)
11970 {
11971 clear_glyph_matrix (w->desired_matrix);
11972 return -1;
11973 }
11974 }
2311178e 11975
5f5c8ee5
GM
11976 /* Don't let the cursor end in the scroll margins. */
11977 {
11978 int this_scroll_margin, cursor_height;
2311178e 11979
5f5c8ee5
GM
11980 this_scroll_margin = max (0, scroll_margin);
11981 this_scroll_margin = min (this_scroll_margin,
11982 XFASTINT (w->height) / 4);
11983 this_scroll_margin *= CANON_Y_UNIT (it.f);
11984 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
2311178e 11985
5f5c8ee5
GM
11986 if ((w->cursor.y < this_scroll_margin
11987 && CHARPOS (start) > BEGV)
11988 /* Don't take scroll margin into account at the bottom because
11989 old redisplay didn't do it either. */
11990 || w->cursor.y + cursor_height > it.last_visible_y)
11991 {
11992 w->cursor.vpos = -1;
11993 clear_glyph_matrix (w->desired_matrix);
11994 return -1;
11995 }
11996 }
11997
11998 /* Scroll the display. Do it before changing the current matrix so
11999 that xterm.c doesn't get confused about where the cursor glyph is
12000 found. */
fa77249f 12001 if (dy && run.height)
5f5c8ee5
GM
12002 {
12003 update_begin (f);
2311178e 12004
5f5c8ee5
GM
12005 if (FRAME_WINDOW_P (f))
12006 {
12007 rif->update_window_begin_hook (w);
64d1e7d3 12008 rif->clear_mouse_face (w);
5f5c8ee5 12009 rif->scroll_run_hook (w, &run);
64d1e7d3 12010 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
12011 }
12012 else
12013 {
12014 /* Terminal frame. In this case, dvpos gives the number of
12015 lines to scroll by; dvpos < 0 means scroll up. */
12016 int first_unchanged_at_end_vpos
12017 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
12018 int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
522ed7fb
GM
12019 int end = (XFASTINT (w->top)
12020 + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
12021 + window_internal_height (w));
2311178e 12022
5f5c8ee5
GM
12023 /* Perform the operation on the screen. */
12024 if (dvpos > 0)
12025 {
12026 /* Scroll last_unchanged_at_beg_row to the end of the
12027 window down dvpos lines. */
12028 set_terminal_window (end);
12029
12030 /* On dumb terminals delete dvpos lines at the end
12031 before inserting dvpos empty lines. */
12032 if (!scroll_region_ok)
12033 ins_del_lines (end - dvpos, -dvpos);
12034
12035 /* Insert dvpos empty lines in front of
12036 last_unchanged_at_beg_row. */
12037 ins_del_lines (from, dvpos);
12038 }
12039 else if (dvpos < 0)
12040 {
12041 /* Scroll up last_unchanged_at_beg_vpos to the end of
12042 the window to last_unchanged_at_beg_vpos - |dvpos|. */
12043 set_terminal_window (end);
12044
12045 /* Delete dvpos lines in front of
12046 last_unchanged_at_beg_vpos. ins_del_lines will set
12047 the cursor to the given vpos and emit |dvpos| delete
12048 line sequences. */
12049 ins_del_lines (from + dvpos, dvpos);
12050
12051 /* On a dumb terminal insert dvpos empty lines at the
12052 end. */
12053 if (!scroll_region_ok)
12054 ins_del_lines (end + dvpos, -dvpos);
12055 }
2311178e 12056
5f5c8ee5
GM
12057 set_terminal_window (0);
12058 }
2311178e 12059
5f5c8ee5
GM
12060 update_end (f);
12061 }
12062
ca42b2e8
GM
12063 /* Shift reused rows of the current matrix to the right position.
12064 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
12065 text. */
12066 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
12067 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
12068 if (dvpos < 0)
12069 {
12070 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
12071 bottom_vpos, dvpos);
12072 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
12073 bottom_vpos, 0);
12074 }
12075 else if (dvpos > 0)
12076 {
12077 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
12078 bottom_vpos, dvpos);
12079 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
12080 first_unchanged_at_end_vpos + dvpos, 0);
12081 }
12082
12083 /* For frame-based redisplay, make sure that current frame and window
12084 matrix are in sync with respect to glyph memory. */
12085 if (!FRAME_WINDOW_P (f))
12086 sync_frame_with_window_matrix_rows (w);
12087
12088 /* Adjust buffer positions in reused rows. */
12089 if (delta)
f2d86d7a
GM
12090 increment_matrix_positions (current_matrix,
12091 first_unchanged_at_end_vpos + dvpos,
12092 bottom_vpos, delta, delta_bytes);
5f5c8ee5
GM
12093
12094 /* Adjust Y positions. */
12095 if (dy)
12096 shift_glyph_matrix (w, current_matrix,
12097 first_unchanged_at_end_vpos + dvpos,
12098 bottom_vpos, dy);
12099
12100 if (first_unchanged_at_end_row)
12101 first_unchanged_at_end_row += dvpos;
12102
12103 /* If scrolling up, there may be some lines to display at the end of
12104 the window. */
12105 last_text_row_at_end = NULL;
12106 if (dy < 0)
12107 {
9c6ba6d1
GM
12108 /* Scrolling up can leave for example a partially visible line
12109 at the end of the window to be redisplayed. */
5f5c8ee5
GM
12110 /* Set last_row to the glyph row in the current matrix where the
12111 window end line is found. It has been moved up or down in
12112 the matrix by dvpos. */
12113 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
12114 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
12115
12116 /* If last_row is the window end line, it should display text. */
12117 xassert (last_row->displays_text_p);
12118
12119 /* If window end line was partially visible before, begin
12120 displaying at that line. Otherwise begin displaying with the
12121 line following it. */
12122 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
12123 {
12124 init_to_row_start (&it, w, last_row);
12125 it.vpos = last_vpos;
12126 it.current_y = last_row->y;
12127 }
12128 else
12129 {
12130 init_to_row_end (&it, w, last_row);
12131 it.vpos = 1 + last_vpos;
12132 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
12133 ++last_row;
12134 }
12adba34 12135
23e8bd86
GM
12136 /* We may start in a continuation line. If so, we have to
12137 get the right continuation_lines_width and current_x. */
12138 it.continuation_lines_width = last_row->continuation_lines_width;
12139 it.hpos = it.current_x = 0;
2311178e 12140
23e8bd86
GM
12141 /* Display the rest of the lines at the window end. */
12142 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
12143 while (it.current_y < it.last_visible_y
12144 && !fonts_changed_p)
5f5c8ee5 12145 {
23e8bd86
GM
12146 /* Is it always sure that the display agrees with lines in
12147 the current matrix? I don't think so, so we mark rows
12148 displayed invalid in the current matrix by setting their
12149 enabled_p flag to zero. */
12150 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
12151 if (display_line (&it))
12152 last_text_row_at_end = it.glyph_row - 1;
5f5c8ee5
GM
12153 }
12154 }
12adba34 12155
5f5c8ee5
GM
12156 /* Update window_end_pos and window_end_vpos. */
12157 if (first_unchanged_at_end_row
12158 && first_unchanged_at_end_row->y < it.last_visible_y
12159 && !last_text_row_at_end)
12160 {
12161 /* Window end line if one of the preserved rows from the current
12162 matrix. Set row to the last row displaying text in current
12163 matrix starting at first_unchanged_at_end_row, after
12164 scrolling. */
12165 xassert (first_unchanged_at_end_row->displays_text_p);
12166 row = find_last_row_displaying_text (w->current_matrix, &it,
12167 first_unchanged_at_end_row);
12168 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
2311178e 12169
ac90c44f 12170 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
5f5c8ee5 12171 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
ac90c44f
GM
12172 w->window_end_vpos
12173 = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
23fca891 12174 xassert (w->window_end_bytepos >= 0);
0416532f 12175 IF_DEBUG (debug_method_add (w, "A"));
5f5c8ee5
GM
12176 }
12177 else if (last_text_row_at_end)
12178 {
ac90c44f
GM
12179 w->window_end_pos
12180 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
5f5c8ee5
GM
12181 w->window_end_bytepos
12182 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
ac90c44f
GM
12183 w->window_end_vpos
12184 = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
23fca891 12185 xassert (w->window_end_bytepos >= 0);
0416532f 12186 IF_DEBUG (debug_method_add (w, "B"));
5f5c8ee5
GM
12187 }
12188 else if (last_text_row)
12189 {
12190 /* We have displayed either to the end of the window or at the
12191 end of the window, i.e. the last row with text is to be found
12192 in the desired matrix. */
ac90c44f
GM
12193 w->window_end_pos
12194 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
5f5c8ee5
GM
12195 w->window_end_bytepos
12196 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12197 w->window_end_vpos
12198 = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
23fca891 12199 xassert (w->window_end_bytepos >= 0);
5f5c8ee5
GM
12200 }
12201 else if (first_unchanged_at_end_row == NULL
12202 && last_text_row == NULL
12203 && last_text_row_at_end == NULL)
12204 {
12205 /* Displayed to end of window, but no line containing text was
12206 displayed. Lines were deleted at the end of the window. */
0416532f
GM
12207 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
12208 int vpos = XFASTINT (w->window_end_vpos);
12209 struct glyph_row *current_row = current_matrix->rows + vpos;
12210 struct glyph_row *desired_row = desired_matrix->rows + vpos;
12211
12212 for (row = NULL;
12213 row == NULL && vpos >= first_vpos;
12214 --vpos, --current_row, --desired_row)
12215 {
12216 if (desired_row->enabled_p)
12217 {
12218 if (desired_row->displays_text_p)
12219 row = desired_row;
12220 }
12221 else if (current_row->displays_text_p)
12222 row = current_row;
12223 }
12adba34 12224
0416532f 12225 xassert (row != NULL);
d88a79d4 12226 w->window_end_vpos = make_number (vpos + 1);
8c56a983
GM
12227 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
12228 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
23fca891 12229 xassert (w->window_end_bytepos >= 0);
0416532f 12230 IF_DEBUG (debug_method_add (w, "C"));
5f5c8ee5
GM
12231 }
12232 else
12233 abort ();
ac90c44f 12234
8cdb267e
GM
12235#if 0 /* This leads to problems, for instance when the cursor is
12236 at ZV, and the cursor line displays no text. */
ac90c44f
GM
12237 /* Disable rows below what's displayed in the window. This makes
12238 debugging easier. */
12239 enable_glyph_matrix_rows (current_matrix,
12240 XFASTINT (w->window_end_vpos) + 1,
12241 bottom_vpos, 0);
8cdb267e 12242#endif
23e8bd86 12243
5f5c8ee5
GM
12244 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
12245 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 12246
5f5c8ee5
GM
12247 /* Record that display has not been completed. */
12248 w->window_end_valid = Qnil;
12249 w->desired_matrix->no_scrolling_p = 1;
ef121659 12250 return 3;
27d16f05
GM
12251
12252#undef GIVE_UP
12adba34 12253}
0f9c0ff0 12254
a2889657 12255
5f5c8ee5
GM
12256\f
12257/***********************************************************************
12258 More debugging support
12259 ***********************************************************************/
a2889657 12260
5f5c8ee5 12261#if GLYPH_DEBUG
a2889657 12262
eaaa65b0 12263void dump_glyph_row P_ ((struct glyph_row *, int, int));
9ab436b9 12264void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
e187cf71 12265void dump_glyph P_ ((struct glyph_row *, struct glyph *, int));
1c9241f5 12266
31b24551 12267
9ab436b9 12268/* Dump the contents of glyph matrix MATRIX on stderr.
ca26e1c8 12269
9ab436b9
GM
12270 GLYPHS 0 means don't show glyph contents.
12271 GLYPHS 1 means show glyphs in short form
12272 GLYPHS > 1 means show glyphs in long form. */
12273
12274void
12275dump_glyph_matrix (matrix, glyphs)
5f5c8ee5 12276 struct glyph_matrix *matrix;
9ab436b9 12277 int glyphs;
5f5c8ee5 12278{
efc63ef0 12279 int i;
5f5c8ee5 12280 for (i = 0; i < matrix->nrows; ++i)
eaaa65b0 12281 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
5f5c8ee5 12282}
31b24551 12283
68a37fa8 12284
e187cf71
GM
12285/* Dump contents of glyph GLYPH to stderr. ROW and AREA are
12286 the glyph row and area where the glyph comes from. */
12287
12288void
12289dump_glyph (row, glyph, area)
12290 struct glyph_row *row;
12291 struct glyph *glyph;
12292 int area;
12293{
12294 if (glyph->type == CHAR_GLYPH)
12295 {
12296 fprintf (stderr,
12297 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
12298 glyph - row->glyphs[TEXT_AREA],
12299 'C',
12300 glyph->charpos,
12301 (BUFFERP (glyph->object)
12302 ? 'B'
12303 : (STRINGP (glyph->object)
12304 ? 'S'
12305 : '-')),
12306 glyph->pixel_width,
12307 glyph->u.ch,
12308 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
12309 ? glyph->u.ch
12310 : '.'),
12311 glyph->face_id,
12312 glyph->left_box_line_p,
12313 glyph->right_box_line_p);
12314 }
12315 else if (glyph->type == STRETCH_GLYPH)
12316 {
12317 fprintf (stderr,
12318 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
12319 glyph - row->glyphs[TEXT_AREA],
12320 'S',
12321 glyph->charpos,
12322 (BUFFERP (glyph->object)
12323 ? 'B'
12324 : (STRINGP (glyph->object)
12325 ? 'S'
12326 : '-')),
12327 glyph->pixel_width,
12328 0,
12329 '.',
12330 glyph->face_id,
12331 glyph->left_box_line_p,
12332 glyph->right_box_line_p);
12333 }
12334 else if (glyph->type == IMAGE_GLYPH)
12335 {
12336 fprintf (stderr,
12337 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
12338 glyph - row->glyphs[TEXT_AREA],
12339 'I',
12340 glyph->charpos,
12341 (BUFFERP (glyph->object)
12342 ? 'B'
12343 : (STRINGP (glyph->object)
12344 ? 'S'
12345 : '-')),
12346 glyph->pixel_width,
12347 glyph->u.img_id,
12348 '.',
12349 glyph->face_id,
12350 glyph->left_box_line_p,
12351 glyph->right_box_line_p);
12352 }
12353}
12354
12355
5f5c8ee5 12356/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
9ab436b9
GM
12357 GLYPHS 0 means don't show glyph contents.
12358 GLYPHS 1 means show glyphs in short form
12359 GLYPHS > 1 means show glyphs in long form. */
a2889657 12360
5f5c8ee5 12361void
eaaa65b0
GM
12362dump_glyph_row (row, vpos, glyphs)
12363 struct glyph_row *row;
9ab436b9 12364 int vpos, glyphs;
5f5c8ee5 12365{
9ab436b9
GM
12366 if (glyphs != 1)
12367 {
b94c0d9c 12368 fprintf (stderr, "Row Start End Used oEI><O\\CTZFesm X Y W H V A P\n");
9ab436b9 12369 fprintf (stderr, "=======================================================================\n");
2311178e 12370
0ad38729 12371 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d\
33ea6c4d 12372%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 12373 vpos,
9ab436b9
GM
12374 MATRIX_ROW_START_CHARPOS (row),
12375 MATRIX_ROW_END_CHARPOS (row),
12376 row->used[TEXT_AREA],
12377 row->contains_overlapping_glyphs_p,
12378 row->enabled_p,
9ab436b9
GM
12379 row->truncated_on_left_p,
12380 row->truncated_on_right_p,
12381 row->overlay_arrow_p,
12382 row->continued_p,
12383 MATRIX_ROW_CONTINUATION_LINE_P (row),
12384 row->displays_text_p,
12385 row->ends_at_zv_p,
12386 row->fill_line_p,
12387 row->ends_in_middle_of_char_p,
12388 row->starts_in_middle_of_char_p,
b94c0d9c 12389 row->mouse_face_p,
9ab436b9
GM
12390 row->x,
12391 row->y,
12392 row->pixel_width,
12393 row->height,
12394 row->visible_height,
12395 row->ascent,
12396 row->phys_ascent);
33ea6c4d
GM
12397 fprintf (stderr, "%9d %5d\t%5d\n", row->start.overlay_string_index,
12398 row->end.overlay_string_index,
12399 row->continuation_lines_width);
9ab436b9
GM
12400 fprintf (stderr, "%9d %5d\n",
12401 CHARPOS (row->start.string_pos),
12402 CHARPOS (row->end.string_pos));
12403 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
12404 row->end.dpvec_index);
12405 }
2311178e 12406
9ab436b9 12407 if (glyphs > 1)
bd66d1ba 12408 {
e187cf71
GM
12409 int area;
12410
12411 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
12412 {
091f8878
GM
12413 struct glyph *glyph = row->glyphs[area];
12414 struct glyph *glyph_end = glyph + row->used[area];
2311178e 12415
e187cf71 12416 /* Glyph for a line end in text. */
091f8878 12417 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
e187cf71 12418 ++glyph_end;
2311178e 12419
e187cf71
GM
12420 if (glyph < glyph_end)
12421 fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
2311178e 12422
e187cf71
GM
12423 for (; glyph < glyph_end; ++glyph)
12424 dump_glyph (row, glyph, area);
f7b4b63a 12425 }
f4faa47c 12426 }
9ab436b9
GM
12427 else if (glyphs == 1)
12428 {
e187cf71 12429 int area;
9ab436b9 12430
e187cf71 12431 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
9ab436b9 12432 {
e187cf71
GM
12433 char *s = (char *) alloca (row->used[area] + 1);
12434 int i;
12435
12436 for (i = 0; i < row->used[area]; ++i)
12437 {
12438 struct glyph *glyph = row->glyphs[area] + i;
12439 if (glyph->type == CHAR_GLYPH
12440 && glyph->u.ch < 0x80
12441 && glyph->u.ch >= ' ')
12442 s[i] = glyph->u.ch;
12443 else
12444 s[i] = '.';
12445 }
2311178e 12446
e187cf71
GM
12447 s[i] = '\0';
12448 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
12449 }
9ab436b9 12450 }
5f5c8ee5 12451}
f4faa47c 12452
a2889657 12453
5f5c8ee5
GM
12454DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
12455 Sdump_glyph_matrix, 0, 1, "p",
7ee72033 12456 doc: /* Dump the current matrix of the selected window to stderr.
228299fa
GM
12457Shows contents of glyph row structures. With non-nil
12458parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show
7ee72033
MB
12459glyphs in short form, otherwise show glyphs in long form. */)
12460 (glyphs)
9ab436b9 12461 Lisp_Object glyphs;
5f5c8ee5
GM
12462{
12463 struct window *w = XWINDOW (selected_window);
12464 struct buffer *buffer = XBUFFER (w->buffer);
12465
12466 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
12467 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
12468 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
12469 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
12470 fprintf (stderr, "=============================================\n");
9ab436b9
GM
12471 dump_glyph_matrix (w->current_matrix,
12472 NILP (glyphs) ? 0 : XINT (glyphs));
5f5c8ee5
GM
12473 return Qnil;
12474}
1c2250c2 12475
1fca3fae 12476
7d4cc828
GM
12477DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
12478 Sdump_frame_glyph_matrix, 0, 0, "", doc: /* */)
12479 ()
12480{
12481 struct frame *f = XFRAME (selected_frame);
12482 dump_glyph_matrix (f->current_matrix, 1);
12483 return Qnil;
12484}
12485
12486
e9abc296 12487DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "",
7ee72033 12488 doc: /* Dump glyph row ROW to stderr.
228299fa
GM
12489GLYPH 0 means don't dump glyphs.
12490GLYPH 1 means dump glyphs in short form.
7ee72033
MB
12491GLYPH > 1 or omitted means dump glyphs in long form. */)
12492 (row, glyphs)
e9abc296 12493 Lisp_Object row, glyphs;
5f5c8ee5 12494{
eaaa65b0
GM
12495 struct glyph_matrix *matrix;
12496 int vpos;
2311178e 12497
b7826503 12498 CHECK_NUMBER (row);
eaaa65b0
GM
12499 matrix = XWINDOW (selected_window)->current_matrix;
12500 vpos = XINT (row);
12501 if (vpos >= 0 && vpos < matrix->nrows)
12502 dump_glyph_row (MATRIX_ROW (matrix, vpos),
12503 vpos,
12504 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
12505 return Qnil;
12506}
1fca3fae 12507
67481ae5 12508
b94c0d9c 12509DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "",
c2552f79 12510 doc: /* Dump glyph row ROW of the tool-bar of the current frame to stderr.
228299fa
GM
12511GLYPH 0 means don't dump glyphs.
12512GLYPH 1 means dump glyphs in short form.
7ee72033
MB
12513GLYPH > 1 or omitted means dump glyphs in long form. */)
12514 (row, glyphs)
b94c0d9c 12515 Lisp_Object row, glyphs;
5f5c8ee5 12516{
886bd6f2 12517 struct frame *sf = SELECTED_FRAME ();
eaaa65b0
GM
12518 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
12519 int vpos;
2311178e 12520
b7826503 12521 CHECK_NUMBER (row);
eaaa65b0
GM
12522 vpos = XINT (row);
12523 if (vpos >= 0 && vpos < m->nrows)
12524 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
12525 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
12526 return Qnil;
12527}
ca26e1c8 12528
0f9c0ff0 12529
62397849 12530DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
7ee72033
MB
12531 doc: /* Toggle tracing of redisplay.
12532With ARG, turn tracing on if and only if ARG is positive. */)
12533 (arg)
62397849 12534 Lisp_Object arg;
5f5c8ee5 12535{
62397849
GM
12536 if (NILP (arg))
12537 trace_redisplay_p = !trace_redisplay_p;
12538 else
12539 {
12540 arg = Fprefix_numeric_value (arg);
12541 trace_redisplay_p = XINT (arg) > 0;
12542 }
2311178e 12543
5f5c8ee5
GM
12544 return Qnil;
12545}
bf9249e3
GM
12546
12547
f4a374a1 12548DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
e9757d41
SM
12549 doc: /* Like `format', but print result to stderr.
12550usage: (trace-to-stderr STRING &rest OBJECTS) */)
7ee72033 12551 (nargs, args)
f4a374a1
GM
12552 int nargs;
12553 Lisp_Object *args;
bf9249e3 12554{
f4a374a1 12555 Lisp_Object s = Fformat (nargs, args);
2051c264 12556 fprintf (stderr, "%s", SDATA (s));
bf9249e3
GM
12557 return Qnil;
12558}
2311178e 12559
5f5c8ee5 12560#endif /* GLYPH_DEBUG */
ca26e1c8 12561
ca26e1c8 12562
5f5c8ee5
GM
12563\f
12564/***********************************************************************
12565 Building Desired Matrix Rows
12566 ***********************************************************************/
a2889657 12567
5f5c8ee5
GM
12568/* Return a temporary glyph row holding the glyphs of an overlay
12569 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 12570
5f5c8ee5
GM
12571static struct glyph_row *
12572get_overlay_arrow_glyph_row (w)
12573 struct window *w;
12574{
12575 struct frame *f = XFRAME (WINDOW_FRAME (w));
12576 struct buffer *buffer = XBUFFER (w->buffer);
12577 struct buffer *old = current_buffer;
50f80c2f 12578 const unsigned char *arrow_string = SDATA (Voverlay_arrow_string);
2051c264 12579 int arrow_len = SCHARS (Voverlay_arrow_string);
50f80c2f
KR
12580 const unsigned char *arrow_end = arrow_string + arrow_len;
12581 const unsigned char *p;
5f5c8ee5
GM
12582 struct it it;
12583 int multibyte_p;
12584 int n_glyphs_before;
12585
12586 set_buffer_temp (buffer);
12587 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
12588 it.glyph_row->used[TEXT_AREA] = 0;
12589 SET_TEXT_POS (it.position, 0, 0);
12590
12591 multibyte_p = !NILP (buffer->enable_multibyte_characters);
12592 p = arrow_string;
12593 while (p < arrow_end)
12594 {
12595 Lisp_Object face, ilisp;
2311178e 12596
5f5c8ee5
GM
12597 /* Get the next character. */
12598 if (multibyte_p)
4fdb80f2 12599 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
12600 else
12601 it.c = *p, it.len = 1;
12602 p += it.len;
2311178e 12603
5f5c8ee5 12604 /* Get its face. */
ac90c44f 12605 ilisp = make_number (p - arrow_string);
5f5c8ee5
GM
12606 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
12607 it.face_id = compute_char_face (f, it.c, face);
12608
12609 /* Compute its width, get its glyphs. */
12610 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 12611 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
12612 PRODUCE_GLYPHS (&it);
12613
12614 /* If this character doesn't fit any more in the line, we have
12615 to remove some glyphs. */
12616 if (it.current_x > it.last_visible_x)
12617 {
12618 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
12619 break;
12620 }
12621 }
2311178e 12622
5f5c8ee5
GM
12623 set_buffer_temp (old);
12624 return it.glyph_row;
12625}
ca26e1c8 12626
b0a0fbda 12627
5f5c8ee5
GM
12628/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
12629 glyphs are only inserted for terminal frames since we can't really
12630 win with truncation glyphs when partially visible glyphs are
12631 involved. Which glyphs to insert is determined by
12632 produce_special_glyphs. */
67481ae5 12633
5f5c8ee5
GM
12634static void
12635insert_left_trunc_glyphs (it)
12636 struct it *it;
12637{
12638 struct it truncate_it;
12639 struct glyph *from, *end, *to, *toend;
12640
12641 xassert (!FRAME_WINDOW_P (it->f));
12642
12643 /* Get the truncation glyphs. */
12644 truncate_it = *it;
5f5c8ee5
GM
12645 truncate_it.current_x = 0;
12646 truncate_it.face_id = DEFAULT_FACE_ID;
12647 truncate_it.glyph_row = &scratch_glyph_row;
12648 truncate_it.glyph_row->used[TEXT_AREA] = 0;
12649 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
6fc556fd 12650 truncate_it.object = make_number (0);
5f5c8ee5 12651 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
2311178e 12652
5f5c8ee5
GM
12653 /* Overwrite glyphs from IT with truncation glyphs. */
12654 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
12655 end = from + truncate_it.glyph_row->used[TEXT_AREA];
12656 to = it->glyph_row->glyphs[TEXT_AREA];
12657 toend = to + it->glyph_row->used[TEXT_AREA];
12658
12659 while (from < end)
12660 *to++ = *from++;
12661
37be86f2
KH
12662 /* There may be padding glyphs left over. Overwrite them too. */
12663 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
12664 {
12665 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
12666 while (from < end)
12667 *to++ = *from++;
12668 }
5f5c8ee5 12669
37be86f2
KH
12670 if (to > toend)
12671 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
5f5c8ee5 12672}
e0bfbde6 12673
e0bfbde6 12674
5f5c8ee5 12675/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 12676
5f5c8ee5
GM
12677 Most of the time, ascent and height of a display line will be equal
12678 to the max_ascent and max_height values of the display iterator
12679 structure. This is not the case if
67481ae5 12680
5f5c8ee5
GM
12681 1. We hit ZV without displaying anything. In this case, max_ascent
12682 and max_height will be zero.
1c9241f5 12683
5f5c8ee5
GM
12684 2. We have some glyphs that don't contribute to the line height.
12685 (The glyph row flag contributes_to_line_height_p is for future
12686 pixmap extensions).
f6fd109b 12687
5f5c8ee5
GM
12688 The first case is easily covered by using default values because in
12689 these cases, the line height does not really matter, except that it
12690 must not be zero. */
67481ae5 12691
5f5c8ee5
GM
12692static void
12693compute_line_metrics (it)
12694 struct it *it;
12695{
12696 struct glyph_row *row = it->glyph_row;
12697 int area, i;
1c2250c2 12698
5f5c8ee5
GM
12699 if (FRAME_WINDOW_P (it->f))
12700 {
75c5350a 12701 int i, min_y, max_y;
1c2250c2 12702
5f5c8ee5
GM
12703 /* The line may consist of one space only, that was added to
12704 place the cursor on it. If so, the row's height hasn't been
12705 computed yet. */
12706 if (row->height == 0)
12707 {
12708 if (it->max_ascent + it->max_descent == 0)
312246d1 12709 it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
5f5c8ee5
GM
12710 row->ascent = it->max_ascent;
12711 row->height = it->max_ascent + it->max_descent;
312246d1
GM
12712 row->phys_ascent = it->max_phys_ascent;
12713 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5 12714 }
2311178e 12715
5f5c8ee5
GM
12716 /* Compute the width of this line. */
12717 row->pixel_width = row->x;
12718 for (i = 0; i < row->used[TEXT_AREA]; ++i)
12719 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
12720
12721 xassert (row->pixel_width >= 0);
12722 xassert (row->ascent >= 0 && row->height > 0);
12723
312246d1
GM
12724 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
12725 || MATRIX_ROW_OVERLAPS_PRED_P (row));
12726
12727 /* If first line's physical ascent is larger than its logical
12728 ascent, use the physical ascent, and make the row taller.
12729 This makes accented characters fully visible. */
b28cb6ed 12730 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
312246d1
GM
12731 && row->phys_ascent > row->ascent)
12732 {
12733 row->height += row->phys_ascent - row->ascent;
12734 row->ascent = row->phys_ascent;
12735 }
12736
5f5c8ee5
GM
12737 /* Compute how much of the line is visible. */
12738 row->visible_height = row->height;
2311178e 12739
75c5350a
GM
12740 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
12741 max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
12742
12743 if (row->y < min_y)
12744 row->visible_height -= min_y - row->y;
12745 if (row->y + row->height > max_y)
12746 row->visible_height -= row->y + row->height - max_y;
5f5c8ee5
GM
12747 }
12748 else
12749 {
12750 row->pixel_width = row->used[TEXT_AREA];
33ea6c4d
GM
12751 if (row->continued_p)
12752 row->pixel_width -= it->continuation_pixel_width;
12753 else if (row->truncated_on_right_p)
12754 row->pixel_width -= it->truncation_pixel_width;
312246d1
GM
12755 row->ascent = row->phys_ascent = 0;
12756 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 12757 }
67481ae5 12758
5f5c8ee5
GM
12759 /* Compute a hash code for this row. */
12760 row->hash = 0;
12761 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
12762 for (i = 0; i < row->used[area]; ++i)
12763 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
12764 + row->glyphs[area][i].u.val
43d120d8
KH
12765 + row->glyphs[area][i].face_id
12766 + row->glyphs[area][i].padding_p
5f5c8ee5 12767 + (row->glyphs[area][i].type << 2));
a2889657 12768
5f5c8ee5 12769 it->max_ascent = it->max_descent = 0;
312246d1 12770 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 12771}
12adba34 12772
ca26e1c8 12773
5f5c8ee5
GM
12774/* Append one space to the glyph row of iterator IT if doing a
12775 window-based redisplay. DEFAULT_FACE_P non-zero means let the
12776 space have the default face, otherwise let it have the same face as
80c6cb1f 12777 IT->face_id. Value is non-zero if a space was added.
c6e89d6c
GM
12778
12779 This function is called to make sure that there is always one glyph
12780 at the end of a glyph row that the cursor can be set on under
12781 window-systems. (If there weren't such a glyph we would not know
12782 how wide and tall a box cursor should be displayed).
12783
12784 At the same time this space let's a nicely handle clearing to the
12785 end of the line if the row ends in italic text. */
ca26e1c8 12786
80c6cb1f 12787static int
5f5c8ee5
GM
12788append_space (it, default_face_p)
12789 struct it *it;
12790 int default_face_p;
12791{
12792 if (FRAME_WINDOW_P (it->f))
12793 {
12794 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 12795
5f5c8ee5
GM
12796 if (it->glyph_row->glyphs[TEXT_AREA] + n
12797 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 12798 {
cafafe0b
GM
12799 /* Save some values that must not be changed.
12800 Must save IT->c and IT->len because otherwise
12801 ITERATOR_AT_END_P wouldn't work anymore after
12802 append_space has been called. */
478d746b 12803 enum display_element_type saved_what = it->what;
cafafe0b
GM
12804 int saved_c = it->c, saved_len = it->len;
12805 int saved_x = it->current_x;
5f5c8ee5 12806 int saved_face_id = it->face_id;
cafafe0b 12807 struct text_pos saved_pos;
5f5c8ee5 12808 Lisp_Object saved_object;
980806b6 12809 struct face *face;
5f5c8ee5
GM
12810
12811 saved_object = it->object;
12812 saved_pos = it->position;
2311178e 12813
5f5c8ee5
GM
12814 it->what = IT_CHARACTER;
12815 bzero (&it->position, sizeof it->position);
6fc556fd 12816 it->object = make_number (0);
5f5c8ee5
GM
12817 it->c = ' ';
12818 it->len = 1;
5f5c8ee5
GM
12819
12820 if (default_face_p)
12821 it->face_id = DEFAULT_FACE_ID;
4aad61f8
GM
12822 else if (it->face_before_selective_p)
12823 it->face_id = it->saved_face_id;
980806b6
KH
12824 face = FACE_FROM_ID (it->f, it->face_id);
12825 it->face_id = FACE_FOR_CHAR (it->f, face, 0);
1842fc1a 12826
5f5c8ee5 12827 PRODUCE_GLYPHS (it);
2311178e 12828
5f5c8ee5
GM
12829 it->current_x = saved_x;
12830 it->object = saved_object;
12831 it->position = saved_pos;
12832 it->what = saved_what;
12833 it->face_id = saved_face_id;
cafafe0b
GM
12834 it->len = saved_len;
12835 it->c = saved_c;
80c6cb1f 12836 return 1;
5f5c8ee5
GM
12837 }
12838 }
80c6cb1f
GM
12839
12840 return 0;
5f5c8ee5 12841}
12adba34 12842
1842fc1a 12843
5f5c8ee5
GM
12844/* Extend the face of the last glyph in the text area of IT->glyph_row
12845 to the end of the display line. Called from display_line.
12846 If the glyph row is empty, add a space glyph to it so that we
12847 know the face to draw. Set the glyph row flag fill_line_p. */
2311178e 12848
5f5c8ee5
GM
12849static void
12850extend_face_to_end_of_line (it)
12851 struct it *it;
12852{
12853 struct face *face;
12854 struct frame *f = it->f;
1842fc1a 12855
5f5c8ee5
GM
12856 /* If line is already filled, do nothing. */
12857 if (it->current_x >= it->last_visible_x)
12858 return;
2311178e 12859
5f5c8ee5
GM
12860 /* Face extension extends the background and box of IT->face_id
12861 to the end of the line. If the background equals the background
4aad61f8
GM
12862 of the frame, we don't have to do anything. */
12863 if (it->face_before_selective_p)
12864 face = FACE_FROM_ID (it->f, it->saved_face_id);
12865 else
12866 face = FACE_FROM_ID (f, it->face_id);
2311178e 12867
5f5c8ee5
GM
12868 if (FRAME_WINDOW_P (f)
12869 && face->box == FACE_NO_BOX
12870 && face->background == FRAME_BACKGROUND_PIXEL (f)
12871 && !face->stipple)
12872 return;
1842fc1a 12873
5f5c8ee5
GM
12874 /* Set the glyph row flag indicating that the face of the last glyph
12875 in the text area has to be drawn to the end of the text area. */
12876 it->glyph_row->fill_line_p = 1;
545e04f6 12877
980806b6
KH
12878 /* If current character of IT is not ASCII, make sure we have the
12879 ASCII face. This will be automatically undone the next time
12880 get_next_display_element returns a multibyte character. Note
12881 that the character will always be single byte in unibyte text. */
12882 if (!SINGLE_BYTE_CHAR_P (it->c))
5f5c8ee5 12883 {
980806b6 12884 it->face_id = FACE_FOR_CHAR (f, face, 0);
5f5c8ee5 12885 }
545e04f6 12886
5f5c8ee5
GM
12887 if (FRAME_WINDOW_P (f))
12888 {
12889 /* If the row is empty, add a space with the current face of IT,
12890 so that we know which face to draw. */
12891 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 12892 {
5f5c8ee5 12893 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
43d120d8 12894 it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
5f5c8ee5 12895 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 12896 }
5f5c8ee5
GM
12897 }
12898 else
12899 {
12900 /* Save some values that must not be changed. */
12901 int saved_x = it->current_x;
12902 struct text_pos saved_pos;
12903 Lisp_Object saved_object;
478d746b 12904 enum display_element_type saved_what = it->what;
4aad61f8 12905 int saved_face_id = it->face_id;
5f5c8ee5
GM
12906
12907 saved_object = it->object;
12908 saved_pos = it->position;
2311178e 12909
5f5c8ee5
GM
12910 it->what = IT_CHARACTER;
12911 bzero (&it->position, sizeof it->position);
6fc556fd 12912 it->object = make_number (0);
5f5c8ee5
GM
12913 it->c = ' ';
12914 it->len = 1;
4aad61f8 12915 it->face_id = face->id;
2311178e 12916
5f5c8ee5 12917 PRODUCE_GLYPHS (it);
2311178e 12918
5f5c8ee5
GM
12919 while (it->current_x <= it->last_visible_x)
12920 PRODUCE_GLYPHS (it);
2311178e 12921
5f5c8ee5
GM
12922 /* Don't count these blanks really. It would let us insert a left
12923 truncation glyph below and make us set the cursor on them, maybe. */
12924 it->current_x = saved_x;
12925 it->object = saved_object;
12926 it->position = saved_pos;
12927 it->what = saved_what;
4aad61f8 12928 it->face_id = saved_face_id;
5f5c8ee5
GM
12929 }
12930}
12adba34 12931
545e04f6 12932
5f5c8ee5
GM
12933/* Value is non-zero if text starting at CHARPOS in current_buffer is
12934 trailing whitespace. */
1c9241f5 12935
5f5c8ee5
GM
12936static int
12937trailing_whitespace_p (charpos)
12938 int charpos;
12939{
12940 int bytepos = CHAR_TO_BYTE (charpos);
12941 int c = 0;
7bbe686f 12942
5f5c8ee5
GM
12943 while (bytepos < ZV_BYTE
12944 && (c = FETCH_CHAR (bytepos),
12945 c == ' ' || c == '\t'))
12946 ++bytepos;
0d09d1e6 12947
8f897821
GM
12948 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
12949 {
12950 if (bytepos != PT_BYTE)
12951 return 1;
12952 }
12953 return 0;
5f5c8ee5 12954}
31b24551 12955
545e04f6 12956
5f5c8ee5 12957/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 12958
5f5c8ee5
GM
12959void
12960highlight_trailing_whitespace (f, row)
12961 struct frame *f;
12962 struct glyph_row *row;
12963{
12964 int used = row->used[TEXT_AREA];
2311178e 12965
5f5c8ee5
GM
12966 if (used)
12967 {
12968 struct glyph *start = row->glyphs[TEXT_AREA];
12969 struct glyph *glyph = start + used - 1;
12970
ade0bee1
GM
12971 /* Skip over glyphs inserted to display the cursor at the
12972 end of a line, for extending the face of the last glyph
12973 to the end of the line on terminals, and for truncation
12974 and continuation glyphs. */
65008712
GM
12975 while (glyph >= start
12976 && glyph->type == CHAR_GLYPH
65008712 12977 && INTEGERP (glyph->object))
5f5c8ee5
GM
12978 --glyph;
12979
12980 /* If last glyph is a space or stretch, and it's trailing
12981 whitespace, set the face of all trailing whitespace glyphs in
12982 IT->glyph_row to `trailing-whitespace'. */
12983 if (glyph >= start
12984 && BUFFERP (glyph->object)
12985 && (glyph->type == STRETCH_GLYPH
12986 || (glyph->type == CHAR_GLYPH
43d120d8 12987 && glyph->u.ch == ' '))
5f5c8ee5 12988 && trailing_whitespace_p (glyph->charpos))
545e04f6 12989 {
980806b6 12990 int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
2311178e 12991
5f5c8ee5
GM
12992 while (glyph >= start
12993 && BUFFERP (glyph->object)
12994 && (glyph->type == STRETCH_GLYPH
12995 || (glyph->type == CHAR_GLYPH
43d120d8
KH
12996 && glyph->u.ch == ' ')))
12997 (glyph--)->face_id = face_id;
545e04f6 12998 }
a2889657 12999 }
5f5c8ee5 13000}
a2889657 13001
5fcbb24d 13002
cafafe0b 13003/* Value is non-zero if glyph row ROW in window W should be
0fd37545 13004 used to hold the cursor. */
cafafe0b
GM
13005
13006static int
13007cursor_row_p (w, row)
13008 struct window *w;
13009 struct glyph_row *row;
13010{
9a038881 13011 int cursor_row_p = 1;
2311178e 13012
cafafe0b
GM
13013 if (PT == MATRIX_ROW_END_CHARPOS (row))
13014 {
9a038881
GM
13015 /* If the row ends with a newline from a string, we don't want
13016 the cursor there (if the row is continued it doesn't end in a
13017 newline). */
13018 if (CHARPOS (row->end.string_pos) >= 0
13019 || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
13020 cursor_row_p = row->continued_p;
13021
13022 /* If the row ends at ZV, display the cursor at the end of that
13023 row instead of at the start of the row below. */
13024 else if (row->ends_at_zv_p)
13025 cursor_row_p = 1;
13026 else
13027 cursor_row_p = 0;
cafafe0b
GM
13028 }
13029
9a038881 13030 return cursor_row_p;
cafafe0b
GM
13031}
13032
13033
5f5c8ee5
GM
13034/* Construct the glyph row IT->glyph_row in the desired matrix of
13035 IT->w from text at the current position of IT. See dispextern.h
13036 for an overview of struct it. Value is non-zero if
13037 IT->glyph_row displays text, as opposed to a line displaying ZV
13038 only. */
2311178e 13039
5f5c8ee5
GM
13040static int
13041display_line (it)
13042 struct it *it;
13043{
13044 struct glyph_row *row = it->glyph_row;
13045
13046 /* We always start displaying at hpos zero even if hscrolled. */
13047 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 13048
5f5c8ee5
GM
13049 /* We must not display in a row that's not a text row. */
13050 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
13051 < it->w->desired_matrix->nrows);
12adba34 13052
5f5c8ee5
GM
13053 /* Is IT->w showing the region? */
13054 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 13055
5f5c8ee5
GM
13056 /* Clear the result glyph row and enable it. */
13057 prepare_desired_row (row);
12adba34 13058
5f5c8ee5
GM
13059 row->y = it->current_y;
13060 row->start = it->current;
13061 row->continuation_lines_width = it->continuation_lines_width;
13062 row->displays_text_p = 1;
91004049
GM
13063 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
13064 it->starts_in_middle_of_char_p = 0;
5f5c8ee5
GM
13065
13066 /* Arrange the overlays nicely for our purposes. Usually, we call
13067 display_line on only one line at a time, in which case this
13068 can't really hurt too much, or we call it on lines which appear
13069 one after another in the buffer, in which case all calls to
13070 recenter_overlay_lists but the first will be pretty cheap. */
13071 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
13072
5f5c8ee5
GM
13073 /* Move over display elements that are not visible because we are
13074 hscrolled. This may stop at an x-position < IT->first_visible_x
13075 if the first glyph is partially visible or if we hit a line end. */
13076 if (it->current_x < it->first_visible_x)
13077 move_it_in_display_line_to (it, ZV, it->first_visible_x,
13078 MOVE_TO_POS | MOVE_TO_X);
13079
13080 /* Get the initial row height. This is either the height of the
13081 text hscrolled, if there is any, or zero. */
13082 row->ascent = it->max_ascent;
13083 row->height = it->max_ascent + it->max_descent;
312246d1
GM
13084 row->phys_ascent = it->max_phys_ascent;
13085 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
13086
13087 /* Loop generating characters. The loop is left with IT on the next
13088 character to display. */
13089 while (1)
13090 {
13091 int n_glyphs_before, hpos_before, x_before;
13092 int x, i, nglyphs;
ae26e27d 13093 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
b28cb6ed 13094
5f5c8ee5
GM
13095 /* Retrieve the next thing to display. Value is zero if end of
13096 buffer reached. */
13097 if (!get_next_display_element (it))
13098 {
13099 /* Maybe add a space at the end of this line that is used to
1b335865
GM
13100 display the cursor there under X. Set the charpos of the
13101 first glyph of blank lines not corresponding to any text
13102 to -1. */
13103 if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
13104 || row->used[TEXT_AREA] == 0)
a2889657 13105 {
5f5c8ee5
GM
13106 row->glyphs[TEXT_AREA]->charpos = -1;
13107 row->displays_text_p = 0;
13108
2ad551af 13109 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines)
e6b70fd8
GM
13110 && (!MINI_WINDOW_P (it->w)
13111 || (minibuf_level && EQ (it->window, minibuf_window))))
5f5c8ee5 13112 row->indicate_empty_line_p = 1;
a2889657 13113 }
2311178e 13114
5f5c8ee5
GM
13115 it->continuation_lines_width = 0;
13116 row->ends_at_zv_p = 1;
13117 break;
a2889657 13118 }
a2889657 13119
5f5c8ee5
GM
13120 /* Now, get the metrics of what we want to display. This also
13121 generates glyphs in `row' (which is IT->glyph_row). */
13122 n_glyphs_before = row->used[TEXT_AREA];
13123 x = it->current_x;
e6819faf
GM
13124
13125 /* Remember the line height so far in case the next element doesn't
13126 fit on the line. */
13127 if (!it->truncate_lines_p)
13128 {
13129 ascent = it->max_ascent;
13130 descent = it->max_descent;
13131 phys_ascent = it->max_phys_ascent;
13132 phys_descent = it->max_phys_descent;
13133 }
2311178e 13134
5f5c8ee5 13135 PRODUCE_GLYPHS (it);
a2889657 13136
5f5c8ee5
GM
13137 /* If this display element was in marginal areas, continue with
13138 the next one. */
13139 if (it->area != TEXT_AREA)
a2889657 13140 {
5f5c8ee5
GM
13141 row->ascent = max (row->ascent, it->max_ascent);
13142 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
13143 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
13144 row->phys_height = max (row->phys_height,
13145 it->max_phys_ascent + it->max_phys_descent);
cafafe0b 13146 set_iterator_to_next (it, 1);
5f5c8ee5
GM
13147 continue;
13148 }
5936754e 13149
5f5c8ee5
GM
13150 /* Does the display element fit on the line? If we truncate
13151 lines, we should draw past the right edge of the window. If
13152 we don't truncate, we want to stop so that we can display the
13153 continuation glyph before the right margin. If lines are
13154 continued, there are two possible strategies for characters
13155 resulting in more than 1 glyph (e.g. tabs): Display as many
13156 glyphs as possible in this line and leave the rest for the
13157 continuation line, or display the whole element in the next
13158 line. Original redisplay did the former, so we do it also. */
13159 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
13160 hpos_before = it->hpos;
13161 x_before = x;
4dcd74e6 13162
4b41cebb 13163 if (/* Not a newline. */
4dcd74e6 13164 nglyphs > 0
202c1b5b 13165 /* Glyphs produced fit entirely in the line. */
4dcd74e6
GM
13166 && it->current_x < it->last_visible_x)
13167 {
37be86f2 13168 it->hpos += nglyphs;
5f5c8ee5
GM
13169 row->ascent = max (row->ascent, it->max_ascent);
13170 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
13171 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
13172 row->phys_height = max (row->phys_height,
13173 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
13174 if (it->current_x - it->pixel_width < it->first_visible_x)
13175 row->x = x - it->first_visible_x;
13176 }
13177 else
13178 {
13179 int new_x;
13180 struct glyph *glyph;
2311178e 13181
5f5c8ee5 13182 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 13183 {
5f5c8ee5
GM
13184 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
13185 new_x = x + glyph->pixel_width;
13186
13187 if (/* Lines are continued. */
13188 !it->truncate_lines_p
13189 && (/* Glyph doesn't fit on the line. */
13190 new_x > it->last_visible_x
13191 /* Or it fits exactly on a window system frame. */
13192 || (new_x == it->last_visible_x
13193 && FRAME_WINDOW_P (it->f))))
a2889657 13194 {
5f5c8ee5 13195 /* End of a continued line. */
2311178e 13196
5f5c8ee5
GM
13197 if (it->hpos == 0
13198 || (new_x == it->last_visible_x
13199 && FRAME_WINDOW_P (it->f)))
13200 {
e6819faf
GM
13201 /* Current glyph is the only one on the line or
13202 fits exactly on the line. We must continue
13203 the line because we can't draw the cursor
13204 after the glyph. */
5f5c8ee5
GM
13205 row->continued_p = 1;
13206 it->current_x = new_x;
13207 it->continuation_lines_width += new_x;
13208 ++it->hpos;
13209 if (i == nglyphs - 1)
cafafe0b 13210 set_iterator_to_next (it, 1);
5f5c8ee5 13211 }
3b3c4bf0
GM
13212 else if (CHAR_GLYPH_PADDING_P (*glyph)
13213 && !FRAME_WINDOW_P (it->f))
13214 {
13215 /* A padding glyph that doesn't fit on this line.
13216 This means the whole character doesn't fit
13217 on the line. */
13218 row->used[TEXT_AREA] = n_glyphs_before;
2311178e 13219
3b3c4bf0
GM
13220 /* Fill the rest of the row with continuation
13221 glyphs like in 20.x. */
13222 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
13223 < row->glyphs[1 + TEXT_AREA])
13224 produce_special_glyphs (it, IT_CONTINUATION);
2311178e 13225
3b3c4bf0
GM
13226 row->continued_p = 1;
13227 it->current_x = x_before;
13228 it->continuation_lines_width += x_before;
2311178e 13229
3b3c4bf0
GM
13230 /* Restore the height to what it was before the
13231 element not fitting on the line. */
13232 it->max_ascent = ascent;
13233 it->max_descent = descent;
13234 it->max_phys_ascent = phys_ascent;
13235 it->max_phys_descent = phys_descent;
13236 }
0df56f4d
GM
13237 else if (it->c == '\t' && FRAME_WINDOW_P (it->f))
13238 {
13239 /* A TAB that extends past the right edge of the
13240 window. This produces a single glyph on
13241 window system frames. We leave the glyph in
13242 this row and let it fill the row, but don't
13243 consume the TAB. */
13244 it->continuation_lines_width += it->last_visible_x;
13245 row->ends_in_middle_of_char_p = 1;
13246 row->continued_p = 1;
13247 glyph->pixel_width = it->last_visible_x - x;
13248 it->starts_in_middle_of_char_p = 1;
13249 }
5f5c8ee5 13250 else
5936754e 13251 {
0df56f4d
GM
13252 /* Something other than a TAB that draws past
13253 the right edge of the window. Restore
13254 positions to values before the element. */
5f5c8ee5 13255 row->used[TEXT_AREA] = n_glyphs_before + i;
2311178e 13256
5f5c8ee5
GM
13257 /* Display continuation glyphs. */
13258 if (!FRAME_WINDOW_P (it->f))
13259 produce_special_glyphs (it, IT_CONTINUATION);
13260 row->continued_p = 1;
653c329b 13261
0df56f4d 13262 it->continuation_lines_width += x;
2311178e 13263
91004049
GM
13264 if (nglyphs > 1 && i > 0)
13265 {
13266 row->ends_in_middle_of_char_p = 1;
13267 it->starts_in_middle_of_char_p = 1;
13268 }
2311178e 13269
e6819faf
GM
13270 /* Restore the height to what it was before the
13271 element not fitting on the line. */
13272 it->max_ascent = ascent;
13273 it->max_descent = descent;
13274 it->max_phys_ascent = phys_ascent;
13275 it->max_phys_descent = phys_descent;
5936754e 13276 }
e6819faf 13277
5f5c8ee5
GM
13278 break;
13279 }
13280 else if (new_x > it->first_visible_x)
13281 {
13282 /* Increment number of glyphs actually displayed. */
13283 ++it->hpos;
2311178e 13284
5f5c8ee5
GM
13285 if (x < it->first_visible_x)
13286 /* Glyph is partially visible, i.e. row starts at
13287 negative X position. */
13288 row->x = x - it->first_visible_x;
13289 }
13290 else
13291 {
13292 /* Glyph is completely off the left margin of the
13293 window. This should not happen because of the
72b8c434
RS
13294 move_it_in_display_line at the start of this
13295 function, unless the text display area of the
13296 window is empty. */
13297 xassert (it->first_visible_x <= it->last_visible_x);
a2889657 13298 }
a2889657 13299 }
2311178e 13300
5f5c8ee5
GM
13301 row->ascent = max (row->ascent, it->max_ascent);
13302 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
13303 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
13304 row->phys_height = max (row->phys_height,
13305 it->max_phys_ascent + it->max_phys_descent);
2311178e 13306
5f5c8ee5
GM
13307 /* End of this display line if row is continued. */
13308 if (row->continued_p)
13309 break;
a2889657 13310 }
a2889657 13311
5f5c8ee5
GM
13312 /* Is this a line end? If yes, we're also done, after making
13313 sure that a non-default face is extended up to the right
13314 margin of the window. */
13315 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 13316 {
5f5c8ee5
GM
13317 int used_before = row->used[TEXT_AREA];
13318
e74fb0f7
GM
13319 row->ends_in_newline_from_string_p = STRINGP (it->object);
13320
5f5c8ee5
GM
13321 /* Add a space at the end of the line that is used to
13322 display the cursor there. */
13323 append_space (it, 0);
2311178e 13324
5f5c8ee5
GM
13325 /* Extend the face to the end of the line. */
13326 extend_face_to_end_of_line (it);
13327
13328 /* Make sure we have the position. */
13329 if (used_before == 0)
13330 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
2311178e 13331
5f5c8ee5 13332 /* Consume the line end. This skips over invisible lines. */
cafafe0b 13333 set_iterator_to_next (it, 1);
5f5c8ee5
GM
13334 it->continuation_lines_width = 0;
13335 break;
1c9241f5 13336 }
a2889657 13337
2311178e 13338 /* Proceed with next display element. Note that this skips
5f5c8ee5 13339 over lines invisible because of selective display. */
cafafe0b 13340 set_iterator_to_next (it, 1);
b1d1124b 13341
5f5c8ee5
GM
13342 /* If we truncate lines, we are done when the last displayed
13343 glyphs reach past the right margin of the window. */
13344 if (it->truncate_lines_p
13345 && (FRAME_WINDOW_P (it->f)
13346 ? (it->current_x >= it->last_visible_x)
13347 : (it->current_x > it->last_visible_x)))
75d13c64 13348 {
5f5c8ee5
GM
13349 /* Maybe add truncation glyphs. */
13350 if (!FRAME_WINDOW_P (it->f))
13351 {
a98b5ed9 13352 int i, n;
2311178e 13353
a98b5ed9
GM
13354 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
13355 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
13356 break;
13357
13358 for (n = row->used[TEXT_AREA]; i < n; ++i)
13359 {
13360 row->used[TEXT_AREA] = i;
13361 produce_special_glyphs (it, IT_TRUNCATION);
13362 }
5f5c8ee5 13363 }
2311178e 13364
5f5c8ee5
GM
13365 row->truncated_on_right_p = 1;
13366 it->continuation_lines_width = 0;
312246d1 13367 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
13368 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
13369 it->hpos = hpos_before;
13370 it->current_x = x_before;
13371 break;
75d13c64 13372 }
a2889657 13373 }
a2889657 13374
5f5c8ee5
GM
13375 /* If line is not empty and hscrolled, maybe insert truncation glyphs
13376 at the left window margin. */
13377 if (it->first_visible_x
13378 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
13379 {
13380 if (!FRAME_WINDOW_P (it->f))
13381 insert_left_trunc_glyphs (it);
13382 row->truncated_on_left_p = 1;
13383 }
a2889657 13384
5f5c8ee5
GM
13385 /* If the start of this line is the overlay arrow-position, then
13386 mark this glyph row as the one containing the overlay arrow.
13387 This is clearly a mess with variable size fonts. It would be
13388 better to let it be displayed like cursors under X. */
e24c997d 13389 if (MARKERP (Voverlay_arrow_position)
a2889657 13390 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
13391 && (MATRIX_ROW_START_CHARPOS (row)
13392 == marker_position (Voverlay_arrow_position))
e24c997d 13393 && STRINGP (Voverlay_arrow_string)
a2889657
JB
13394 && ! overlay_arrow_seen)
13395 {
b46952ae 13396 /* Overlay arrow in window redisplay is a fringe bitmap. */
5f5c8ee5 13397 if (!FRAME_WINDOW_P (it->f))
c4628384 13398 {
5f5c8ee5
GM
13399 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
13400 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
13401 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
13402 struct glyph *p = row->glyphs[TEXT_AREA];
13403 struct glyph *p2, *end;
13404
13405 /* Copy the arrow glyphs. */
13406 while (glyph < arrow_end)
13407 *p++ = *glyph++;
13408
13409 /* Throw away padding glyphs. */
13410 p2 = p;
13411 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
13412 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
13413 ++p2;
13414 if (p2 > p)
212e4f87 13415 {
5f5c8ee5
GM
13416 while (p2 < end)
13417 *p++ = *p2++;
13418 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 13419 }
c4628384 13420 }
2311178e 13421
a2889657 13422 overlay_arrow_seen = 1;
5f5c8ee5 13423 row->overlay_arrow_p = 1;
a2889657
JB
13424 }
13425
5f5c8ee5
GM
13426 /* Compute pixel dimensions of this line. */
13427 compute_line_metrics (it);
13428
13429 /* Remember the position at which this line ends. */
13430 row->end = it->current;
13431
173cbca8 13432 /* Maybe set the cursor. */
5f5c8ee5
GM
13433 if (it->w->cursor.vpos < 0
13434 && PT >= MATRIX_ROW_START_CHARPOS (row)
cafafe0b
GM
13435 && PT <= MATRIX_ROW_END_CHARPOS (row)
13436 && cursor_row_p (it->w, row))
13437 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
13438
13439 /* Highlight trailing whitespace. */
8f897821 13440 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
13441 highlight_trailing_whitespace (it->f, it->glyph_row);
13442
13443 /* Prepare for the next line. This line starts horizontally at (X
13444 HPOS) = (0 0). Vertical positions are incremented. As a
13445 convenience for the caller, IT->glyph_row is set to the next
13446 row to be used. */
13447 it->current_x = it->hpos = 0;
13448 it->current_y += row->height;
13449 ++it->vpos;
13450 ++it->glyph_row;
13451 return row->displays_text_p;
a2889657 13452}
5f5c8ee5
GM
13453
13454
a2889657 13455\f
5f5c8ee5
GM
13456/***********************************************************************
13457 Menu Bar
13458 ***********************************************************************/
13459
13460/* Redisplay the menu bar in the frame for window W.
13461
13462 The menu bar of X frames that don't have X toolkit support is
13463 displayed in a special window W->frame->menu_bar_window.
2311178e 13464
5f5c8ee5
GM
13465 The menu bar of terminal frames is treated specially as far as
13466 glyph matrices are concerned. Menu bar lines are not part of
13467 windows, so the update is done directly on the frame matrix rows
13468 for the menu bar. */
7ce2c095
RS
13469
13470static void
13471display_menu_bar (w)
13472 struct window *w;
13473{
5f5c8ee5
GM
13474 struct frame *f = XFRAME (WINDOW_FRAME (w));
13475 struct it it;
13476 Lisp_Object items;
8351baf2 13477 int i;
7ce2c095 13478
5f5c8ee5 13479 /* Don't do all this for graphical frames. */
dc937613 13480#ifdef HAVE_NTGUI
d129c4c2
KH
13481 if (!NILP (Vwindow_system))
13482 return;
dc937613 13483#endif
dc937613 13484#ifdef USE_X_TOOLKIT
d3413a53 13485 if (FRAME_X_P (f))
7ce2c095 13486 return;
5f5c8ee5 13487#endif
e0f712ba 13488#ifdef MAC_OS
1a578e9b
AC
13489 if (FRAME_MAC_P (f))
13490 return;
13491#endif
5f5c8ee5
GM
13492
13493#ifdef USE_X_TOOLKIT
13494 xassert (!FRAME_WINDOW_P (f));
52377a47 13495 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5
GM
13496 it.first_visible_x = 0;
13497 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
13498#else /* not USE_X_TOOLKIT */
13499 if (FRAME_WINDOW_P (f))
13500 {
13501 /* Menu bar lines are displayed in the desired matrix of the
13502 dummy window menu_bar_window. */
13503 struct window *menu_w;
13504 xassert (WINDOWP (f->menu_bar_window));
13505 menu_w = XWINDOW (f->menu_bar_window);
13506 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 13507 MENU_FACE_ID);
5f5c8ee5
GM
13508 it.first_visible_x = 0;
13509 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
13510 }
13511 else
13512 {
13513 /* This is a TTY frame, i.e. character hpos/vpos are used as
13514 pixel x/y. */
13515 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 13516 MENU_FACE_ID);
5f5c8ee5
GM
13517 it.first_visible_x = 0;
13518 it.last_visible_x = FRAME_WIDTH (f);
13519 }
13520#endif /* not USE_X_TOOLKIT */
13521
1862a24e
MB
13522 if (! mode_line_inverse_video)
13523 /* Force the menu-bar to be displayed in the default face. */
13524 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
13525
5f5c8ee5
GM
13526 /* Clear all rows of the menu bar. */
13527 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
13528 {
13529 struct glyph_row *row = it.glyph_row + i;
13530 clear_glyph_row (row);
13531 row->enabled_p = 1;
13532 row->full_width_p = 1;
13533 }
7ce2c095 13534
5f5c8ee5
GM
13535 /* Display all items of the menu bar. */
13536 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 13537 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 13538 {
5f5c8ee5
GM
13539 Lisp_Object string;
13540
13541 /* Stop at nil string. */
a61b7058 13542 string = AREF (items, i + 1);
8351baf2
RS
13543 if (NILP (string))
13544 break;
2d66ad19 13545
5f5c8ee5 13546 /* Remember where item was displayed. */
a61b7058 13547 AREF (items, i + 3) = make_number (it.hpos);
7ce2c095 13548
5f5c8ee5
GM
13549 /* Display the item, pad with one space. */
13550 if (it.current_x < it.last_visible_x)
13551 display_string (NULL, string, Qnil, 0, 0, &it,
2051c264 13552 SCHARS (string) + 1, 0, 0, -1);
7ce2c095
RS
13553 }
13554
2d66ad19 13555 /* Fill out the line with spaces. */
5f5c8ee5
GM
13556 if (it.current_x < it.last_visible_x)
13557 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 13558
5f5c8ee5
GM
13559 /* Compute the total height of the lines. */
13560 compute_line_metrics (&it);
7ce2c095 13561}
5f5c8ee5
GM
13562
13563
7ce2c095 13564\f
5f5c8ee5
GM
13565/***********************************************************************
13566 Mode Line
13567 ***********************************************************************/
13568
715e84c9
GM
13569/* Redisplay mode lines in the window tree whose root is WINDOW. If
13570 FORCE is non-zero, redisplay mode lines unconditionally.
13571 Otherwise, redisplay only mode lines that are garbaged. Value is
13572 the number of windows whose mode lines were redisplayed. */
a2889657 13573
715e84c9
GM
13574static int
13575redisplay_mode_lines (window, force)
13576 Lisp_Object window;
13577 int force;
13578{
13579 int nwindows = 0;
2311178e 13580
715e84c9
GM
13581 while (!NILP (window))
13582 {
13583 struct window *w = XWINDOW (window);
2311178e 13584
715e84c9
GM
13585 if (WINDOWP (w->hchild))
13586 nwindows += redisplay_mode_lines (w->hchild, force);
13587 else if (WINDOWP (w->vchild))
13588 nwindows += redisplay_mode_lines (w->vchild, force);
13589 else if (force
13590 || FRAME_GARBAGED_P (XFRAME (w->frame))
13591 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
13592 {
715e84c9
GM
13593 struct text_pos lpoint;
13594 struct buffer *old = current_buffer;
13595
13596 /* Set the window's buffer for the mode line display. */
13597 SET_TEXT_POS (lpoint, PT, PT_BYTE);
13598 set_buffer_internal_1 (XBUFFER (w->buffer));
2311178e 13599
715e84c9
GM
13600 /* Point refers normally to the selected window. For any
13601 other window, set up appropriate value. */
13602 if (!EQ (window, selected_window))
13603 {
13604 struct text_pos pt;
2311178e 13605
715e84c9
GM
13606 SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
13607 if (CHARPOS (pt) < BEGV)
13608 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
13609 else if (CHARPOS (pt) > (ZV - 1))
13610 TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
13611 else
13612 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
13613 }
13614
715e84c9
GM
13615 /* Display mode lines. */
13616 clear_glyph_matrix (w->desired_matrix);
13617 if (display_mode_lines (w))
13618 {
13619 ++nwindows;
13620 w->must_be_updated_p = 1;
13621 }
13622
13623 /* Restore old settings. */
715e84c9
GM
13624 set_buffer_internal_1 (old);
13625 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
13626 }
13627
13628 window = w->next;
13629 }
13630
13631 return nwindows;
13632}
13633
13634
13635/* Display the mode and/or top line of window W. Value is the number
13636 of mode lines displayed. */
13637
13638static int
5f5c8ee5 13639display_mode_lines (w)
a2889657
JB
13640 struct window *w;
13641{
edd1e654 13642 Lisp_Object old_selected_window, old_selected_frame;
715e84c9 13643 int n = 0;
edd1e654
GM
13644
13645 old_selected_frame = selected_frame;
13646 selected_frame = w->frame;
13647 old_selected_window = selected_window;
13648 XSETWINDOW (selected_window, w);
2311178e 13649
5f5c8ee5 13650 /* These will be set while the mode line specs are processed. */
aa6d10fa 13651 line_number_displayed = 0;
155ef550 13652 w->column_number_displayed = Qnil;
aa6d10fa 13653
5f5c8ee5 13654 if (WINDOW_WANTS_MODELINE_P (w))
715e84c9 13655 {
c96e83bf 13656 struct window *sel_w = XWINDOW (old_selected_window);
f87c0a98 13657
96d2320f 13658 /* Select mode line face based on the real selected window. */
c96e83bf 13659 display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w),
715e84c9
GM
13660 current_buffer->mode_line_format);
13661 ++n;
13662 }
2311178e 13663
045dee35 13664 if (WINDOW_WANTS_HEADER_LINE_P (w))
715e84c9
GM
13665 {
13666 display_mode_line (w, HEADER_LINE_FACE_ID,
13667 current_buffer->header_line_format);
13668 ++n;
13669 }
13670
edd1e654
GM
13671 selected_frame = old_selected_frame;
13672 selected_window = old_selected_window;
715e84c9 13673 return n;
5f5c8ee5 13674}
03b294dc 13675
03b294dc 13676
5f5c8ee5 13677/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 13678 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
04612a64
GM
13679 FORMAT is the mode line format to display. Value is the pixel
13680 height of the mode line displayed. */
03b294dc 13681
04612a64 13682static int
5f5c8ee5
GM
13683display_mode_line (w, face_id, format)
13684 struct window *w;
13685 enum face_id face_id;
13686 Lisp_Object format;
13687{
13688 struct it it;
13689 struct face *face;
03b294dc 13690
5f5c8ee5
GM
13691 init_iterator (&it, w, -1, -1, NULL, face_id);
13692 prepare_desired_row (it.glyph_row);
13693
1862a24e
MB
13694 if (! mode_line_inverse_video)
13695 /* Force the mode-line to be displayed in the default face. */
13696 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
13697
5f5c8ee5
GM
13698 /* Temporarily make frame's keyboard the current kboard so that
13699 kboard-local variables in the mode_line_format will get the right
13700 values. */
13701 push_frame_kboard (it.f);
c53a1624 13702 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
5f5c8ee5 13703 pop_frame_kboard ();
a2889657 13704
5f5c8ee5
GM
13705 /* Fill up with spaces. */
13706 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
2311178e 13707
5f5c8ee5
GM
13708 compute_line_metrics (&it);
13709 it.glyph_row->full_width_p = 1;
13710 it.glyph_row->mode_line_p = 1;
5f5c8ee5
GM
13711 it.glyph_row->continued_p = 0;
13712 it.glyph_row->truncated_on_left_p = 0;
13713 it.glyph_row->truncated_on_right_p = 0;
13714
13715 /* Make a 3D mode-line have a shadow at its right end. */
13716 face = FACE_FROM_ID (it.f, face_id);
13717 extend_face_to_end_of_line (&it);
13718 if (face->box != FACE_NO_BOX)
d7eb09a0 13719 {
5f5c8ee5
GM
13720 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
13721 + it.glyph_row->used[TEXT_AREA] - 1);
13722 last->right_box_line_p = 1;
d7eb09a0 13723 }
04612a64
GM
13724
13725 return it.glyph_row->height;
a2889657
JB
13726}
13727
0fcf414f
RS
13728/* Alist that caches the results of :propertize.
13729 Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */
13730Lisp_Object mode_line_proptrans_alist;
a2889657 13731
fec8f23e
KS
13732/* List of strings making up the mode-line. */
13733Lisp_Object mode_line_string_list;
13734
13735/* Base face property when building propertized mode line string. */
13736static Lisp_Object mode_line_string_face;
13737static Lisp_Object mode_line_string_face_prop;
13738
13739
5f5c8ee5
GM
13740/* Contribute ELT to the mode line for window IT->w. How it
13741 translates into text depends on its data type.
a2889657 13742
5f5c8ee5 13743 IT describes the display environment in which we display, as usual.
a2889657
JB
13744
13745 DEPTH is the depth in recursion. It is used to prevent
13746 infinite recursion here.
13747
5f5c8ee5
GM
13748 FIELD_WIDTH is the number of characters the display of ELT should
13749 occupy in the mode line, and PRECISION is the maximum number of
13750 characters to display from ELT's representation. See
b8523839 13751 display_string for details.
a2889657 13752
c53a1624
RS
13753 Returns the hpos of the end of the text generated by ELT.
13754
13755 PROPS is a property list to add to any string we encounter.
13756
7d0393cf 13757 If RISKY is nonzero, remove (disregard) any properties in any string
93da8435
SM
13758 we encounter, and ignore :eval and :propertize.
13759
13760 If the global variable `frame_title_ptr' is non-NULL, then the output
13761 is passed to `store_frame_title' instead of `display_string'. */
a2889657
JB
13762
13763static int
c53a1624 13764display_mode_element (it, depth, field_width, precision, elt, props, risky)
5f5c8ee5 13765 struct it *it;
a2889657 13766 int depth;
5f5c8ee5 13767 int field_width, precision;
0fcf414f 13768 Lisp_Object elt, props;
c53a1624 13769 int risky;
a2889657 13770{
5f5c8ee5 13771 int n = 0, field, prec;
0fcf414f 13772 int literal = 0;
5f5c8ee5 13773
a2889657
JB
13774 tail_recurse:
13775 if (depth > 10)
13776 goto invalid;
13777
13778 depth++;
13779
0220c518 13780 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
13781 {
13782 case Lisp_String:
13783 {
13784 /* A string: output it and check for %-constructs within it. */
5f5c8ee5 13785 unsigned char c;
50f80c2f 13786 const unsigned char *this, *lisp_string;
5f5c8ee5 13787
c53a1624 13788 if (!NILP (props) || risky)
0fcf414f
RS
13789 {
13790 Lisp_Object oprops, aelt;
13791 oprops = Ftext_properties_at (make_number (0), elt);
c53a1624
RS
13792
13793 if (NILP (Fequal (props, oprops)) || risky)
0fcf414f 13794 {
ae02e06a
RS
13795 /* If the starting string has properties,
13796 merge the specified ones onto the existing ones. */
c53a1624 13797 if (! NILP (oprops) && !risky)
ae02e06a
RS
13798 {
13799 Lisp_Object tem;
13800
13801 oprops = Fcopy_sequence (oprops);
13802 tem = props;
13803 while (CONSP (tem))
13804 {
13805 oprops = Fplist_put (oprops, XCAR (tem),
13806 XCAR (XCDR (tem)));
13807 tem = XCDR (XCDR (tem));
13808 }
13809 props = oprops;
13810 }
13811
0fcf414f
RS
13812 aelt = Fassoc (elt, mode_line_proptrans_alist);
13813 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
adb63af1
RS
13814 {
13815 mode_line_proptrans_alist
13816 = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist));
13817 elt = XCAR (aelt);
13818 }
0fcf414f
RS
13819 else
13820 {
adb63af1
RS
13821 Lisp_Object tem;
13822
0fcf414f 13823 elt = Fcopy_sequence (elt);
dc3b2c8b
SM
13824 Fset_text_properties (make_number (0), Flength (elt),
13825 props, elt);
adb63af1 13826 /* Add this item to mode_line_proptrans_alist. */
0fcf414f
RS
13827 mode_line_proptrans_alist
13828 = Fcons (Fcons (elt, props),
13829 mode_line_proptrans_alist);
adb63af1
RS
13830 /* Truncate mode_line_proptrans_alist
13831 to at most 50 elements. */
13832 tem = Fnthcdr (make_number (50),
13833 mode_line_proptrans_alist);
13834 if (! NILP (tem))
13835 XSETCDR (tem, Qnil);
0fcf414f
RS
13836 }
13837 }
13838 }
13839
2051c264 13840 this = SDATA (elt);
ae02e06a
RS
13841 lisp_string = this;
13842
0fcf414f
RS
13843 if (literal)
13844 {
13845 prec = precision - n;
13846 if (frame_title_ptr)
2051c264 13847 n += store_frame_title (SDATA (elt), -1, prec);
fec8f23e
KS
13848 else if (!NILP (mode_line_string_list))
13849 n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
0fcf414f
RS
13850 else
13851 n += display_string (NULL, elt, Qnil, 0, 0, it,
13852 0, prec, 0, STRING_MULTIBYTE (elt));
13853
13854 break;
13855 }
13856
5f5c8ee5
GM
13857 while ((precision <= 0 || n < precision)
13858 && *this
13859 && (frame_title_ptr
fec8f23e 13860 || !NILP (mode_line_string_list)
5f5c8ee5 13861 || it->current_x < it->last_visible_x))
a2889657 13862 {
50f80c2f 13863 const unsigned char *last = this;
5f5c8ee5
GM
13864
13865 /* Advance to end of string or next format specifier. */
a2889657
JB
13866 while ((c = *this++) != '\0' && c != '%')
13867 ;
2311178e 13868
a2889657
JB
13869 if (this - 1 != last)
13870 {
5f5c8ee5
GM
13871 /* Output to end of string or up to '%'. Field width
13872 is length of string. Don't output more than
13873 PRECISION allows us. */
d26b89b8 13874 --this;
eaaa65b0
GM
13875
13876 prec = chars_in_text (last, this - last);
5f5c8ee5
GM
13877 if (precision > 0 && prec > precision - n)
13878 prec = precision - n;
2311178e 13879
d39b6696 13880 if (frame_title_ptr)
d26b89b8 13881 n += store_frame_title (last, 0, prec);
fec8f23e
KS
13882 else if (!NILP (mode_line_string_list))
13883 {
13884 int bytepos = last - lisp_string;
13885 int charpos = string_byte_to_char (elt, bytepos);
13886 n += store_mode_line_string (NULL,
13887 Fsubstring (elt, make_number (charpos),
13888 make_number (charpos + prec)),
13889 0, 0, 0, Qnil);
13890 }
d39b6696 13891 else
eaaa65b0
GM
13892 {
13893 int bytepos = last - lisp_string;
13894 int charpos = string_byte_to_char (elt, bytepos);
13895 n += display_string (NULL, elt, Qnil, 0, charpos,
ca77144d
GM
13896 it, 0, prec, 0,
13897 STRING_MULTIBYTE (elt));
eaaa65b0 13898 }
a2889657
JB
13899 }
13900 else /* c == '%' */
13901 {
50f80c2f 13902 const unsigned char *percent_position = this;
2311178e 13903
5f5c8ee5
GM
13904 /* Get the specified minimum width. Zero means
13905 don't pad. */
13906 field = 0;
a2889657 13907 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 13908 field = field * 10 + c - '0';
a2889657 13909
5f5c8ee5
GM
13910 /* Don't pad beyond the total padding allowed. */
13911 if (field_width - n > 0 && field > field_width - n)
13912 field = field_width - n;
a2889657 13913
5f5c8ee5
GM
13914 /* Note that either PRECISION <= 0 or N < PRECISION. */
13915 prec = precision - n;
2311178e 13916
a2889657 13917 if (c == 'M')
5f5c8ee5 13918 n += display_mode_element (it, depth, field, prec,
c53a1624
RS
13919 Vglobal_mode_string, props,
13920 risky);
a2889657 13921 else if (c != 0)
d39b6696 13922 {
72f62cb5 13923 int multibyte;
ae02e06a
RS
13924 int bytepos, charpos;
13925 unsigned char *spec;
2311178e 13926
ae02e06a
RS
13927 bytepos = percent_position - lisp_string;
13928 charpos = (STRING_MULTIBYTE (elt)
13929 ? string_byte_to_char (elt, bytepos)
13930 : bytepos);
13931
13932 spec
72f62cb5
GM
13933 = decode_mode_spec (it->w, c, field, prec, &multibyte);
13934
d39b6696 13935 if (frame_title_ptr)
5f5c8ee5 13936 n += store_frame_title (spec, field, prec);
fec8f23e
KS
13937 else if (!NILP (mode_line_string_list))
13938 {
13939 int len = strlen (spec);
13940 Lisp_Object tem = make_string (spec, len);
13941 props = Ftext_properties_at (make_number (charpos), elt);
13942 /* Should only keep face property in props */
13943 n += store_mode_line_string (NULL, tem, 0, field, prec, props);
13944 }
d39b6696 13945 else
5f5c8ee5 13946 {
ae02e06a 13947 int nglyphs_before, nwritten;
2311178e 13948
72f62cb5 13949 nglyphs_before = it->glyph_row->used[TEXT_AREA];
72f62cb5
GM
13950 nwritten = display_string (spec, Qnil, elt,
13951 charpos, 0, it,
13952 field, prec, 0,
13953 multibyte);
5f5c8ee5
GM
13954
13955 /* Assign to the glyphs written above the
13956 string where the `%x' came from, position
13957 of the `%'. */
13958 if (nwritten > 0)
13959 {
13960 struct glyph *glyph
13961 = (it->glyph_row->glyphs[TEXT_AREA]
13962 + nglyphs_before);
13963 int i;
13964
13965 for (i = 0; i < nwritten; ++i)
13966 {
13967 glyph[i].object = elt;
13968 glyph[i].charpos = charpos;
13969 }
2311178e 13970
5f5c8ee5
GM
13971 n += nwritten;
13972 }
13973 }
d39b6696 13974 }
b8523839
AS
13975 else /* c == 0 */
13976 break;
a2889657
JB
13977 }
13978 }
13979 }
13980 break;
13981
13982 case Lisp_Symbol:
13983 /* A symbol: process the value of the symbol recursively
13984 as if it appeared here directly. Avoid error if symbol void.
13985 Special case: if value of symbol is a string, output the string
13986 literally. */
13987 {
13988 register Lisp_Object tem;
c53a1624
RS
13989
13990 /* If the variable is not marked as risky to set
13991 then its contents are risky to use. */
13992 if (NILP (Fget (elt, Qrisky_local_variable)))
13993 risky = 1;
13994
a2889657 13995 tem = Fboundp (elt);
265a9e55 13996 if (!NILP (tem))
a2889657
JB
13997 {
13998 tem = Fsymbol_value (elt);
13999 /* If value is a string, output that string literally:
14000 don't check for % within it. */
e24c997d 14001 if (STRINGP (tem))
0fcf414f
RS
14002 literal = 1;
14003
14004 if (!EQ (tem, elt))
5f5c8ee5
GM
14005 {
14006 /* Give up right away for nil or t. */
14007 elt = tem;
14008 goto tail_recurse;
14009 }
a2889657
JB
14010 }
14011 }
14012 break;
14013
14014 case Lisp_Cons:
14015 {
14016 register Lisp_Object car, tem;
14017
0fcf414f
RS
14018 /* A cons cell: five distinct cases.
14019 If first element is :eval or :propertize, do something special.
a2889657
JB
14020 If first element is a string or a cons, process all the elements
14021 and effectively concatenate them.
14022 If first element is a negative number, truncate displaying cdr to
14023 at most that many characters. If positive, pad (with spaces)
14024 to at least that many characters.
14025 If first element is a symbol, process the cadr or caddr recursively
14026 according to whether the symbol's value is non-nil or nil. */
9472f927 14027 car = XCAR (elt);
0fcf414f 14028 if (EQ (car, QCeval))
5f5c8ee5
GM
14029 {
14030 /* An element of the form (:eval FORM) means evaluate FORM
14031 and use the result as mode line elements. */
0fcf414f 14032
c53a1624
RS
14033 if (risky)
14034 break;
14035
0fcf414f
RS
14036 if (CONSP (XCDR (elt)))
14037 {
14038 Lisp_Object spec;
14039 spec = safe_eval (XCAR (XCDR (elt)));
14040 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
14041 precision - n, spec, props,
14042 risky);
0fcf414f
RS
14043 }
14044 }
14045 else if (EQ (car, QCpropertize))
14046 {
c53a1624
RS
14047 /* An element of the form (:propertize ELT PROPS...)
14048 means display ELT but applying properties PROPS. */
14049
14050 if (risky)
14051 break;
14052
0fcf414f 14053 if (CONSP (XCDR (elt)))
c53a1624
RS
14054 n += display_mode_element (it, depth, field_width - n,
14055 precision - n, XCAR (XCDR (elt)),
14056 XCDR (XCDR (elt)), risky);
5f5c8ee5
GM
14057 }
14058 else if (SYMBOLP (car))
a2889657
JB
14059 {
14060 tem = Fboundp (car);
9472f927 14061 elt = XCDR (elt);
e24c997d 14062 if (!CONSP (elt))
a2889657
JB
14063 goto invalid;
14064 /* elt is now the cdr, and we know it is a cons cell.
14065 Use its car if CAR has a non-nil value. */
265a9e55 14066 if (!NILP (tem))
a2889657
JB
14067 {
14068 tem = Fsymbol_value (car);
265a9e55 14069 if (!NILP (tem))
9472f927
GM
14070 {
14071 elt = XCAR (elt);
14072 goto tail_recurse;
14073 }
a2889657
JB
14074 }
14075 /* Symbol's value is nil (or symbol is unbound)
14076 Get the cddr of the original list
14077 and if possible find the caddr and use that. */
9472f927 14078 elt = XCDR (elt);
265a9e55 14079 if (NILP (elt))
a2889657 14080 break;
e24c997d 14081 else if (!CONSP (elt))
a2889657 14082 goto invalid;
9472f927 14083 elt = XCAR (elt);
a2889657
JB
14084 goto tail_recurse;
14085 }
e24c997d 14086 else if (INTEGERP (car))
a2889657
JB
14087 {
14088 register int lim = XINT (car);
9472f927 14089 elt = XCDR (elt);
a2889657 14090 if (lim < 0)
5f5c8ee5
GM
14091 {
14092 /* Negative int means reduce maximum width. */
14093 if (precision <= 0)
14094 precision = -lim;
14095 else
14096 precision = min (precision, -lim);
14097 }
a2889657
JB
14098 else if (lim > 0)
14099 {
14100 /* Padding specified. Don't let it be more than
14101 current maximum. */
5f5c8ee5
GM
14102 if (precision > 0)
14103 lim = min (precision, lim);
14104
a2889657
JB
14105 /* If that's more padding than already wanted, queue it.
14106 But don't reduce padding already specified even if
14107 that is beyond the current truncation point. */
5f5c8ee5 14108 field_width = max (lim, field_width);
a2889657
JB
14109 }
14110 goto tail_recurse;
14111 }
e24c997d 14112 else if (STRINGP (car) || CONSP (car))
a2889657
JB
14113 {
14114 register int limit = 50;
5f5c8ee5
GM
14115 /* Limit is to protect against circular lists. */
14116 while (CONSP (elt)
14117 && --limit > 0
14118 && (precision <= 0 || n < precision))
a2889657 14119 {
5f5c8ee5 14120 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
14121 precision - n, XCAR (elt),
14122 props, risky);
9472f927 14123 elt = XCDR (elt);
a2889657
JB
14124 }
14125 }
14126 }
14127 break;
14128
14129 default:
14130 invalid:
d39b6696 14131 if (frame_title_ptr)
5f5c8ee5 14132 n += store_frame_title ("*invalid*", 0, precision - n);
fec8f23e
KS
14133 else if (!NILP (mode_line_string_list))
14134 n += store_mode_line_string ("*invalid*", Qnil, 0, 0, precision - n, Qnil);
d39b6696 14135 else
5f5c8ee5
GM
14136 n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
14137 precision - n, 0, 0);
14138 return n;
a2889657
JB
14139 }
14140
5f5c8ee5
GM
14141 /* Pad to FIELD_WIDTH. */
14142 if (field_width > 0 && n < field_width)
14143 {
14144 if (frame_title_ptr)
14145 n += store_frame_title ("", field_width - n, 0);
fec8f23e
KS
14146 else if (!NILP (mode_line_string_list))
14147 n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
5f5c8ee5
GM
14148 else
14149 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
14150 0, 0, 0);
14151 }
2311178e 14152
5f5c8ee5 14153 return n;
a2889657 14154}
5f5c8ee5 14155
fec8f23e
KS
14156/* Store a mode-line string element in mode_line_string_list.
14157
14158 If STRING is non-null, display that C string. Otherwise, the Lisp
14159 string LISP_STRING is displayed.
14160
14161 FIELD_WIDTH is the minimum number of output glyphs to produce.
14162 If STRING has fewer characters than FIELD_WIDTH, pad to the right
14163 with spaces. FIELD_WIDTH <= 0 means don't pad.
14164
14165 PRECISION is the maximum number of characters to output from
14166 STRING. PRECISION <= 0 means don't truncate the string.
14167
14168 If COPY_STRING is non-zero, make a copy of LISP_STRING before adding
14169 properties to the string.
14170
7d0393cf 14171 PROPS are the properties to add to the string.
fec8f23e
KS
14172 The mode_line_string_face face property is always added to the string.
14173 */
14174
14175static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
14176 char *string;
14177 Lisp_Object lisp_string;
14178 int copy_string;
14179 int field_width;
14180 int precision;
14181 Lisp_Object props;
14182{
14183 int len;
14184 int n = 0;
14185
14186 if (string != NULL)
14187 {
14188 len = strlen (string);
14189 if (precision > 0 && len > precision)
14190 len = precision;
14191 lisp_string = make_string (string, len);
14192 if (NILP (props))
14193 props = mode_line_string_face_prop;
14194 else if (!NILP (mode_line_string_face))
14195 {
14196 Lisp_Object face = Fplist_get (props, Qface);
14197 props = Fcopy_sequence (props);
14198 if (NILP (face))
14199 face = mode_line_string_face;
14200 else
14201 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
14202 props = Fplist_put (props, Qface, face);
14203 }
14204 Fadd_text_properties (make_number (0), make_number (len),
14205 props, lisp_string);
14206 }
7d0393cf 14207 else
fec8f23e 14208 {
c8224325 14209 len = XFASTINT (Flength (lisp_string));
fec8f23e
KS
14210 if (precision > 0 && len > precision)
14211 {
14212 len = precision;
14213 lisp_string = Fsubstring (lisp_string, make_number (0), make_number (len));
14214 precision = -1;
14215 }
14216 if (!NILP (mode_line_string_face))
14217 {
14218 Lisp_Object face;
14219 if (NILP (props))
14220 props = Ftext_properties_at (make_number (0), lisp_string);
14221 face = Fplist_get (props, Qface);
14222 if (NILP (face))
14223 face = mode_line_string_face;
14224 else
14225 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
14226 props = Fcons (Qface, Fcons (face, Qnil));
14227 if (copy_string)
14228 lisp_string = Fcopy_sequence (lisp_string);
14229 }
14230 if (!NILP (props))
14231 Fadd_text_properties (make_number (0), make_number (len),
14232 props, lisp_string);
14233 }
14234
14235 if (len > 0)
14236 {
14237 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 14238 n += len;
fec8f23e
KS
14239 }
14240
14241 if (field_width > len)
14242 {
14243 field_width -= len;
14244 lisp_string = Fmake_string (make_number (field_width), make_number (' '));
14245 if (!NILP (props))
14246 Fadd_text_properties (make_number (0), make_number (field_width),
14247 props, lisp_string);
14248 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 14249 n += field_width;
fec8f23e
KS
14250 }
14251
14252 return n;
14253}
14254
5f5c8ee5 14255
8143e6ab 14256DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
fec8f23e 14257 0, 3, 0,
8143e6ab
KS
14258 doc: /* Return the mode-line of selected window as a string.
14259First optional arg FORMAT specifies a different format string (see
8b22c65a 14260`mode-line-format' for details) to use. If FORMAT is t, return
8143e6ab 14261the buffer's header-line. Second optional arg WINDOW specifies a
fec8f23e
KS
14262different window to use as the context for the formatting.
14263If third optional arg NO-PROPS is non-nil, string is not propertized. */)
14264 (format, window, no_props)
14265 Lisp_Object format, window, no_props;
8143e6ab
KS
14266{
14267 struct it it;
8143e6ab
KS
14268 int len;
14269 struct window *w;
14270 struct buffer *old_buffer = NULL;
fec8f23e 14271 enum face_id face_id = DEFAULT_FACE_ID;
8143e6ab
KS
14272
14273 if (NILP (window))
14274 window = selected_window;
14275 CHECK_WINDOW (window);
14276 w = XWINDOW (window);
14277 CHECK_BUFFER (w->buffer);
14278
14279 if (XBUFFER (w->buffer) != current_buffer)
14280 {
14281 old_buffer = current_buffer;
14282 set_buffer_internal_1 (XBUFFER (w->buffer));
14283 }
14284
14285 if (NILP (format) || EQ (format, Qt))
fec8f23e
KS
14286 {
14287 face_id = NILP (format)
14288 ? CURRENT_MODE_LINE_FACE_ID (w) :
14289 HEADER_LINE_FACE_ID;
14290 format = NILP (format)
14291 ? current_buffer->mode_line_format
14292 : current_buffer->header_line_format;
14293 }
14294
14295 init_iterator (&it, w, -1, -1, NULL, face_id);
8143e6ab 14296
fec8f23e
KS
14297 if (NILP (no_props))
14298 {
14299 mode_line_string_face =
14300 (face_id == MODE_LINE_FACE_ID ? Qmode_line :
14301 face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
14302 face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
8143e6ab 14303
fec8f23e
KS
14304 mode_line_string_face_prop =
14305 NILP (mode_line_string_face) ? Qnil :
14306 Fcons (Qface, Fcons (mode_line_string_face, Qnil));
14307
14308 /* We need a dummy last element in mode_line_string_list to
14309 indicate we are building the propertized mode-line string.
14310 Using mode_line_string_face_prop here GC protects it. */
7d0393cf 14311 mode_line_string_list =
fec8f23e
KS
14312 Fcons (mode_line_string_face_prop, Qnil);
14313 frame_title_ptr = NULL;
14314 }
14315 else
14316 {
14317 mode_line_string_face_prop = Qnil;
14318 mode_line_string_list = Qnil;
14319 frame_title_ptr = frame_title_buf;
14320 }
8143e6ab
KS
14321
14322 push_frame_kboard (it.f);
14323 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
14324 pop_frame_kboard ();
14325
14326 if (old_buffer)
14327 set_buffer_internal_1 (old_buffer);
14328
fec8f23e
KS
14329 if (NILP (no_props))
14330 {
14331 Lisp_Object str;
14332 mode_line_string_list = Fnreverse (mode_line_string_list);
14333 str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list),
14334 make_string ("", 0));
14335 mode_line_string_face_prop = Qnil;
14336 mode_line_string_list = Qnil;
14337 return str;
14338 }
14339
8143e6ab
KS
14340 len = frame_title_ptr - frame_title_buf;
14341 if (len > 0 && frame_title_ptr[-1] == '-')
14342 {
14343 /* Mode lines typically ends with numerous dashes; reduce to two dashes. */
14344 while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-')
14345 ;
14346 frame_title_ptr += 3; /* restore last non-dash + two dashes */
14347 if (len > frame_title_ptr - frame_title_buf)
14348 len = frame_title_ptr - frame_title_buf;
14349 }
14350
14351 frame_title_ptr = NULL;
14352 return make_string (frame_title_buf, len);
14353}
14354
766525bc
RS
14355/* Write a null-terminated, right justified decimal representation of
14356 the positive integer D to BUF using a minimal field width WIDTH. */
14357
14358static void
14359pint2str (buf, width, d)
14360 register char *buf;
14361 register int width;
14362 register int d;
14363{
14364 register char *p = buf;
2311178e 14365
766525bc 14366 if (d <= 0)
5f5c8ee5 14367 *p++ = '0';
766525bc 14368 else
5f5c8ee5 14369 {
766525bc 14370 while (d > 0)
5f5c8ee5 14371 {
766525bc
RS
14372 *p++ = d % 10 + '0';
14373 d /= 10;
5f5c8ee5
GM
14374 }
14375 }
2311178e 14376
5f5c8ee5
GM
14377 for (width -= (int) (p - buf); width > 0; --width)
14378 *p++ = ' ';
766525bc
RS
14379 *p-- = '\0';
14380 while (p > buf)
5f5c8ee5 14381 {
766525bc
RS
14382 d = *buf;
14383 *buf++ = *p;
14384 *p-- = d;
5f5c8ee5 14385 }
766525bc
RS
14386}
14387
5f5c8ee5 14388/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
14389 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
14390 type of CODING_SYSTEM. Return updated pointer into BUF. */
14391
6693a99a 14392static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 14393
1c9241f5
KH
14394static char *
14395decode_mode_spec_coding (coding_system, buf, eol_flag)
14396 Lisp_Object coding_system;
14397 register char *buf;
14398 int eol_flag;
14399{
1e1078d6 14400 Lisp_Object val;
916848d8 14401 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
50f80c2f 14402 const unsigned char *eol_str;
302f2b38
EZ
14403 int eol_str_len;
14404 /* The EOL conversion we are using. */
14405 Lisp_Object eoltype;
1e1078d6 14406
4a09dee0 14407 val = Fget (coding_system, Qcoding_system);
085536c2 14408 eoltype = Qnil;
1c9241f5 14409
4a09dee0 14410 if (!VECTORP (val)) /* Not yet decided. */
1c9241f5 14411 {
916848d8
RS
14412 if (multibyte)
14413 *buf++ = '-';
21e989e3 14414 if (eol_flag)
302f2b38 14415 eoltype = eol_mnemonic_undecided;
1e1078d6 14416 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
14417 }
14418 else
14419 {
1e1078d6
RS
14420 Lisp_Object eolvalue;
14421
14422 eolvalue = Fget (coding_system, Qeol_type);
14423
916848d8 14424 if (multibyte)
a61b7058 14425 *buf++ = XFASTINT (AREF (val, 1));
916848d8 14426
1c9241f5
KH
14427 if (eol_flag)
14428 {
1e1078d6
RS
14429 /* The EOL conversion that is normal on this system. */
14430
14431 if (NILP (eolvalue)) /* Not yet decided. */
14432 eoltype = eol_mnemonic_undecided;
14433 else if (VECTORP (eolvalue)) /* Not yet decided. */
14434 eoltype = eol_mnemonic_undecided;
14435 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
14436 eoltype = (XFASTINT (eolvalue) == 0
14437 ? eol_mnemonic_unix
14438 : (XFASTINT (eolvalue) == 1
14439 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
14440 }
14441 }
2311178e 14442
302f2b38
EZ
14443 if (eol_flag)
14444 {
14445 /* Mention the EOL conversion if it is not the usual one. */
14446 if (STRINGP (eoltype))
14447 {
2051c264
GM
14448 eol_str = SDATA (eoltype);
14449 eol_str_len = SBYTES (eoltype);
302f2b38 14450 }
f30b3499
KH
14451 else if (INTEGERP (eoltype)
14452 && CHAR_VALID_P (XINT (eoltype), 0))
14453 {
50f80c2f
KR
14454 unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
14455 eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
14456 eol_str = tmp;
f30b3499 14457 }
302f2b38
EZ
14458 else
14459 {
14460 eol_str = invalid_eol_type;
14461 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 14462 }
f30b3499 14463 bcopy (eol_str, buf, eol_str_len);
302f2b38 14464 buf += eol_str_len;
1c9241f5 14465 }
302f2b38 14466
1c9241f5
KH
14467 return buf;
14468}
14469
a2889657 14470/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
14471 generated by character C. PRECISION >= 0 means don't return a
14472 string longer than that value. FIELD_WIDTH > 0 means pad the
72f62cb5
GM
14473 string returned with spaces to that value. Return 1 in *MULTIBYTE
14474 if the result is multibyte text. */
a2889657 14475
11e82b76
JB
14476static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
14477
a2889657 14478static char *
72f62cb5 14479decode_mode_spec (w, c, field_width, precision, multibyte)
a2889657 14480 struct window *w;
68c45bf0 14481 register int c;
5f5c8ee5 14482 int field_width, precision;
72f62cb5 14483 int *multibyte;
a2889657 14484{
0b67772d 14485 Lisp_Object obj;
5f5c8ee5
GM
14486 struct frame *f = XFRAME (WINDOW_FRAME (w));
14487 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 14488 struct buffer *b = XBUFFER (w->buffer);
a2889657 14489
0b67772d 14490 obj = Qnil;
72f62cb5 14491 *multibyte = 0;
a2889657
JB
14492
14493 switch (c)
14494 {
1af9f229
RS
14495 case '*':
14496 if (!NILP (b->read_only))
14497 return "%";
14498 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
14499 return "*";
14500 return "-";
14501
14502 case '+':
14503 /* This differs from %* only for a modified read-only buffer. */
14504 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
14505 return "*";
14506 if (!NILP (b->read_only))
14507 return "%";
14508 return "-";
14509
14510 case '&':
14511 /* This differs from %* in ignoring read-only-ness. */
14512 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
14513 return "*";
14514 return "-";
14515
14516 case '%':
14517 return "%";
14518
2311178e 14519 case '[':
1af9f229
RS
14520 {
14521 int i;
14522 char *p;
14523
14524 if (command_loop_level > 5)
14525 return "[[[... ";
14526 p = decode_mode_spec_buf;
14527 for (i = 0; i < command_loop_level; i++)
14528 *p++ = '[';
14529 *p = 0;
14530 return decode_mode_spec_buf;
14531 }
14532
2311178e 14533 case ']':
1af9f229
RS
14534 {
14535 int i;
14536 char *p;
14537
14538 if (command_loop_level > 5)
14539 return " ...]]]";
14540 p = decode_mode_spec_buf;
14541 for (i = 0; i < command_loop_level; i++)
14542 *p++ = ']';
14543 *p = 0;
14544 return decode_mode_spec_buf;
14545 }
14546
14547 case '-':
14548 {
1af9f229 14549 register int i;
5f5c8ee5
GM
14550
14551 /* Let lots_of_dashes be a string of infinite length. */
fec8f23e
KS
14552 if (!NILP (mode_line_string_list))
14553 return "--";
5f5c8ee5
GM
14554 if (field_width <= 0
14555 || field_width > sizeof (lots_of_dashes))
1af9f229 14556 {
5f5c8ee5
GM
14557 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
14558 decode_mode_spec_buf[i] = '-';
14559 decode_mode_spec_buf[i] = '\0';
14560 return decode_mode_spec_buf;
1af9f229 14561 }
5f5c8ee5
GM
14562 else
14563 return lots_of_dashes;
1af9f229
RS
14564 }
14565
2311178e 14566 case 'b':
d39b6696 14567 obj = b->name;
a2889657
JB
14568 break;
14569
1af9f229
RS
14570 case 'c':
14571 {
2311178e 14572 int col = (int) current_column (); /* iftc */
ac90c44f 14573 w->column_number_displayed = make_number (col);
5f5c8ee5 14574 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
14575 return decode_mode_spec_buf;
14576 }
14577
14578 case 'F':
14579 /* %F displays the frame name. */
5f5c8ee5 14580 if (!NILP (f->title))
2051c264 14581 return (char *) SDATA (f->title);
fd8ff63d 14582 if (f->explicit_name || ! FRAME_WINDOW_P (f))
2051c264 14583 return (char *) SDATA (f->name);
9c6da96f 14584 return "Emacs";
1af9f229 14585
2311178e 14586 case 'f':
d39b6696 14587 obj = b->filename;
a2889657
JB
14588 break;
14589
aa6d10fa
RS
14590 case 'l':
14591 {
12adba34
RS
14592 int startpos = XMARKER (w->start)->charpos;
14593 int startpos_byte = marker_byte_position (w->start);
14594 int line, linepos, linepos_byte, topline;
aa6d10fa 14595 int nlines, junk;
aa6d10fa
RS
14596 int height = XFASTINT (w->height);
14597
2311178e 14598 /* If we decided that this buffer isn't suitable for line numbers,
aa6d10fa
RS
14599 don't forget that too fast. */
14600 if (EQ (w->base_line_pos, w->buffer))
766525bc 14601 goto no_value;
5300fd39
RS
14602 /* But do forget it, if the window shows a different buffer now. */
14603 else if (BUFFERP (w->base_line_pos))
14604 w->base_line_pos = Qnil;
aa6d10fa
RS
14605
14606 /* If the buffer is very big, don't waste time. */
37d034d3 14607 if (INTEGERP (Vline_number_display_limit)
090703f4 14608 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
aa6d10fa
RS
14609 {
14610 w->base_line_pos = Qnil;
14611 w->base_line_number = Qnil;
766525bc 14612 goto no_value;
aa6d10fa
RS
14613 }
14614
14615 if (!NILP (w->base_line_number)
14616 && !NILP (w->base_line_pos)
12adba34 14617 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
14618 {
14619 line = XFASTINT (w->base_line_number);
14620 linepos = XFASTINT (w->base_line_pos);
12adba34 14621 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
14622 }
14623 else
14624 {
14625 line = 1;
d39b6696 14626 linepos = BUF_BEGV (b);
12adba34 14627 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
14628 }
14629
14630 /* Count lines from base line to window start position. */
12adba34
RS
14631 nlines = display_count_lines (linepos, linepos_byte,
14632 startpos_byte,
14633 startpos, &junk);
aa6d10fa
RS
14634
14635 topline = nlines + line;
14636
14637 /* Determine a new base line, if the old one is too close
14638 or too far away, or if we did not have one.
14639 "Too close" means it's plausible a scroll-down would
14640 go back past it. */
d39b6696 14641 if (startpos == BUF_BEGV (b))
aa6d10fa 14642 {
ac90c44f
GM
14643 w->base_line_number = make_number (topline);
14644 w->base_line_pos = make_number (BUF_BEGV (b));
aa6d10fa
RS
14645 }
14646 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 14647 || linepos == BUF_BEGV (b))
aa6d10fa 14648 {
d39b6696 14649 int limit = BUF_BEGV (b);
12adba34 14650 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 14651 int position;
5d121aec 14652 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
14653
14654 if (startpos - distance > limit)
12adba34
RS
14655 {
14656 limit = startpos - distance;
14657 limit_byte = CHAR_TO_BYTE (limit);
14658 }
aa6d10fa 14659
12adba34
RS
14660 nlines = display_count_lines (startpos, startpos_byte,
14661 limit_byte,
14662 - (height * 2 + 30),
aa6d10fa 14663 &position);
2311178e 14664 /* If we couldn't find the lines we wanted within
5d121aec 14665 line_number_display_limit_width chars per line,
aa6d10fa 14666 give up on line numbers for this window. */
12adba34 14667 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
14668 {
14669 w->base_line_pos = w->buffer;
14670 w->base_line_number = Qnil;
766525bc 14671 goto no_value;
aa6d10fa
RS
14672 }
14673
ac90c44f
GM
14674 w->base_line_number = make_number (topline - nlines);
14675 w->base_line_pos = make_number (BYTE_TO_CHAR (position));
aa6d10fa
RS
14676 }
14677
14678 /* Now count lines from the start pos to point. */
12adba34
RS
14679 nlines = display_count_lines (startpos, startpos_byte,
14680 PT_BYTE, PT, &junk);
aa6d10fa
RS
14681
14682 /* Record that we did display the line number. */
14683 line_number_displayed = 1;
14684
14685 /* Make the string to show. */
5f5c8ee5 14686 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 14687 return decode_mode_spec_buf;
766525bc
RS
14688 no_value:
14689 {
14690 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
14691 int pad = field_width - 2;
14692 while (pad-- > 0)
14693 *p++ = ' ';
14694 *p++ = '?';
b357b9d4
KR
14695 *p++ = '?';
14696 *p = '\0';
766525bc
RS
14697 return decode_mode_spec_buf;
14698 }
aa6d10fa
RS
14699 }
14700 break;
14701
2311178e 14702 case 'm':
d39b6696 14703 obj = b->mode_name;
a2889657
JB
14704 break;
14705
14706 case 'n':
d39b6696 14707 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
14708 return " Narrow";
14709 break;
14710
a2889657
JB
14711 case 'p':
14712 {
14713 int pos = marker_position (w->start);
d39b6696 14714 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 14715
d39b6696 14716 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 14717 {
d39b6696 14718 if (pos <= BUF_BEGV (b))
a2889657
JB
14719 return "All";
14720 else
14721 return "Bottom";
14722 }
d39b6696 14723 else if (pos <= BUF_BEGV (b))
a2889657
JB
14724 return "Top";
14725 else
14726 {
3c7d31b9
RS
14727 if (total > 1000000)
14728 /* Do it differently for a large value, to avoid overflow. */
14729 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
14730 else
14731 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
14732 /* We can't normally display a 3-digit number,
14733 so get us a 2-digit number that is close. */
14734 if (total == 100)
14735 total = 99;
14736 sprintf (decode_mode_spec_buf, "%2d%%", total);
14737 return decode_mode_spec_buf;
14738 }
14739 }
14740
8ffcb79f
RS
14741 /* Display percentage of size above the bottom of the screen. */
14742 case 'P':
14743 {
14744 int toppos = marker_position (w->start);
d39b6696
KH
14745 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
14746 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 14747
d39b6696 14748 if (botpos >= BUF_ZV (b))
8ffcb79f 14749 {
d39b6696 14750 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
14751 return "All";
14752 else
14753 return "Bottom";
14754 }
14755 else
14756 {
3c7d31b9
RS
14757 if (total > 1000000)
14758 /* Do it differently for a large value, to avoid overflow. */
14759 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
14760 else
14761 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
14762 /* We can't normally display a 3-digit number,
14763 so get us a 2-digit number that is close. */
14764 if (total == 100)
14765 total = 99;
d39b6696 14766 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
14767 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
14768 else
14769 sprintf (decode_mode_spec_buf, "%2d%%", total);
14770 return decode_mode_spec_buf;
14771 }
14772 }
14773
1af9f229
RS
14774 case 's':
14775 /* status of process */
14776 obj = Fget_buffer_process (w->buffer);
14777 if (NILP (obj))
14778 return "no process";
14779#ifdef subprocesses
14780 obj = Fsymbol_name (Fprocess_status (obj));
14781#endif
14782 break;
d39b6696 14783
1af9f229
RS
14784 case 't': /* indicate TEXT or BINARY */
14785#ifdef MODE_LINE_BINARY_TEXT
14786 return MODE_LINE_BINARY_TEXT (b);
14787#else
14788 return "T";
14789#endif
1c9241f5
KH
14790
14791 case 'z':
14792 /* coding-system (not including end-of-line format) */
14793 case 'Z':
14794 /* coding-system (including end-of-line type) */
14795 {
14796 int eol_flag = (c == 'Z');
539b4d41 14797 char *p = decode_mode_spec_buf;
1c9241f5 14798
d30e754b 14799 if (! FRAME_WINDOW_P (f))
1c9241f5 14800 {
11c52c4f
RS
14801 /* No need to mention EOL here--the terminal never needs
14802 to do EOL conversion. */
14803 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
14804 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 14805 }
f13c925f 14806 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 14807 p, eol_flag);
f13c925f 14808
11c52c4f 14809#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
14810#ifdef subprocesses
14811 obj = Fget_buffer_process (Fcurrent_buffer ());
14812 if (PROCESSP (obj))
14813 {
14814 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
14815 p, eol_flag);
14816 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
14817 p, eol_flag);
14818 }
14819#endif /* subprocesses */
11c52c4f 14820#endif /* 0 */
1c9241f5
KH
14821 *p = 0;
14822 return decode_mode_spec_buf;
14823 }
a2889657 14824 }
d39b6696 14825
e24c997d 14826 if (STRINGP (obj))
72f62cb5
GM
14827 {
14828 *multibyte = STRING_MULTIBYTE (obj);
2051c264 14829 return (char *) SDATA (obj);
72f62cb5 14830 }
a2889657
JB
14831 else
14832 return "";
14833}
5f5c8ee5
GM
14834
14835
12adba34
RS
14836/* Count up to COUNT lines starting from START / START_BYTE.
14837 But don't go beyond LIMIT_BYTE.
14838 Return the number of lines thus found (always nonnegative).
59b49f63 14839
12adba34 14840 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
14841
14842static int
12adba34
RS
14843display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
14844 int start, start_byte, limit_byte, count;
14845 int *byte_pos_ptr;
59b49f63 14846{
59b49f63
RS
14847 register unsigned char *cursor;
14848 unsigned char *base;
14849
14850 register int ceiling;
14851 register unsigned char *ceiling_addr;
12adba34 14852 int orig_count = count;
59b49f63
RS
14853
14854 /* If we are not in selective display mode,
14855 check only for newlines. */
12adba34
RS
14856 int selective_display = (!NILP (current_buffer->selective_display)
14857 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
14858
14859 if (count > 0)
12adba34
RS
14860 {
14861 while (start_byte < limit_byte)
14862 {
14863 ceiling = BUFFER_CEILING_OF (start_byte);
14864 ceiling = min (limit_byte - 1, ceiling);
14865 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
14866 base = (cursor = BYTE_POS_ADDR (start_byte));
14867 while (1)
14868 {
14869 if (selective_display)
14870 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
14871 ;
14872 else
14873 while (*cursor != '\n' && ++cursor != ceiling_addr)
14874 ;
14875
14876 if (cursor != ceiling_addr)
14877 {
14878 if (--count == 0)
14879 {
14880 start_byte += cursor - base + 1;
14881 *byte_pos_ptr = start_byte;
14882 return orig_count;
14883 }
14884 else
14885 if (++cursor == ceiling_addr)
14886 break;
14887 }
14888 else
14889 break;
14890 }
14891 start_byte += cursor - base;
14892 }
14893 }
59b49f63
RS
14894 else
14895 {
12adba34
RS
14896 while (start_byte > limit_byte)
14897 {
14898 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
14899 ceiling = max (limit_byte, ceiling);
14900 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
14901 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
14902 while (1)
14903 {
12adba34
RS
14904 if (selective_display)
14905 while (--cursor != ceiling_addr
14906 && *cursor != '\n' && *cursor != 015)
14907 ;
14908 else
14909 while (--cursor != ceiling_addr && *cursor != '\n')
14910 ;
14911
59b49f63
RS
14912 if (cursor != ceiling_addr)
14913 {
14914 if (++count == 0)
14915 {
12adba34
RS
14916 start_byte += cursor - base + 1;
14917 *byte_pos_ptr = start_byte;
14918 /* When scanning backwards, we should
14919 not count the newline posterior to which we stop. */
14920 return - orig_count - 1;
59b49f63
RS
14921 }
14922 }
14923 else
14924 break;
14925 }
12adba34
RS
14926 /* Here we add 1 to compensate for the last decrement
14927 of CURSOR, which took it past the valid range. */
14928 start_byte += cursor - base + 1;
59b49f63
RS
14929 }
14930 }
14931
12adba34 14932 *byte_pos_ptr = limit_byte;
aa6d10fa 14933
12adba34
RS
14934 if (count < 0)
14935 return - orig_count + count;
14936 return orig_count - count;
aa6d10fa 14937
12adba34 14938}
a2889657 14939
a2889657 14940
5f5c8ee5
GM
14941\f
14942/***********************************************************************
14943 Displaying strings
14944 ***********************************************************************/
278feba9 14945
5f5c8ee5 14946/* Display a NUL-terminated string, starting with index START.
a3788d53 14947
5f5c8ee5
GM
14948 If STRING is non-null, display that C string. Otherwise, the Lisp
14949 string LISP_STRING is displayed.
a2889657 14950
5f5c8ee5
GM
14951 If FACE_STRING is not nil, FACE_STRING_POS is a position in
14952 FACE_STRING. Display STRING or LISP_STRING with the face at
14953 FACE_STRING_POS in FACE_STRING:
a2889657 14954
5f5c8ee5
GM
14955 Display the string in the environment given by IT, but use the
14956 standard display table, temporarily.
a3788d53 14957
5f5c8ee5
GM
14958 FIELD_WIDTH is the minimum number of output glyphs to produce.
14959 If STRING has fewer characters than FIELD_WIDTH, pad to the right
14960 with spaces. If STRING has more characters, more than FIELD_WIDTH
14961 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
2311178e 14962
5f5c8ee5
GM
14963 PRECISION is the maximum number of characters to output from
14964 STRING. PRECISION < 0 means don't truncate the string.
a2889657 14965
5f5c8ee5 14966 This is roughly equivalent to printf format specifiers:
a2889657 14967
5f5c8ee5
GM
14968 FIELD_WIDTH PRECISION PRINTF
14969 ----------------------------------------
14970 -1 -1 %s
14971 -1 10 %.10s
14972 10 -1 %10s
14973 20 10 %20.10s
a2889657 14974
5f5c8ee5
GM
14975 MULTIBYTE zero means do not display multibyte chars, > 0 means do
14976 display them, and < 0 means obey the current buffer's value of
14977 enable_multibyte_characters.
278feba9 14978
5f5c8ee5 14979 Value is the number of glyphs produced. */
b1d1124b 14980
5f5c8ee5
GM
14981static int
14982display_string (string, lisp_string, face_string, face_string_pos,
14983 start, it, field_width, precision, max_x, multibyte)
14984 unsigned char *string;
14985 Lisp_Object lisp_string;
68c45bf0
PE
14986 Lisp_Object face_string;
14987 int face_string_pos;
5f5c8ee5
GM
14988 int start;
14989 struct it *it;
14990 int field_width, precision, max_x;
14991 int multibyte;
14992{
14993 int hpos_at_start = it->hpos;
14994 int saved_face_id = it->face_id;
14995 struct glyph_row *row = it->glyph_row;
14996
14997 /* Initialize the iterator IT for iteration over STRING beginning
e719f5ae 14998 with index START. */
5f5c8ee5
GM
14999 reseat_to_string (it, string, lisp_string, start,
15000 precision, field_width, multibyte);
15001
15002 /* If displaying STRING, set up the face of the iterator
15003 from LISP_STRING, if that's given. */
15004 if (STRINGP (face_string))
15005 {
15006 int endptr;
15007 struct face *face;
2311178e 15008
5f5c8ee5
GM
15009 it->face_id
15010 = face_at_string_position (it->w, face_string, face_string_pos,
15011 0, it->region_beg_charpos,
15012 it->region_end_charpos,
5de7c6f2 15013 &endptr, it->base_face_id, 0);
5f5c8ee5
GM
15014 face = FACE_FROM_ID (it->f, it->face_id);
15015 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 15016 }
a2889657 15017
5f5c8ee5
GM
15018 /* Set max_x to the maximum allowed X position. Don't let it go
15019 beyond the right edge of the window. */
15020 if (max_x <= 0)
15021 max_x = it->last_visible_x;
15022 else
15023 max_x = min (max_x, it->last_visible_x);
efc63ef0 15024
5f5c8ee5
GM
15025 /* Skip over display elements that are not visible. because IT->w is
15026 hscrolled. */
15027 if (it->current_x < it->first_visible_x)
15028 move_it_in_display_line_to (it, 100000, it->first_visible_x,
15029 MOVE_TO_POS | MOVE_TO_X);
a2889657 15030
5f5c8ee5
GM
15031 row->ascent = it->max_ascent;
15032 row->height = it->max_ascent + it->max_descent;
312246d1
GM
15033 row->phys_ascent = it->max_phys_ascent;
15034 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 15035
5f5c8ee5
GM
15036 /* This condition is for the case that we are called with current_x
15037 past last_visible_x. */
15038 while (it->current_x < max_x)
a2889657 15039 {
5f5c8ee5 15040 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 15041
5f5c8ee5
GM
15042 /* Get the next display element. */
15043 if (!get_next_display_element (it))
90adcf20 15044 break;
1c9241f5 15045
5f5c8ee5
GM
15046 /* Produce glyphs. */
15047 x_before = it->current_x;
15048 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
15049 PRODUCE_GLYPHS (it);
90adcf20 15050
5f5c8ee5
GM
15051 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
15052 i = 0;
15053 x = x_before;
15054 while (i < nglyphs)
a2889657 15055 {
5f5c8ee5 15056 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 15057
5f5c8ee5
GM
15058 if (!it->truncate_lines_p
15059 && x + glyph->pixel_width > max_x)
15060 {
15061 /* End of continued line or max_x reached. */
37be86f2
KH
15062 if (CHAR_GLYPH_PADDING_P (*glyph))
15063 {
15064 /* A wide character is unbreakable. */
15065 it->glyph_row->used[TEXT_AREA] = n_glyphs_before;
15066 it->current_x = x_before;
15067 }
15068 else
15069 {
15070 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
15071 it->current_x = x;
15072 }
5f5c8ee5
GM
15073 break;
15074 }
15075 else if (x + glyph->pixel_width > it->first_visible_x)
15076 {
15077 /* Glyph is at least partially visible. */
15078 ++it->hpos;
15079 if (x < it->first_visible_x)
15080 it->glyph_row->x = x - it->first_visible_x;
15081 }
15082 else
a2889657 15083 {
5f5c8ee5
GM
15084 /* Glyph is off the left margin of the display area.
15085 Should not happen. */
15086 abort ();
a2889657 15087 }
5f5c8ee5
GM
15088
15089 row->ascent = max (row->ascent, it->max_ascent);
15090 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
15091 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
15092 row->phys_height = max (row->phys_height,
15093 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
15094 x += glyph->pixel_width;
15095 ++i;
a2889657 15096 }
5f5c8ee5
GM
15097
15098 /* Stop if max_x reached. */
15099 if (i < nglyphs)
15100 break;
15101
15102 /* Stop at line ends. */
15103 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 15104 {
5f5c8ee5
GM
15105 it->continuation_lines_width = 0;
15106 break;
a2889657 15107 }
1c9241f5 15108
cafafe0b 15109 set_iterator_to_next (it, 1);
a688bb24 15110
5f5c8ee5
GM
15111 /* Stop if truncating at the right edge. */
15112 if (it->truncate_lines_p
15113 && it->current_x >= it->last_visible_x)
15114 {
15115 /* Add truncation mark, but don't do it if the line is
15116 truncated at a padding space. */
15117 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 15118 {
5f5c8ee5 15119 if (!FRAME_WINDOW_P (it->f))
37be86f2
KH
15120 {
15121 int i, n;
15122
9299cb15 15123 if (it->current_x > it->last_visible_x)
37be86f2 15124 {
9299cb15
KH
15125 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
15126 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
15127 break;
15128 for (n = row->used[TEXT_AREA]; i < n; ++i)
15129 {
15130 row->used[TEXT_AREA] = i;
15131 produce_special_glyphs (it, IT_TRUNCATION);
15132 }
37be86f2 15133 }
9299cb15 15134 produce_special_glyphs (it, IT_TRUNCATION);
37be86f2 15135 }
5f5c8ee5 15136 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 15137 }
5f5c8ee5 15138 break;
1c9241f5 15139 }
a2889657
JB
15140 }
15141
5f5c8ee5
GM
15142 /* Maybe insert a truncation at the left. */
15143 if (it->first_visible_x
15144 && IT_CHARPOS (*it) > 0)
a2889657 15145 {
5f5c8ee5
GM
15146 if (!FRAME_WINDOW_P (it->f))
15147 insert_left_trunc_glyphs (it);
15148 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
15149 }
15150
5f5c8ee5 15151 it->face_id = saved_face_id;
2311178e 15152
5f5c8ee5
GM
15153 /* Value is number of columns displayed. */
15154 return it->hpos - hpos_at_start;
15155}
a2889657 15156
a2889657 15157
a2889657 15158\f
3b6b6db7 15159/* This is like a combination of memq and assq. Return 1/2 if PROPVAL
5f5c8ee5
GM
15160 appears as an element of LIST or as the car of an element of LIST.
15161 If PROPVAL is a list, compare each element against LIST in that
3b6b6db7
SM
15162 way, and return 1/2 if any element of PROPVAL is found in LIST.
15163 Otherwise return 0. This function cannot quit.
15164 The return value is 2 if the text is invisible but with an ellipsis
15165 and 1 if it's invisible and without an ellipsis. */
642eefc6
RS
15166
15167int
15168invisible_p (propval, list)
15169 register Lisp_Object propval;
15170 Lisp_Object list;
15171{
3b6b6db7 15172 register Lisp_Object tail, proptail;
2311178e 15173
3b6b6db7
SM
15174 for (tail = list; CONSP (tail); tail = XCDR (tail))
15175 {
15176 register Lisp_Object tem;
15177 tem = XCAR (tail);
15178 if (EQ (propval, tem))
15179 return 1;
15180 if (CONSP (tem) && EQ (propval, XCAR (tem)))
15181 return NILP (XCDR (tem)) ? 1 : 2;
15182 }
2311178e 15183
3b6b6db7
SM
15184 if (CONSP (propval))
15185 {
15186 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
15187 {
15188 Lisp_Object propelt;
15189 propelt = XCAR (proptail);
15190 for (tail = list; CONSP (tail); tail = XCDR (tail))
15191 {
15192 register Lisp_Object tem;
15193 tem = XCAR (tail);
15194 if (EQ (propelt, tem))
15195 return 1;
15196 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
15197 return NILP (XCDR (tem)) ? 1 : 2;
15198 }
15199 }
15200 }
2311178e 15201
3b6b6db7 15202 return 0;
642eefc6 15203}
5f5c8ee5 15204
642eefc6 15205\f
cfe03a41
KS
15206/***********************************************************************
15207 Cursor types
15208 ***********************************************************************/
15209
15210/* Value is the internal representation of the specified cursor type
15211 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
15212 of the bar cursor. */
15213
15214enum text_cursor_kinds
15215get_specified_cursor_type (arg, width)
15216 Lisp_Object arg;
15217 int *width;
15218{
15219 enum text_cursor_kinds type;
7d0393cf 15220
cfe03a41
KS
15221 if (NILP (arg))
15222 return NO_CURSOR;
15223
15224 if (EQ (arg, Qbox))
15225 return FILLED_BOX_CURSOR;
15226
15227 if (EQ (arg, Qhollow))
15228 return HOLLOW_BOX_CURSOR;
15229
15230 if (EQ (arg, Qbar))
15231 {
15232 *width = 2;
15233 return BAR_CURSOR;
15234 }
15235
15236 if (CONSP (arg)
15237 && EQ (XCAR (arg), Qbar)
15238 && INTEGERP (XCDR (arg))
15239 && XINT (XCDR (arg)) >= 0)
15240 {
15241 *width = XINT (XCDR (arg));
15242 return BAR_CURSOR;
15243 }
15244
15245 if (EQ (arg, Qhbar))
15246 {
15247 *width = 2;
15248 return HBAR_CURSOR;
15249 }
15250
15251 if (CONSP (arg)
15252 && EQ (XCAR (arg), Qhbar)
15253 && INTEGERP (XCDR (arg))
15254 && XINT (XCDR (arg)) >= 0)
15255 {
15256 *width = XINT (XCDR (arg));
15257 return HBAR_CURSOR;
15258 }
15259
15260 /* Treat anything unknown as "hollow box cursor".
15261 It was bad to signal an error; people have trouble fixing
15262 .Xdefaults with Emacs, when it has something bad in it. */
15263 type = HOLLOW_BOX_CURSOR;
15264
15265 return type;
15266}
15267
15268/* Set the default cursor types for specified frame. */
15269void
15270set_frame_cursor_types (f, arg)
15271 struct frame *f;
15272 Lisp_Object arg;
15273{
15274 int width;
15275 Lisp_Object tem;
15276
15277 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
15278 FRAME_CURSOR_WIDTH (f) = width;
15279
15280 /* By default, set up the blink-off state depending on the on-state. */
15281
15282 tem = Fassoc (arg, Vblink_cursor_alist);
15283 if (!NILP (tem))
15284 {
15285 FRAME_BLINK_OFF_CURSOR (f)
15286 = get_specified_cursor_type (XCDR (tem), &width);
15287 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
15288 }
15289 else
15290 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
15291}
15292
15293
e9c99027
KS
15294/* Return the cursor we want to be displayed in window W. Return
15295 width of bar/hbar cursor through WIDTH arg. Return with
15296 ACTIVE_CURSOR arg set to 1 if cursor in window W is `active'
15297 (i.e. if the `system caret' should track this cursor).
15298
15299 In a mini-buffer window, we want the cursor only to appear if we
15300 are reading input from this window. For the selected window, we
15301 want the cursor type given by the frame parameter or buffer local
15302 setting of cursor-type. If explicitly marked off, draw no cursor.
15303 In all other cases, we want a hollow box cursor. */
cfe03a41
KS
15304
15305enum text_cursor_kinds
e9c99027 15306get_window_cursor_type (w, width, active_cursor)
cfe03a41
KS
15307 struct window *w;
15308 int *width;
e9c99027 15309 int *active_cursor;
cfe03a41
KS
15310{
15311 struct frame *f = XFRAME (w->frame);
15312 struct buffer *b = XBUFFER (w->buffer);
15313 int cursor_type = DEFAULT_CURSOR;
15314 Lisp_Object alt_cursor;
15315 int non_selected = 0;
15316
e9c99027
KS
15317 *active_cursor = 1;
15318
cfe03a41
KS
15319 /* Echo area */
15320 if (cursor_in_echo_area
15321 && FRAME_HAS_MINIBUF_P (f)
15322 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
15323 {
15324 if (w == XWINDOW (echo_area_window))
15325 {
15326 *width = FRAME_CURSOR_WIDTH (f);
15327 return FRAME_DESIRED_CURSOR (f);
15328 }
15329
e9c99027 15330 *active_cursor = 0;
cfe03a41
KS
15331 non_selected = 1;
15332 }
15333
15334 /* Nonselected window or nonselected frame. */
97acc803
EZ
15335 else if (w != XWINDOW (f->selected_window)
15336#ifdef HAVE_WINDOW_SYSTEM
15337 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
15338#endif
15339 )
cfe03a41 15340 {
e9c99027
KS
15341 *active_cursor = 0;
15342
cfe03a41
KS
15343 if (MINI_WINDOW_P (w) && minibuf_level == 0)
15344 return NO_CURSOR;
15345
15346 non_selected = 1;
15347 }
15348
15349 /* Never display a cursor in a window in which cursor-type is nil. */
15350 if (NILP (b->cursor_type))
15351 return NO_CURSOR;
15352
15353 /* Use cursor-in-non-selected-windows for non-selected window or frame. */
15354 if (non_selected)
15355 {
15356 alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer);
15357 return get_specified_cursor_type (alt_cursor, width);
15358 }
15359
15360 /* Get the normal cursor type for this window. */
15361 if (EQ (b->cursor_type, Qt))
15362 {
15363 cursor_type = FRAME_DESIRED_CURSOR (f);
15364 *width = FRAME_CURSOR_WIDTH (f);
15365 }
15366 else
15367 cursor_type = get_specified_cursor_type (b->cursor_type, width);
15368
15369 /* Use normal cursor if not blinked off. */
15370 if (!w->cursor_off_p)
15371 return cursor_type;
15372
15373 /* Cursor is blinked off, so determine how to "toggle" it. */
15374
8420a5dd
KS
15375 /* First look for an entry matching the buffer's cursor-type in blink-cursor-alist. */
15376 if ((alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor)))
cfe03a41
KS
15377 return get_specified_cursor_type (XCDR (alt_cursor), width);
15378
15379 /* Then see if frame has specified a specific blink off cursor type. */
15380 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
15381 {
15382 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
15383 return FRAME_BLINK_OFF_CURSOR (f);
15384 }
7d0393cf
JB
15385
15386 /* Finally perform built-in cursor blinking:
cfe03a41
KS
15387 filled box <-> hollow box
15388 wide [h]bar <-> narrow [h]bar
15389 narrow [h]bar <-> no cursor
15390 other type <-> no cursor */
15391
15392 if (cursor_type == FILLED_BOX_CURSOR)
15393 return HOLLOW_BOX_CURSOR;
15394
15395 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
15396 {
15397 *width = 1;
15398 return cursor_type;
15399 }
15400
15401 return NO_CURSOR;
15402}
15403
15404\f
5f5c8ee5
GM
15405/***********************************************************************
15406 Initialization
15407 ***********************************************************************/
15408
a2889657
JB
15409void
15410syms_of_xdisp ()
15411{
c6e89d6c
GM
15412 Vwith_echo_area_save_vector = Qnil;
15413 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 15414
c6e89d6c
GM
15415 Vmessage_stack = Qnil;
15416 staticpro (&Vmessage_stack);
2311178e 15417
735c094c 15418 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 15419 staticpro (&Qinhibit_redisplay);
735c094c 15420
b14bc55e
RS
15421 message_dolog_marker1 = Fmake_marker ();
15422 staticpro (&message_dolog_marker1);
15423 message_dolog_marker2 = Fmake_marker ();
15424 staticpro (&message_dolog_marker2);
15425 message_dolog_marker3 = Fmake_marker ();
15426 staticpro (&message_dolog_marker3);
15427
5f5c8ee5 15428#if GLYPH_DEBUG
7d4cc828 15429 defsubr (&Sdump_frame_glyph_matrix);
5f5c8ee5
GM
15430 defsubr (&Sdump_glyph_matrix);
15431 defsubr (&Sdump_glyph_row);
e037b9ec 15432 defsubr (&Sdump_tool_bar_row);
62397849 15433 defsubr (&Strace_redisplay);
bf9249e3 15434 defsubr (&Strace_to_stderr);
5f5c8ee5 15435#endif
99a5de87 15436#ifdef HAVE_WINDOW_SYSTEM
57c28064 15437 defsubr (&Stool_bar_lines_needed);
99a5de87 15438#endif
8143e6ab 15439 defsubr (&Sformat_mode_line);
5f5c8ee5 15440
cf074754
RS
15441 staticpro (&Qmenu_bar_update_hook);
15442 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
15443
d46fb96a 15444 staticpro (&Qoverriding_terminal_local_map);
7079aefa 15445 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 15446
399164b4
KH
15447 staticpro (&Qoverriding_local_map);
15448 Qoverriding_local_map = intern ("overriding-local-map");
15449
75c43375
RS
15450 staticpro (&Qwindow_scroll_functions);
15451 Qwindow_scroll_functions = intern ("window-scroll-functions");
15452
e0bfbde6
RS
15453 staticpro (&Qredisplay_end_trigger_functions);
15454 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
2311178e 15455
2e54982e
RS
15456 staticpro (&Qinhibit_point_motion_hooks);
15457 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
15458
9499d71b
GM
15459 QCdata = intern (":data");
15460 staticpro (&QCdata);
5f5c8ee5 15461 Qdisplay = intern ("display");
f3751a65 15462 staticpro (&Qdisplay);
5f5c8ee5
GM
15463 Qspace_width = intern ("space-width");
15464 staticpro (&Qspace_width);
5f5c8ee5
GM
15465 Qraise = intern ("raise");
15466 staticpro (&Qraise);
15467 Qspace = intern ("space");
15468 staticpro (&Qspace);
f3751a65
GM
15469 Qmargin = intern ("margin");
15470 staticpro (&Qmargin);
5f5c8ee5 15471 Qleft_margin = intern ("left-margin");
f3751a65 15472 staticpro (&Qleft_margin);
5f5c8ee5 15473 Qright_margin = intern ("right-margin");
f3751a65 15474 staticpro (&Qright_margin);
5f5c8ee5
GM
15475 Qalign_to = intern ("align-to");
15476 staticpro (&Qalign_to);
15477 QCalign_to = intern (":align-to");
15478 staticpro (&QCalign_to);
5f5c8ee5
GM
15479 Qrelative_width = intern ("relative-width");
15480 staticpro (&Qrelative_width);
15481 QCrelative_width = intern (":relative-width");
15482 staticpro (&QCrelative_width);
15483 QCrelative_height = intern (":relative-height");
15484 staticpro (&QCrelative_height);
15485 QCeval = intern (":eval");
15486 staticpro (&QCeval);
0fcf414f
RS
15487 QCpropertize = intern (":propertize");
15488 staticpro (&QCpropertize);
d3acf96b 15489 Qwhen = intern ("when");
f3751a65 15490 staticpro (&Qwhen);
886bd6f2
GM
15491 QCfile = intern (":file");
15492 staticpro (&QCfile);
5f5c8ee5
GM
15493 Qfontified = intern ("fontified");
15494 staticpro (&Qfontified);
15495 Qfontification_functions = intern ("fontification-functions");
15496 staticpro (&Qfontification_functions);
5f5c8ee5
GM
15497 Qtrailing_whitespace = intern ("trailing-whitespace");
15498 staticpro (&Qtrailing_whitespace);
15499 Qimage = intern ("image");
15500 staticpro (&Qimage);
ad4f174e
GM
15501 Qmessage_truncate_lines = intern ("message-truncate-lines");
15502 staticpro (&Qmessage_truncate_lines);
af79bccb
RS
15503 Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
15504 staticpro (&Qcursor_in_non_selected_windows);
6422c1d7
GM
15505 Qgrow_only = intern ("grow-only");
15506 staticpro (&Qgrow_only);
e1477f43
GM
15507 Qinhibit_menubar_update = intern ("inhibit-menubar-update");
15508 staticpro (&Qinhibit_menubar_update);
30a3f61c
GM
15509 Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
15510 staticpro (&Qinhibit_eval_during_redisplay);
b384d6f8
GM
15511 Qposition = intern ("position");
15512 staticpro (&Qposition);
15513 Qbuffer_position = intern ("buffer-position");
15514 staticpro (&Qbuffer_position);
15515 Qobject = intern ("object");
15516 staticpro (&Qobject);
cfe03a41
KS
15517 Qbar = intern ("bar");
15518 staticpro (&Qbar);
15519 Qhbar = intern ("hbar");
15520 staticpro (&Qhbar);
15521 Qbox = intern ("box");
15522 staticpro (&Qbox);
15523 Qhollow = intern ("hollow");
15524 staticpro (&Qhollow);
c53a1624
RS
15525 Qrisky_local_variable = intern ("risky-local-variable");
15526 staticpro (&Qrisky_local_variable);
26683087
RS
15527 Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
15528 staticpro (&Qinhibit_free_realized_faces);
5f5c8ee5 15529
7033d6df
RS
15530 list_of_error = Fcons (intern ("error"), Qnil);
15531 staticpro (&list_of_error);
15532
a2889657
JB
15533 last_arrow_position = Qnil;
15534 last_arrow_string = Qnil;
f3751a65
GM
15535 staticpro (&last_arrow_position);
15536 staticpro (&last_arrow_string);
2311178e 15537
c6e89d6c
GM
15538 echo_buffer[0] = echo_buffer[1] = Qnil;
15539 staticpro (&echo_buffer[0]);
15540 staticpro (&echo_buffer[1]);
15541
15542 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
15543 staticpro (&echo_area_buffer[0]);
15544 staticpro (&echo_area_buffer[1]);
a2889657 15545
6a94510a
GM
15546 Vmessages_buffer_name = build_string ("*Messages*");
15547 staticpro (&Vmessages_buffer_name);
0fcf414f
RS
15548
15549 mode_line_proptrans_alist = Qnil;
15550 staticpro (&mode_line_proptrans_alist);
2311178e 15551
fec8f23e
KS
15552 mode_line_string_list = Qnil;
15553 staticpro (&mode_line_string_list);
15554
7ee72033
MB
15555 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
15556 doc: /* Non-nil means highlight trailing whitespace.
228299fa 15557The face used for trailing whitespace is `trailing-whitespace'. */);
8f897821
GM
15558 Vshow_trailing_whitespace = Qnil;
15559
7ee72033
MB
15560 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
15561 doc: /* Non-nil means don't actually do any redisplay.
228299fa 15562This is used for internal purposes. */);
735c094c
KH
15563 Vinhibit_redisplay = Qnil;
15564
7ee72033
MB
15565 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
15566 doc: /* String (or mode line construct) included (normally) in `mode-line-format'. */);
a2889657
JB
15567 Vglobal_mode_string = Qnil;
15568
7ee72033
MB
15569 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
15570 doc: /* Marker for where to display an arrow on top of the buffer text.
228299fa
GM
15571This must be the beginning of a line in order to work.
15572See also `overlay-arrow-string'. */);
a2889657
JB
15573 Voverlay_arrow_position = Qnil;
15574
7ee72033
MB
15575 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
15576 doc: /* String to display as an arrow. See also `overlay-arrow-position'. */);
a2889657
JB
15577 Voverlay_arrow_string = Qnil;
15578
7ee72033
MB
15579 DEFVAR_INT ("scroll-step", &scroll_step,
15580 doc: /* *The number of lines to try scrolling a window by when point moves out.
228299fa
GM
15581If that fails to bring point back on frame, point is centered instead.
15582If this is zero, point is always centered after it moves off frame.
15583If you want scrolling to always be a line at a time, you should set
15584`scroll-conservatively' to a large value rather than set this to 1. */);
15585
7ee72033
MB
15586 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
15587 doc: /* *Scroll up to this many lines, to bring point back on screen.
228299fa
GM
15588A value of zero means to scroll the text to center point vertically
15589in the window. */);
0789adb2
RS
15590 scroll_conservatively = 0;
15591
7ee72033
MB
15592 DEFVAR_INT ("scroll-margin", &scroll_margin,
15593 doc: /* *Number of lines of margin at the top and bottom of a window.
228299fa
GM
15594Recenter the window whenever point gets within this many lines
15595of the top or bottom of the window. */);
9afd2168
RS
15596 scroll_margin = 0;
15597
5f5c8ee5 15598#if GLYPH_DEBUG
7ee72033 15599 DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask. */);
5f5c8ee5 15600#endif
a2889657
JB
15601
15602 DEFVAR_BOOL ("truncate-partial-width-windows",
7ee72033
MB
15603 &truncate_partial_width_windows,
15604 doc: /* *Non-nil means truncate lines in all windows less than full frame wide. */);
a2889657
JB
15605 truncate_partial_width_windows = 1;
15606
7ee72033
MB
15607 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
15608 doc: /* nil means display the mode-line/header-line/menu-bar in the default face.
228299fa 15609Any other value means to use the appropriate face, `mode-line',
ccfe8f57 15610`header-line', or `menu' respectively. */);
1862a24e 15611 mode_line_inverse_video = 1;
aa6d10fa 15612
7ee72033
MB
15613 DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
15614 doc: /* *Maximum buffer size for which line number should be displayed.
228299fa
GM
15615If the buffer is bigger than this, the line number does not appear
15616in the mode line. A value of nil means no limit. */);
090703f4 15617 Vline_number_display_limit = Qnil;
fba9ce76 15618
090703f4 15619 DEFVAR_INT ("line-number-display-limit-width",
7ee72033
MB
15620 &line_number_display_limit_width,
15621 doc: /* *Maximum line width (in characters) for line number display.
228299fa
GM
15622If the average length of the lines near point is bigger than this, then the
15623line number may be omitted from the mode line. */);
5d121aec
KH
15624 line_number_display_limit_width = 200;
15625
7ee72033
MB
15626 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
15627 doc: /* *Non-nil means highlight region even in nonselected windows. */);
293a54ce 15628 highlight_nonselected_windows = 0;
d39b6696 15629
7ee72033
MB
15630 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
15631 doc: /* Non-nil if more than one frame is visible on this display.
228299fa
GM
15632Minibuffer-only frames don't count, but iconified frames do.
15633This variable is not guaranteed to be accurate except while processing
15634`frame-title-format' and `icon-title-format'. */);
15635
7ee72033
MB
15636 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
15637 doc: /* Template for displaying the title bar of visible frames.
228299fa
GM
15638\(Assuming the window manager supports this feature.)
15639This variable has the same structure as `mode-line-format' (which see),
15640and is used only on frames for which no explicit name has been set
15641\(see `modify-frame-parameters'). */);
7ee72033
MB
15642 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
15643 doc: /* Template for displaying the title bar of an iconified frame.
228299fa
GM
15644\(Assuming the window manager supports this feature.)
15645This variable has the same structure as `mode-line-format' (which see),
15646and is used only on frames for which no explicit name has been set
15647\(see `modify-frame-parameters'). */);
d39b6696
KH
15648 Vicon_title_format
15649 = Vframe_title_format
15650 = Fcons (intern ("multiple-frames"),
15651 Fcons (build_string ("%b"),
3ebf0ea9 15652 Fcons (Fcons (empty_string,
d39b6696
KH
15653 Fcons (intern ("invocation-name"),
15654 Fcons (build_string ("@"),
15655 Fcons (intern ("system-name"),
15656 Qnil)))),
15657 Qnil)));
5992c4f7 15658
7ee72033
MB
15659 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
15660 doc: /* Maximum number of lines to keep in the message log buffer.
228299fa
GM
15661If nil, disable message logging. If t, log messages but don't truncate
15662the buffer when it becomes large. */);
ac90c44f 15663 Vmessage_log_max = make_number (50);
08b610e4 15664
7ee72033
MB
15665 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
15666 doc: /* Functions called before redisplay, if window sizes have changed.
228299fa
GM
15667The value should be a list of functions that take one argument.
15668Just before redisplay, for each frame, if any of its windows have changed
15669size since the last redisplay, or have been split or deleted,
15670all the functions in the list are called, with the frame as argument. */);
08b610e4 15671 Vwindow_size_change_functions = Qnil;
75c43375 15672
7ee72033
MB
15673 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
15674 doc: /* List of Functions to call before redisplaying a window with scrolling.
228299fa
GM
15675Each function is called with two arguments, the window
15676and its new display-start position. Note that the value of `window-end'
15677is not valid when these functions are called. */);
75c43375 15678 Vwindow_scroll_functions = Qnil;
2311178e 15679
7ee72033
MB
15680 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
15681 doc: /* *Non-nil means automatically resize tool-bars.
228299fa
GM
15682This increases a tool-bar's height if not all tool-bar items are visible.
15683It decreases a tool-bar's height when it would display blank lines
15684otherwise. */);
e037b9ec 15685 auto_resize_tool_bars_p = 1;
2311178e 15686
7ee72033
MB
15687 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
15688 doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
e037b9ec 15689 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 15690
7ee72033
MB
15691 DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
15692 doc: /* *Margin around tool-bar buttons in pixels.
228299fa 15693If an integer, use that for both horizontal and vertical margins.
f6c89f27 15694Otherwise, value should be a pair of integers `(HORZ . VERT)' with
228299fa
GM
15695HORZ specifying the horizontal margin, and VERT specifying the
15696vertical margin. */);
c3d76173 15697 Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
5f5c8ee5 15698
7ee72033 15699 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
6da3c85b 15700 doc: /* *Relief thickness of tool-bar buttons. */);
c3d76173 15701 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
5f5c8ee5 15702
7ee72033
MB
15703 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
15704 doc: /* List of functions to call to fontify regions of text.
228299fa
GM
15705Each function is called with one argument POS. Functions must
15706fontify a region starting at POS in the current buffer, and give
15707fontified regions the property `fontified'. */);
5f5c8ee5 15708 Vfontification_functions = Qnil;
6b9f0906 15709 Fmake_variable_buffer_local (Qfontification_functions);
7bbe686f
AI
15710
15711 DEFVAR_BOOL ("unibyte-display-via-language-environment",
7ee72033
MB
15712 &unibyte_display_via_language_environment,
15713 doc: /* *Non-nil means display unibyte text according to language environment.
228299fa
GM
15714Specifically this means that unibyte non-ASCII characters
15715are displayed by converting them to the equivalent multibyte characters
15716according to the current language environment. As a result, they are
15717displayed according to the current fontset. */);
7bbe686f 15718 unibyte_display_via_language_environment = 0;
c6e89d6c 15719
7ee72033
MB
15720 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
15721 doc: /* *Maximum height for resizing mini-windows.
228299fa
GM
15722If a float, it specifies a fraction of the mini-window frame's height.
15723If an integer, it specifies a number of lines. */);
c6e89d6c 15724 Vmax_mini_window_height = make_float (0.25);
6422c1d7 15725
7ee72033
MB
15726 DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows,
15727 doc: /* *How to resize mini-windows.
228299fa
GM
15728A value of nil means don't automatically resize mini-windows.
15729A value of t means resize them to fit the text displayed in them.
15730A value of `grow-only', the default, means let mini-windows grow
15731only, until their display becomes empty, at which point the windows
15732go back to their normal size. */);
6422c1d7
GM
15733 Vresize_mini_windows = Qgrow_only;
15734
cfe03a41
KS
15735 DEFVAR_LISP ("cursor-in-non-selected-windows",
15736 &Vcursor_in_non_selected_windows,
15737 doc: /* *Cursor type to display in non-selected windows.
15738t means to use hollow box cursor. See `cursor-type' for other values. */);
15739 Vcursor_in_non_selected_windows = Qt;
15740
cfe03a41
KS
15741 DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
15742 doc: /* Alist specifying how to blink the cursor off.
15743Each element has the form (ON-STATE . OFF-STATE). Whenever the
15744`cursor-type' frame-parameter or variable equals ON-STATE,
15745comparing using `equal', Emacs uses OFF-STATE to specify
15746how to blink it off. */);
15747 Vblink_cursor_alist = Qnil;
2311178e 15748
e76d28d5 15749 DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
7ee72033 15750 doc: /* *Non-nil means scroll the display automatically to make point visible. */);
d475bcb8 15751 automatic_hscrolling_p = 1;
1df7e8f0 15752
e76d28d5 15753 DEFVAR_INT ("hscroll-margin", &hscroll_margin,
1df7e8f0
EZ
15754 doc: /* *How many columns away from the window edge point is allowed to get
15755before automatic hscrolling will horizontally scroll the window. */);
e76d28d5 15756 hscroll_margin = 5;
1df7e8f0 15757
e76d28d5 15758 DEFVAR_LISP ("hscroll-step", &Vhscroll_step,
1df7e8f0
EZ
15759 doc: /* *How many columns to scroll the window when point gets too close to the edge.
15760When point is less than `automatic-hscroll-margin' columns from the window
15761edge, automatic hscrolling will scroll the window by the amount of columns
15762determined by this variable. If its value is a positive integer, scroll that
15763many columns. If it's a positive floating-point number, it specifies the
15764fraction of the window's width to scroll. If it's nil or zero, point will be
15765centered horizontally after the scroll. Any other value, including negative
15766numbers, are treated as if the value were zero.
15767
15768Automatic hscrolling always moves point outside the scroll margin, so if
15769point was more than scroll step columns inside the margin, the window will
15770scroll more than the value given by the scroll step.
15771
15772Note that the lower bound for automatic hscrolling specified by `scroll-left'
15773and `scroll-right' overrides this variable's effect. */);
e76d28d5 15774 Vhscroll_step = make_number (0);
2311178e 15775
7ee72033
MB
15776 DEFVAR_LISP ("image-types", &Vimage_types,
15777 doc: /* List of supported image types.
228299fa 15778Each element of the list is a symbol for a supported image type. */);
e00daaa0 15779 Vimage_types = Qnil;
2311178e 15780
7ee72033
MB
15781 DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
15782 doc: /* If non-nil, messages are truncated instead of resizing the echo area.
228299fa 15783Bind this around calls to `message' to let it take effect. */);
ad4f174e 15784 message_truncate_lines = 0;
0bca8940 15785
7ee72033
MB
15786 DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
15787 doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
228299fa 15788Can be used to update submenus whose contents should vary. */);
6422c1d7 15789 Vmenu_bar_update_hook = Qnil;
2311178e 15790
7ee72033
MB
15791 DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
15792 doc: /* Non-nil means don't update menu bars. Internal use only. */);
e1477f43 15793 inhibit_menubar_update = 0;
30a3f61c 15794
7ee72033
MB
15795 DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
15796 doc: /* Non-nil means don't eval Lisp during redisplay. */);
30a3f61c 15797 inhibit_eval_during_redisplay = 0;
76cb5e06 15798
26683087
RS
15799 DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces,
15800 doc: /* Non-nil means don't free realized faces. Internal use only. */);
15801 inhibit_free_realized_faces = 0;
15802
69d1f7c9 15803#if GLYPH_DEBUG
76cb5e06
GM
15804 DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id,
15805 doc: /* Inhibit try_window_id display optimization. */);
15806 inhibit_try_window_id = 0;
15807
15808 DEFVAR_BOOL ("inhibit-try-window-reusing", &inhibit_try_window_reusing,
15809 doc: /* Inhibit try_window_reusing display optimization. */);
15810 inhibit_try_window_reusing = 0;
15811
15812 DEFVAR_BOOL ("inhibit-try-cursor-movement", &inhibit_try_cursor_movement,
15813 doc: /* Inhibit try_cursor_movement display optimization. */);
15814 inhibit_try_cursor_movement = 0;
15815#endif /* GLYPH_DEBUG */
a2889657
JB
15816}
15817
5f5c8ee5
GM
15818
15819/* Initialize this module when Emacs starts. */
15820
dfcf069d 15821void
a2889657
JB
15822init_xdisp ()
15823{
15824 Lisp_Object root_window;
5f5c8ee5 15825 struct window *mini_w;
a2889657 15826
04612a64
GM
15827 current_header_line_height = current_mode_line_height = -1;
15828
5f5c8ee5 15829 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
15830
15831 mini_w = XWINDOW (minibuf_window);
11e82b76 15832 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 15833
a2889657
JB
15834 if (!noninteractive)
15835 {
5f5c8ee5
GM
15836 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
15837 int i;
15838
ac90c44f 15839 XWINDOW (root_window)->top = make_number (FRAME_TOP_MARGIN (f));
12c226c5 15840 set_window_height (root_window,
5f5c8ee5 15841 FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 15842 0);
ac90c44f 15843 mini_w->top = make_number (FRAME_HEIGHT (f) - 1);
a2889657
JB
15844 set_window_height (minibuf_window, 1, 0);
15845
ac90c44f
GM
15846 XWINDOW (root_window)->width = make_number (FRAME_WIDTH (f));
15847 mini_w->width = make_number (FRAME_WIDTH (f));
5f5c8ee5
GM
15848
15849 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
15850 scratch_glyph_row.glyphs[TEXT_AREA + 1]
15851 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
15852
2311178e 15853 /* The default ellipsis glyphs `...'. */
5f5c8ee5 15854 for (i = 0; i < 3; ++i)
ac90c44f 15855 default_invis_vector[i] = make_number ('.');
a2889657 15856 }
5f5c8ee5 15857
5f5c8ee5 15858 {
93da8435
SM
15859 /* Allocate the buffer for frame titles.
15860 Also used for `format-mode-line'. */
5f5c8ee5
GM
15861 int size = 100;
15862 frame_title_buf = (char *) xmalloc (size);
15863 frame_title_buf_end = frame_title_buf + size;
15864 frame_title_ptr = NULL;
15865 }
2311178e 15866
21fdfb65 15867 help_echo_showing_p = 0;
a2889657 15868}
5f5c8ee5
GM
15869
15870