Add support for large files, plus some locale improvements.
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
5f5c8ee5
GM
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99
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,
36 let's say almost---see the the description of direct update
37 operations, below.).
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)
50 direct_output_for_insert,
51 direct_forward_char (dispnew.c)
52 +---------------------------------+
53 | |
54 | V
55 +--------------+ redisplay() +----------------+
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
67 What does redisplay? Obviously, it has to figure out somehow what
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
91 You will find a lot of of redisplay optimizations when you start
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
109
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
123 interface functions taking a iterator structure (struct it)
124 argument.
125
126 Iteration over things to be be displayed is then simple. It is
127 started by initializing an iterator with a call to init_iterator
128 (or init_string_iterator for that matter). Calls to
129 get_next_display_element fill the iterator structure with relevant
130 information about the next thing to display. Calls to
131 set_iterator_to_next move the iterator to the next thing.
132
133 Besides this, an iterator also contains information about the
134 display environment in which glyphs for display elements are to be
135 produced. It has fields for the width and height of the display,
136 the information whether long lines are truncated or continued, a
137 current X and Y position, and lots of other stuff you can better
138 see in dispextern.h.
139
140 Glyphs in a desired matrix are normally constructed in a loop
141 calling get_next_display_element and then produce_glyphs. The call
142 to produce_glyphs will fill the iterator structure with pixel
143 information about the element being displayed and at the same time
144 produce glyphs for it. If the display element fits on the line
145 being displayed, set_iterator_to_next is called next, otherwise the
146 glyphs produced are discarded.
147
148
149 Frame matrices.
150
151 That just couldn't be all, could it? What about terminal types not
152 supporting operations on sub-windows of the screen? To update the
153 display on such a terminal, window-based glyph matrices are not
154 well suited. To be able to reuse part of the display (scrolling
155 lines up and down), we must instead have a view of the whole
156 screen. This is what `frame matrices' are for. They are a trick.
157
158 Frames on terminals like above have a glyph pool. Windows on such
159 a frame sub-allocate their glyph memory from their frame's glyph
160 pool. The frame itself is given its own glyph matrices. By
161 coincidence---or maybe something else---rows in window glyph
162 matrices are slices of corresponding rows in frame matrices. Thus
163 writing to window matrices implicitly updates a frame matrix which
164 provides us with the view of the whole screen that we originally
165 wanted to have without having to move many bytes around. To be
166 honest, there is a little bit more done, but not much more. If you
167 plan to extend that code, take a look at dispnew.c. The function
168 build_frame_matrix is a good starting point. */
a2889657 169
18160b98 170#include <config.h>
a2889657 171#include <stdio.h>
5f5c8ee5
GM
172#ifdef STDC_HEADERS
173#include <stdlib.h>
174#endif
a2889657 175#include "lisp.h"
44fa5b1e 176#include "frame.h"
a2889657
JB
177#include "window.h"
178#include "termchar.h"
179#include "dispextern.h"
180#include "buffer.h"
1c9241f5 181#include "charset.h"
a2889657
JB
182#include "indent.h"
183#include "commands.h"
184#include "macros.h"
185#include "disptab.h"
30c566e4 186#include "termhooks.h"
b0a0fbda 187#include "intervals.h"
fe8b0cf8 188#include "keyboard.h"
1c9241f5
KH
189#include "coding.h"
190#include "process.h"
dfcf069d
AS
191#include "region-cache.h"
192
6d55d620 193#ifdef HAVE_X_WINDOWS
dfcf069d
AS
194#include "xterm.h"
195#endif
a2889657 196
5f5c8ee5
GM
197#define min(a, b) ((a) < (b) ? (a) : (b))
198#define max(a, b) ((a) > (b) ? (a) : (b))
199
200#define INFINITY 10000000
201
8f3343d0 202#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
76412d64 203extern void set_frame_menubar ();
cd6dfed6 204extern int pending_menu_activation;
76412d64
RS
205#endif
206
a2889657
JB
207extern int interrupt_input;
208extern int command_loop_level;
209
b6436d4e
RS
210extern int minibuffer_auto_raise;
211
c4628384
RS
212extern Lisp_Object Qface;
213
399164b4
KH
214extern Lisp_Object Voverriding_local_map;
215extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 216extern Lisp_Object Qmenu_item;
399164b4 217
d46fb96a 218Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 219Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 220Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 221Lisp_Object Qinhibit_point_motion_hooks;
886bd6f2 222Lisp_Object QCeval, Qwhen, QCfile;
5f5c8ee5
GM
223Lisp_Object Qfontified;
224
225/* Functions called to fontify regions of text. */
226
227Lisp_Object Vfontification_functions;
228Lisp_Object Qfontification_functions;
229
e037b9ec 230/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
231 over them. */
232
e037b9ec 233int auto_raise_tool_bar_buttons_p;
5f5c8ee5 234
e037b9ec 235/* Margin around tool bar buttons in pixels. */
5f5c8ee5 236
e037b9ec 237int tool_bar_button_margin;
5f5c8ee5 238
e037b9ec 239/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 240
e037b9ec 241int tool_bar_button_relief;
5f5c8ee5 242
e037b9ec 243/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
244 items are visible, and no blank lines remain. */
245
e037b9ec 246int auto_resize_tool_bars_p;
399164b4 247
735c094c
KH
248/* Non-nil means don't actually do any redisplay. */
249
250Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
251
5f5c8ee5
GM
252/* Names of text properties relevant for redisplay. */
253
254Lisp_Object Qdisplay, Qrelative_width, Qwidth, Qalign_to;
255extern Lisp_Object Qface, Qinvisible, Qimage;
256
257/* Symbols used in text property values. */
258
259Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
260Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qheight, Qraise;
f3751a65 261Lisp_Object Qmargin;
5f5c8ee5 262
8f897821 263/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 264
8f897821 265Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5
GM
266
267/* Name of the face used to highlight trailing whitespace. */
268
269Lisp_Object Qtrailing_whitespace;
270
271/* The symbol `image' which is the car of the lists used to represent
272 images in Lisp. */
273
274Lisp_Object Qimage;
275
276/* Non-zero means print newline to stdout before next mini-buffer
277 message. */
a2889657
JB
278
279int noninteractive_need_newline;
280
5f5c8ee5 281/* Non-zero means print newline to message log before next message. */
f88eb0b6 282
3c6595e0 283static int message_log_need_newline;
f88eb0b6 284
5f5c8ee5
GM
285\f
286/* The buffer position of the first character appearing entirely or
287 partially on the line of the selected window which contains the
288 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
289 redisplay optimization in redisplay_internal. */
a2889657 290
5f5c8ee5 291static struct text_pos this_line_start_pos;
a2889657 292
5f5c8ee5
GM
293/* Number of characters past the end of the line above, including the
294 terminating newline. */
295
296static struct text_pos this_line_end_pos;
297
298/* The vertical positions and the height of this line. */
a2889657 299
a2889657 300static int this_line_vpos;
5f5c8ee5
GM
301static int this_line_y;
302static int this_line_pixel_height;
303
304/* X position at which this display line starts. Usually zero;
305 negative if first character is partially visible. */
306
307static int this_line_start_x;
a2889657 308
5f5c8ee5 309/* Buffer that this_line_.* variables are referring to. */
a2889657 310
a2889657
JB
311static struct buffer *this_line_buffer;
312
5f5c8ee5
GM
313/* Nonzero means truncate lines in all windows less wide than the
314 frame. */
a2889657 315
a2889657
JB
316int truncate_partial_width_windows;
317
7bbe686f 318/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 319
7bbe686f 320int unibyte_display_via_language_environment;
5f5c8ee5
GM
321
322/* Nonzero means we have more than one non-mini-buffer-only frame.
323 Not guaranteed to be accurate except while parsing
324 frame-title-format. */
7bbe686f 325
d39b6696
KH
326int multiple_frames;
327
a2889657
JB
328Lisp_Object Vglobal_mode_string;
329
330/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 331
a2889657
JB
332Lisp_Object Voverlay_arrow_position;
333
5f5c8ee5
GM
334/* String to display for the arrow. Only used on terminal frames. */
335
a2889657
JB
336Lisp_Object Voverlay_arrow_string;
337
5f5c8ee5
GM
338/* Values of those variables at last redisplay. However, if
339 Voverlay_arrow_position is a marker, last_arrow_position is its
340 numerical position. */
341
d45de95b
RS
342static Lisp_Object last_arrow_position, last_arrow_string;
343
5f5c8ee5
GM
344/* Like mode-line-format, but for the title bar on a visible frame. */
345
d39b6696
KH
346Lisp_Object Vframe_title_format;
347
5f5c8ee5
GM
348/* Like mode-line-format, but for the title bar on an iconified frame. */
349
d39b6696
KH
350Lisp_Object Vicon_title_format;
351
08b610e4
RS
352/* List of functions to call when a window's size changes. These
353 functions get one arg, a frame on which one or more windows' sizes
354 have changed. */
5f5c8ee5 355
08b610e4
RS
356static Lisp_Object Vwindow_size_change_functions;
357
cf074754
RS
358Lisp_Object Qmenu_bar_update_hook;
359
a2889657 360/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 361
5f5c8ee5 362static int overlay_arrow_seen;
ca26e1c8 363
fba9ce76 364/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 365
5f5c8ee5
GM
366int highlight_nonselected_windows;
367
368/* If cursor motion alone moves point off frame, try scrolling this
369 many lines up or down if that will bring it back. */
370
14510fee 371static int scroll_step;
a2889657 372
5f5c8ee5
GM
373/* Non-0 means scroll just far enough to bring point back on the
374 screen, when appropriate. */
375
0789adb2
RS
376static int scroll_conservatively;
377
5f5c8ee5
GM
378/* Recenter the window whenever point gets within this many lines of
379 the top or bottom of the window. This value is translated into a
380 pixel value by multiplying it with CANON_Y_UNIT, which means that
381 there is really a fixed pixel height scroll margin. */
382
9afd2168
RS
383int scroll_margin;
384
5f5c8ee5
GM
385/* Number of windows showing the buffer of the selected window (or
386 another buffer with the same base buffer). keyboard.c refers to
387 this. */
a2889657 388
a2889657
JB
389int buffer_shared;
390
5f5c8ee5 391/* Vector containing glyphs for an ellipsis `...'. */
a2889657 392
5f5c8ee5 393static Lisp_Object default_invis_vector[3];
a2889657 394
5f5c8ee5 395/* Nonzero means display mode line highlighted. */
a2889657 396
a2889657
JB
397int mode_line_inverse_video;
398
5f5c8ee5
GM
399/* Prompt to display in front of the mini-buffer contents. */
400
8c5b6a0a 401Lisp_Object minibuf_prompt;
a2889657 402
5f5c8ee5
GM
403/* Width of current mini-buffer prompt. Only set after display_line
404 of the line that contains the prompt. */
405
a2889657 406int minibuf_prompt_width;
5f5c8ee5
GM
407int minibuf_prompt_pixel_width;
408
5f5c8ee5
GM
409/* This is the window where the echo area message was displayed. It
410 is always a mini-buffer window, but it may not be the same window
411 currently active as a mini-buffer. */
412
73af359d
RS
413Lisp_Object echo_area_window;
414
c6e89d6c
GM
415/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
416 pushes the current message and the value of
417 message_enable_multibyte on the stack, the function restore_message
418 pops the stack and displays MESSAGE again. */
419
420Lisp_Object Vmessage_stack;
421
a3788d53
RS
422/* Nonzero means multibyte characters were enabled when the echo area
423 message was specified. */
5f5c8ee5 424
a3788d53
RS
425int message_enable_multibyte;
426
5f5c8ee5
GM
427/* True if we should redraw the mode lines on the next redisplay. */
428
a2889657
JB
429int update_mode_lines;
430
5f5c8ee5
GM
431/* Nonzero if window sizes or contents have changed since last
432 redisplay that finished */
433
a2889657
JB
434int windows_or_buffers_changed;
435
5f5c8ee5
GM
436/* Nonzero after display_mode_line if %l was used and it displayed a
437 line number. */
438
aa6d10fa
RS
439int line_number_displayed;
440
441/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 442
14510fee 443static int line_number_display_limit;
5992c4f7 444
5d121aec
KH
445/* line width to consider when repostioning for line number display */
446
447static int line_number_display_limit_width;
448
5f5c8ee5
GM
449/* Number of lines to keep in the message log buffer. t means
450 infinite. nil means don't log at all. */
451
5992c4f7 452Lisp_Object Vmessage_log_max;
d45de95b 453
c6e89d6c
GM
454/* Current, index 0, and last displayed echo area message. Either
455 buffers from echo_buffers, or nil to indicate no message. */
456
457Lisp_Object echo_area_buffer[2];
458
459/* The buffers referenced from echo_area_buffer. */
460
461static Lisp_Object echo_buffer[2];
462
463/* A vector saved used in with_area_buffer to reduce consing. */
464
465static Lisp_Object Vwith_echo_area_save_vector;
466
467/* Non-zero means display_echo_area should display the last echo area
468 message again. Set by redisplay_preserve_echo_area. */
469
470static int display_last_displayed_message_p;
471
472/* Nonzero if echo area is being used by print; zero if being used by
473 message. */
474
475int message_buf_print;
476
9142dd5b
GM
477/* Maximum height for resizing mini-windows. Either a float
478 specifying a fraction of the available height, or an integer
479 specifying a number of lines. */
c6e89d6c
GM
480
481static Lisp_Object Vmax_mini_window_height;
482
5f5c8ee5
GM
483/* A scratch glyph row with contents used for generating truncation
484 glyphs. Also used in direct_output_for_insert. */
12adba34 485
5f5c8ee5
GM
486#define MAX_SCRATCH_GLYPHS 100
487struct glyph_row scratch_glyph_row;
488static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 489
5f5c8ee5
GM
490/* Ascent and height of the last line processed by move_it_to. */
491
492static int last_max_ascent, last_height;
493
494/* The maximum distance to look ahead for text properties. Values
495 that are too small let us call compute_char_face and similar
496 functions too often which is expensive. Values that are too large
497 let us call compute_char_face and alike too often because we
498 might not be interested in text properties that far away. */
499
500#define TEXT_PROP_DISTANCE_LIMIT 100
501
502/* Non-zero means print traces of redisplay if compiled with
503 GLYPH_DEBUG != 0. */
504
505#if GLYPH_DEBUG
506int trace_redisplay_p;
507#endif
508
509/* Value returned from text property handlers (see below). */
510
511enum prop_handled
3c6595e0 512{
5f5c8ee5
GM
513 HANDLED_NORMALLY,
514 HANDLED_RECOMPUTE_PROPS,
515 HANDLED_OVERLAY_STRING_CONSUMED,
516 HANDLED_RETURN
517};
3c6595e0 518
5f5c8ee5
GM
519/* A description of text properties that redisplay is interested
520 in. */
3c6595e0 521
5f5c8ee5
GM
522struct props
523{
524 /* The name of the property. */
525 Lisp_Object *name;
90adcf20 526
5f5c8ee5
GM
527 /* A unique index for the property. */
528 enum prop_idx idx;
529
530 /* A handler function called to set up iterator IT from the property
531 at IT's current position. Value is used to steer handle_stop. */
532 enum prop_handled (*handler) P_ ((struct it *it));
533};
534
535static enum prop_handled handle_face_prop P_ ((struct it *));
536static enum prop_handled handle_invisible_prop P_ ((struct it *));
537static enum prop_handled handle_display_prop P_ ((struct it *));
538static enum prop_handled handle_overlay_change P_ ((struct it *));
539static enum prop_handled handle_fontified_prop P_ ((struct it *));
540
541/* Properties handled by iterators. */
542
543static struct props it_props[] =
5992c4f7 544{
5f5c8ee5
GM
545 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
546 /* Handle `face' before `display' because some sub-properties of
547 `display' need to know the face. */
548 {&Qface, FACE_PROP_IDX, handle_face_prop},
549 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
550 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
551 {NULL, 0, NULL}
552};
5992c4f7 553
5f5c8ee5
GM
554/* Value is the position described by X. If X is a marker, value is
555 the marker_position of X. Otherwise, value is X. */
12adba34 556
5f5c8ee5 557#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 558
5f5c8ee5 559/* Enumeration returned by some move_it_.* functions internally. */
12adba34 560
5f5c8ee5
GM
561enum move_it_result
562{
563 /* Not used. Undefined value. */
564 MOVE_UNDEFINED,
bab29e15 565
5f5c8ee5
GM
566 /* Move ended at the requested buffer position or ZV. */
567 MOVE_POS_MATCH_OR_ZV,
bab29e15 568
5f5c8ee5
GM
569 /* Move ended at the requested X pixel position. */
570 MOVE_X_REACHED,
12adba34 571
5f5c8ee5
GM
572 /* Move within a line ended at the end of a line that must be
573 continued. */
574 MOVE_LINE_CONTINUED,
575
576 /* Move within a line ended at the end of a line that would
577 be displayed truncated. */
578 MOVE_LINE_TRUNCATED,
ff6c30e5 579
5f5c8ee5
GM
580 /* Move within a line ended at a line end. */
581 MOVE_NEWLINE_OR_CR
582};
12adba34 583
ff6c30e5 584
5f5c8ee5
GM
585\f
586/* Function prototypes. */
587
e037b9ec
GM
588static struct glyph_row *row_containing_pos P_ ((struct window *, int,
589 struct glyph_row *,
590 struct glyph_row *));
c6e89d6c
GM
591static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
592static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
c6e89d6c
GM
593static void clear_garbaged_frames P_ ((void));
594static int current_message_1 P_ ((Lisp_Object *));
595static int truncate_message_1 P_ ((int));
596static int set_message_1 P_ ((char *s, Lisp_Object, int, int));
597static int display_echo_area P_ ((struct window *));
598static int display_echo_area_1 P_ ((struct window *));
28514cd9 599static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
4fdb80f2 600static int string_char_and_length P_ ((unsigned char *, int, int *));
5f5c8ee5
GM
601static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
602 struct text_pos));
603static int compute_window_start_on_continuation_line P_ ((struct window *));
604static Lisp_Object eval_handler P_ ((Lisp_Object));
605static Lisp_Object eval_form P_ ((Lisp_Object));
606static void insert_left_trunc_glyphs P_ ((struct it *));
607static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
608static void extend_face_to_end_of_line P_ ((struct it *));
609static void append_space P_ ((struct it *, int));
610static void make_cursor_line_fully_visible P_ ((struct window *));
611static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
612static int trailing_whitespace_p P_ ((int));
613static int message_log_check_duplicate P_ ((int, int, int, int));
614int invisible_p P_ ((Lisp_Object, Lisp_Object));
615int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
616static void push_it P_ ((struct it *));
617static void pop_it P_ ((struct it *));
618static void sync_frame_with_window_matrix_rows P_ ((struct window *));
619static void redisplay_internal P_ ((int));
c6e89d6c 620static int echo_area_display P_ ((int));
5f5c8ee5
GM
621static void redisplay_windows P_ ((Lisp_Object));
622static void redisplay_window P_ ((Lisp_Object, int));
623static void update_menu_bar P_ ((struct frame *, int));
624static int try_window_reusing_current_matrix P_ ((struct window *));
625static int try_window_id P_ ((struct window *));
626static int display_line P_ ((struct it *));
627static void display_mode_lines P_ ((struct window *));
628static void display_mode_line P_ ((struct window *, enum face_id,
629 Lisp_Object));
630static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
631static char *decode_mode_spec P_ ((struct window *, char, int, int));
632static void display_menu_bar P_ ((struct window *));
633static int display_count_lines P_ ((int, int, int, int, int *));
634static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
635 int, int, struct it *, int, int, int, int));
636static void compute_line_metrics P_ ((struct it *));
637static void run_redisplay_end_trigger_hook P_ ((struct it *));
638static int get_overlay_strings P_ ((struct it *));
639static void next_overlay_string P_ ((struct it *));
640void set_iterator_to_next P_ ((struct it *));
641static void reseat P_ ((struct it *, struct text_pos, int));
642static void reseat_1 P_ ((struct it *, struct text_pos, int));
643static void back_to_previous_visible_line_start P_ ((struct it *));
644static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 645static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
646static int next_element_from_display_vector P_ ((struct it *));
647static int next_element_from_string P_ ((struct it *));
648static int next_element_from_c_string P_ ((struct it *));
649static int next_element_from_buffer P_ ((struct it *));
650static int next_element_from_image P_ ((struct it *));
651static int next_element_from_stretch P_ ((struct it *));
652static void load_overlay_strings P_ ((struct it *));
653static void init_from_display_pos P_ ((struct it *, struct window *,
654 struct display_pos *));
655static void reseat_to_string P_ ((struct it *, unsigned char *,
656 Lisp_Object, int, int, int, int));
657static int charset_at_position P_ ((struct text_pos));
658static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
659 int, int, int));
660void move_it_vertically_backward P_ ((struct it *, int));
661static void init_to_row_start P_ ((struct it *, struct window *,
662 struct glyph_row *));
663static void init_to_row_end P_ ((struct it *, struct window *,
664 struct glyph_row *));
665static void back_to_previous_line_start P_ ((struct it *));
666static void forward_to_next_line_start P_ ((struct it *));
667static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
668 Lisp_Object, int));
669static struct text_pos string_pos P_ ((int, Lisp_Object));
670static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
671static int number_of_chars P_ ((unsigned char *, int));
672static void compute_stop_pos P_ ((struct it *));
673static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
674 Lisp_Object));
675static int face_before_or_after_it_pos P_ ((struct it *, int));
676static int next_overlay_change P_ ((int));
677static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
678 Lisp_Object, struct text_pos *));
679
680#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
681#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 682
5f5c8ee5 683#ifdef HAVE_WINDOW_SYSTEM
12adba34 684
e037b9ec
GM
685static void update_tool_bar P_ ((struct frame *, int));
686static void build_desired_tool_bar_string P_ ((struct frame *f));
687static int redisplay_tool_bar P_ ((struct frame *));
688static void display_tool_bar_line P_ ((struct it *));
12adba34 689
5f5c8ee5 690#endif /* HAVE_WINDOW_SYSTEM */
12adba34 691
5f5c8ee5
GM
692\f
693/***********************************************************************
694 Window display dimensions
695 ***********************************************************************/
12adba34 696
5f5c8ee5
GM
697/* Return the window-relative maximum y + 1 for glyph rows displaying
698 text in window W. This is the height of W minus the height of a
699 mode line, if any. */
700
701INLINE int
702window_text_bottom_y (w)
703 struct window *w;
704{
705 struct frame *f = XFRAME (w->frame);
706 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
707
708 if (WINDOW_WANTS_MODELINE_P (w))
709 height -= CURRENT_MODE_LINE_HEIGHT (w);
710 return height;
f88eb0b6
KH
711}
712
f82aff7c 713
5f5c8ee5
GM
714/* Return the pixel width of display area AREA of window W. AREA < 0
715 means return the total width of W, not including bitmap areas to
716 the left and right of the window. */
ff6c30e5 717
5f5c8ee5
GM
718INLINE int
719window_box_width (w, area)
720 struct window *w;
721 int area;
722{
723 struct frame *f = XFRAME (w->frame);
724 int width = XFASTINT (w->width);
725
726 if (!w->pseudo_window_p)
ff6c30e5 727 {
050d82d7 728 width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FLAGS_AREA_COLS (f);
5f5c8ee5
GM
729
730 if (area == TEXT_AREA)
731 {
732 if (INTEGERP (w->left_margin_width))
733 width -= XFASTINT (w->left_margin_width);
734 if (INTEGERP (w->right_margin_width))
735 width -= XFASTINT (w->right_margin_width);
736 }
737 else if (area == LEFT_MARGIN_AREA)
738 width = (INTEGERP (w->left_margin_width)
739 ? XFASTINT (w->left_margin_width) : 0);
740 else if (area == RIGHT_MARGIN_AREA)
741 width = (INTEGERP (w->right_margin_width)
742 ? XFASTINT (w->right_margin_width) : 0);
ff6c30e5 743 }
5f5c8ee5
GM
744
745 return width * CANON_X_UNIT (f);
ff6c30e5 746}
1adc55de 747
1adc55de 748
5f5c8ee5
GM
749/* Return the pixel height of the display area of window W, not
750 including mode lines of W, if any.. */
f88eb0b6 751
5f5c8ee5
GM
752INLINE int
753window_box_height (w)
754 struct window *w;
f88eb0b6 755{
5f5c8ee5
GM
756 struct frame *f = XFRAME (w->frame);
757 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
758
759 if (WINDOW_WANTS_MODELINE_P (w))
760 height -= CURRENT_MODE_LINE_HEIGHT (w);
761
045dee35
GM
762 if (WINDOW_WANTS_HEADER_LINE_P (w))
763 height -= CURRENT_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
764
765 return height;
5992c4f7
KH
766}
767
768
5f5c8ee5
GM
769/* Return the frame-relative coordinate of the left edge of display
770 area AREA of window W. AREA < 0 means return the left edge of the
771 whole window, to the right of any bitmap area at the left side of
772 W. */
5992c4f7 773
5f5c8ee5
GM
774INLINE int
775window_box_left (w, area)
776 struct window *w;
777 int area;
90adcf20 778{
5f5c8ee5
GM
779 struct frame *f = XFRAME (w->frame);
780 int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
a3788d53 781
5f5c8ee5 782 if (!w->pseudo_window_p)
90adcf20 783 {
5f5c8ee5 784 x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
050d82d7 785 + FRAME_LEFT_FLAGS_AREA_WIDTH (f));
5f5c8ee5
GM
786
787 if (area == TEXT_AREA)
788 x += window_box_width (w, LEFT_MARGIN_AREA);
789 else if (area == RIGHT_MARGIN_AREA)
790 x += (window_box_width (w, LEFT_MARGIN_AREA)
791 + window_box_width (w, TEXT_AREA));
90adcf20 792 }
73af359d 793
5f5c8ee5
GM
794 return x;
795}
90adcf20 796
b6436d4e 797
5f5c8ee5
GM
798/* Return the frame-relative coordinate of the right edge of display
799 area AREA of window W. AREA < 0 means return the left edge of the
800 whole window, to the left of any bitmap area at the right side of
801 W. */
ded34426 802
5f5c8ee5
GM
803INLINE int
804window_box_right (w, area)
805 struct window *w;
806 int area;
807{
808 return window_box_left (w, area) + window_box_width (w, area);
809}
810
811
812/* Get the bounding box of the display area AREA of window W, without
813 mode lines, in frame-relative coordinates. AREA < 0 means the
814 whole window, not including bitmap areas to the left and right of
815 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
816 coordinates of the upper-left corner of the box. Return in
817 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
818
819INLINE void
820window_box (w, area, box_x, box_y, box_width, box_height)
821 struct window *w;
822 int area;
823 int *box_x, *box_y, *box_width, *box_height;
824{
825 struct frame *f = XFRAME (w->frame);
826
827 *box_width = window_box_width (w, area);
828 *box_height = window_box_height (w);
829 *box_x = window_box_left (w, area);
830 *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
831 + XFASTINT (w->top) * CANON_Y_UNIT (f));
045dee35
GM
832 if (WINDOW_WANTS_HEADER_LINE_P (w))
833 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
ded34426 834}
1adc55de 835
1adc55de 836
5f5c8ee5
GM
837/* Get the bounding box of the display area AREA of window W, without
838 mode lines. AREA < 0 means the whole window, not including bitmap
839 areas to the left and right of the window. Return in *TOP_LEFT_X
840 and TOP_LEFT_Y the frame-relative pixel coordinates of the
841 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
842 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
843 box. */
ded34426 844
5f5c8ee5
GM
845INLINE void
846window_box_edges (w, area, top_left_x, top_left_y,
847 bottom_right_x, bottom_right_y)
848 struct window *w;
849 int area;
850 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 851{
5f5c8ee5
GM
852 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
853 bottom_right_y);
854 *bottom_right_x += *top_left_x;
855 *bottom_right_y += *top_left_y;
48ae5f0a
KH
856}
857
5f5c8ee5
GM
858
859\f
860/***********************************************************************
861 Utilities
862 ***********************************************************************/
863
4fdb80f2
GM
864/* Return the next character from STR which is MAXLEN bytes long.
865 Return in *LEN the length of the character. This is like
866 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
867 we find one, we return a `?', but with the length of the illegal
868 character. */
869
870static INLINE int
7a5b8a93 871string_char_and_length (str, maxlen, len)
4fdb80f2 872 unsigned char *str;
7a5b8a93 873 int maxlen, *len;
4fdb80f2
GM
874{
875 int c;
876
877 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
878 if (!CHAR_VALID_P (c, 1))
879 /* We may not change the length here because other places in Emacs
880 don't use this function, i.e. they silently accept illegal
881 characters. */
882 c = '?';
883
884 return c;
885}
886
887
888
5f5c8ee5
GM
889/* Given a position POS containing a valid character and byte position
890 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
891
892static struct text_pos
893string_pos_nchars_ahead (pos, string, nchars)
894 struct text_pos pos;
895 Lisp_Object string;
896 int nchars;
0b1005ef 897{
5f5c8ee5
GM
898 xassert (STRINGP (string) && nchars >= 0);
899
900 if (STRING_MULTIBYTE (string))
901 {
902 int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos);
903 unsigned char *p = XSTRING (string)->data + BYTEPOS (pos);
904 int len;
905
906 while (nchars--)
907 {
4fdb80f2 908 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
909 p += len, rest -= len;
910 xassert (rest >= 0);
911 CHARPOS (pos) += 1;
912 BYTEPOS (pos) += len;
913 }
914 }
915 else
916 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
917
918 return pos;
0a9dc68b
RS
919}
920
0a9dc68b 921
5f5c8ee5
GM
922/* Value is the text position, i.e. character and byte position,
923 for character position CHARPOS in STRING. */
924
925static INLINE struct text_pos
926string_pos (charpos, string)
927 int charpos;
0a9dc68b 928 Lisp_Object string;
0a9dc68b 929{
5f5c8ee5
GM
930 struct text_pos pos;
931 xassert (STRINGP (string));
932 xassert (charpos >= 0);
933 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
934 return pos;
935}
936
937
938/* Value is a text position, i.e. character and byte position, for
939 character position CHARPOS in C string S. MULTIBYTE_P non-zero
940 means recognize multibyte characters. */
941
942static struct text_pos
943c_string_pos (charpos, s, multibyte_p)
944 int charpos;
945 unsigned char *s;
946 int multibyte_p;
947{
948 struct text_pos pos;
949
950 xassert (s != NULL);
951 xassert (charpos >= 0);
952
953 if (multibyte_p)
0a9dc68b 954 {
5f5c8ee5
GM
955 int rest = strlen (s), len;
956
957 SET_TEXT_POS (pos, 0, 0);
958 while (charpos--)
0a9dc68b 959 {
4fdb80f2 960 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
961 s += len, rest -= len;
962 xassert (rest >= 0);
963 CHARPOS (pos) += 1;
964 BYTEPOS (pos) += len;
0a9dc68b
RS
965 }
966 }
5f5c8ee5
GM
967 else
968 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 969
5f5c8ee5
GM
970 return pos;
971}
0a9dc68b 972
0a9dc68b 973
5f5c8ee5
GM
974/* Value is the number of characters in C string S. MULTIBYTE_P
975 non-zero means recognize multibyte characters. */
0a9dc68b 976
5f5c8ee5
GM
977static int
978number_of_chars (s, multibyte_p)
979 unsigned char *s;
980 int multibyte_p;
981{
982 int nchars;
983
984 if (multibyte_p)
985 {
986 int rest = strlen (s), len;
987 unsigned char *p = (unsigned char *) s;
0a9dc68b 988
5f5c8ee5
GM
989 for (nchars = 0; rest > 0; ++nchars)
990 {
4fdb80f2 991 string_char_and_length (p, rest, &len);
5f5c8ee5 992 rest -= len, p += len;
0a9dc68b
RS
993 }
994 }
5f5c8ee5
GM
995 else
996 nchars = strlen (s);
997
998 return nchars;
0b1005ef
KH
999}
1000
5f5c8ee5
GM
1001
1002/* Compute byte position NEWPOS->bytepos corresponding to
1003 NEWPOS->charpos. POS is a known position in string STRING.
1004 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1005
5f5c8ee5
GM
1006static void
1007compute_string_pos (newpos, pos, string)
1008 struct text_pos *newpos, pos;
1009 Lisp_Object string;
76412d64 1010{
5f5c8ee5
GM
1011 xassert (STRINGP (string));
1012 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
1013
1014 if (STRING_MULTIBYTE (string))
1015 *newpos = string_pos_nchars_ahead (pos, CHARPOS (*newpos) - CHARPOS (pos),
1016 string);
1017 else
1018 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1019}
1020
9c74a0dd 1021
5f5c8ee5
GM
1022/* Return the charset of the character at position POS in
1023 current_buffer. */
1adc55de 1024
5f5c8ee5
GM
1025static int
1026charset_at_position (pos)
1027 struct text_pos pos;
a2889657 1028{
5f5c8ee5
GM
1029 int c, multibyte_p;
1030 unsigned char *p = BYTE_POS_ADDR (BYTEPOS (pos));
1031
1032 multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1033 if (multibyte_p)
a2889657 1034 {
5f5c8ee5
GM
1035 int maxlen = ((BYTEPOS (pos) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
1036 - BYTEPOS (pos));
1037 int len;
4fdb80f2 1038 c = string_char_and_length (p, maxlen, &len);
a2889657 1039 }
5f5c8ee5
GM
1040 else
1041 c = *p;
1042
1043 return CHAR_CHARSET (c);
1044}
1045
1046
1047\f
1048/***********************************************************************
1049 Lisp form evaluation
1050 ***********************************************************************/
1051
1052/* Error handler for eval_form. */
1053
1054static Lisp_Object
1055eval_handler (arg)
1056 Lisp_Object arg;
1057{
1058 return Qnil;
1059}
1060
1061
1062/* Evaluate SEXPR and return the result, or nil if something went
1063 wrong. */
1064
1065static Lisp_Object
1066eval_form (sexpr)
1067 Lisp_Object sexpr;
1068{
1069 int count = specpdl_ptr - specpdl;
1070 Lisp_Object val;
1071 specbind (Qinhibit_redisplay, Qt);
1072 val = internal_condition_case_1 (Feval, sexpr, Qerror, eval_handler);
1073 return unbind_to (count, val);
1074}
1075
1076
1077\f
1078/***********************************************************************
1079 Debugging
1080 ***********************************************************************/
1081
1082#if 0
1083
1084/* Define CHECK_IT to perform sanity checks on iterators.
1085 This is for debugging. It is too slow to do unconditionally. */
1086
1087static void
1088check_it (it)
1089 struct it *it;
1090{
1091 if (it->method == next_element_from_string)
a2889657 1092 {
5f5c8ee5
GM
1093 xassert (STRINGP (it->string));
1094 xassert (IT_STRING_CHARPOS (*it) >= 0);
1095 }
1096 else if (it->method == next_element_from_buffer)
1097 {
1098 /* Check that character and byte positions agree. */
1099 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1100 }
73af359d 1101
5f5c8ee5
GM
1102 if (it->dpvec)
1103 xassert (it->current.dpvec_index >= 0);
1104 else
1105 xassert (it->current.dpvec_index < 0);
1106}
1f40cad2 1107
5f5c8ee5
GM
1108#define CHECK_IT(IT) check_it ((IT))
1109
1110#else /* not 0 */
1111
1112#define CHECK_IT(IT) (void) 0
1113
1114#endif /* not 0 */
1115
1116
1117#if GLYPH_DEBUG
1118
1119/* Check that the window end of window W is what we expect it
1120 to be---the last row in the current matrix displaying text. */
1121
1122static void
1123check_window_end (w)
1124 struct window *w;
1125{
1126 if (!MINI_WINDOW_P (w)
1127 && !NILP (w->window_end_valid))
1128 {
1129 struct glyph_row *row;
1130 xassert ((row = MATRIX_ROW (w->current_matrix,
1131 XFASTINT (w->window_end_vpos)),
1132 !row->enabled_p
1133 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1134 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1135 }
1136}
1137
1138#define CHECK_WINDOW_END(W) check_window_end ((W))
1139
1140#else /* not GLYPH_DEBUG */
1141
1142#define CHECK_WINDOW_END(W) (void) 0
1143
1144#endif /* not GLYPH_DEBUG */
1145
1146
1147\f
1148/***********************************************************************
1149 Iterator initialization
1150 ***********************************************************************/
1151
1152/* Initialize IT for displaying current_buffer in window W, starting
1153 at character position CHARPOS. CHARPOS < 0 means that no buffer
1154 position is specified which is useful when the iterator is assigned
1155 a position later. BYTEPOS is the byte position corresponding to
1156 CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS.
1157
1158 If ROW is not null, calls to produce_glyphs with IT as parameter
1159 will produce glyphs in that row.
1160
1161 BASE_FACE_ID is the id of a base face to use. It must be one of
1162 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or
045dee35 1163 HEADER_LINE_FACE_ID for displaying mode lines, or TOOL_BAR_FACE_ID for
e037b9ec 1164 displaying the tool-bar.
5f5c8ee5
GM
1165
1166 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or
045dee35 1167 HEADER_LINE_FACE_ID, the iterator will be initialized to use the
5f5c8ee5
GM
1168 corresponding mode line glyph row of the desired matrix of W. */
1169
1170void
1171init_iterator (it, w, charpos, bytepos, row, base_face_id)
1172 struct it *it;
1173 struct window *w;
1174 int charpos, bytepos;
1175 struct glyph_row *row;
1176 enum face_id base_face_id;
1177{
1178 int highlight_region_p;
5f5c8ee5
GM
1179
1180 /* Some precondition checks. */
1181 xassert (w != NULL && it != NULL);
5f5c8ee5
GM
1182 xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
1183
1184 /* If face attributes have been changed since the last redisplay,
1185 free realized faces now because they depend on face definitions
1186 that might have changed. */
1187 if (face_change_count)
1188 {
1189 face_change_count = 0;
1190 free_all_realized_faces (Qnil);
1191 }
1192
1193 /* Use one of the mode line rows of W's desired matrix if
1194 appropriate. */
1195 if (row == NULL)
1196 {
1197 if (base_face_id == MODE_LINE_FACE_ID)
1198 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
1199 else if (base_face_id == HEADER_LINE_FACE_ID)
1200 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5
GM
1201 }
1202
1203 /* Clear IT. */
1204 bzero (it, sizeof *it);
1205 it->current.overlay_string_index = -1;
1206 it->current.dpvec_index = -1;
1207 it->charset = CHARSET_ASCII;
1208 it->base_face_id = base_face_id;
1209
1210 /* The window in which we iterate over current_buffer: */
1211 XSETWINDOW (it->window, w);
1212 it->w = w;
1213 it->f = XFRAME (w->frame);
1214
1215 /* If realized faces have been removed, e.g. because of face
1216 attribute changes of named faces, recompute them. */
1217 if (FRAME_FACE_CACHE (it->f)->used == 0)
1218 recompute_basic_faces (it->f);
1219
5f5c8ee5
GM
1220 /* Current value of the `space-width', and 'height' properties. */
1221 it->space_width = Qnil;
1222 it->font_height = Qnil;
1223
1224 /* Are control characters displayed as `^C'? */
1225 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
1226
1227 /* -1 means everything between a CR and the following line end
1228 is invisible. >0 means lines indented more than this value are
1229 invisible. */
1230 it->selective = (INTEGERP (current_buffer->selective_display)
1231 ? XFASTINT (current_buffer->selective_display)
1232 : (!NILP (current_buffer->selective_display)
1233 ? -1 : 0));
1234 it->selective_display_ellipsis_p
1235 = !NILP (current_buffer->selective_display_ellipses);
1236
1237 /* Display table to use. */
1238 it->dp = window_display_table (w);
1239
1240 /* Are multibyte characters enabled in current_buffer? */
1241 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1242
1243 /* Non-zero if we should highlight the region. */
1244 highlight_region_p
1245 = (!NILP (Vtransient_mark_mode)
1246 && !NILP (current_buffer->mark_active)
1247 && XMARKER (current_buffer->mark)->buffer != 0);
1248
1249 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
1250 start and end of a visible region in window IT->w. Set both to
1251 -1 to indicate no region. */
1252 if (highlight_region_p
1253 /* Maybe highlight only in selected window. */
1254 && (/* Either show region everywhere. */
1255 highlight_nonselected_windows
1256 /* Or show region in the selected window. */
1257 || w == XWINDOW (selected_window)
1258 /* Or show the region if we are in the mini-buffer and W is
1259 the window the mini-buffer refers to. */
1260 || (MINI_WINDOW_P (XWINDOW (selected_window))
1261 && w == XWINDOW (Vminibuf_scroll_window))))
1262 {
1263 int charpos = marker_position (current_buffer->mark);
1264 it->region_beg_charpos = min (PT, charpos);
1265 it->region_end_charpos = max (PT, charpos);
1266 }
1267 else
1268 it->region_beg_charpos = it->region_end_charpos = -1;
1269
1270 /* Get the position at which the redisplay_end_trigger hook should
1271 be run, if it is to be run at all. */
1272 if (MARKERP (w->redisplay_end_trigger)
1273 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
1274 it->redisplay_end_trigger_charpos
1275 = marker_position (w->redisplay_end_trigger);
1276 else if (INTEGERP (w->redisplay_end_trigger))
1277 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
1278
1279 /* Correct bogus values of tab_width. */
1280 it->tab_width = XINT (current_buffer->tab_width);
1281 if (it->tab_width <= 0 || it->tab_width > 1000)
1282 it->tab_width = 8;
1283
1284 /* Are lines in the display truncated? */
1285 it->truncate_lines_p
1286 = (base_face_id != DEFAULT_FACE_ID
1287 || XINT (it->w->hscroll)
1288 || (truncate_partial_width_windows
1289 && !WINDOW_FULL_WIDTH_P (it->w))
1290 || !NILP (current_buffer->truncate_lines));
1291
1292 /* Get dimensions of truncation and continuation glyphs. These are
1293 displayed as bitmaps under X, so we don't need them for such
1294 frames. */
1295 if (!FRAME_WINDOW_P (it->f))
1296 {
1297 if (it->truncate_lines_p)
1298 {
1299 /* We will need the truncation glyph. */
1300 xassert (it->glyph_row == NULL);
1301 produce_special_glyphs (it, IT_TRUNCATION);
1302 it->truncation_pixel_width = it->pixel_width;
1303 }
1304 else
1305 {
1306 /* We will need the continuation glyph. */
1307 xassert (it->glyph_row == NULL);
1308 produce_special_glyphs (it, IT_CONTINUATION);
1309 it->continuation_pixel_width = it->pixel_width;
1310 }
1311
1312 /* Reset these values to zero becaue the produce_special_glyphs
1313 above has changed them. */
1314 it->pixel_width = it->ascent = it->descent = 0;
312246d1 1315 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
1316 }
1317
1318 /* Set this after getting the dimensions of truncation and
1319 continuation glyphs, so that we don't produce glyphs when calling
1320 produce_special_glyphs, above. */
1321 it->glyph_row = row;
1322 it->area = TEXT_AREA;
1323
1324 /* Get the dimensions of the display area. The display area
1325 consists of the visible window area plus a horizontally scrolled
1326 part to the left of the window. All x-values are relative to the
1327 start of this total display area. */
1328 if (base_face_id != DEFAULT_FACE_ID)
1329 {
1330 /* Mode lines, menu bar in terminal frames. */
1331 it->first_visible_x = 0;
1332 it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
1333 }
1334 else
1335 {
1336 it->first_visible_x
1337 = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
1338 it->last_visible_x = (it->first_visible_x
1339 + window_box_width (w, TEXT_AREA));
1340
1341 /* If we truncate lines, leave room for the truncator glyph(s) at
1342 the right margin. Otherwise, leave room for the continuation
1343 glyph(s). Truncation and continuation glyphs are not inserted
1344 for window-based redisplay. */
1345 if (!FRAME_WINDOW_P (it->f))
1346 {
1347 if (it->truncate_lines_p)
1348 it->last_visible_x -= it->truncation_pixel_width;
1349 else
1350 it->last_visible_x -= it->continuation_pixel_width;
1351 }
1352
045dee35
GM
1353 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
1354 it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
1355 }
1356
1357 /* Leave room for a border glyph. */
1358 if (!FRAME_WINDOW_P (it->f)
1359 && !WINDOW_RIGHTMOST_P (it->w))
1360 it->last_visible_x -= 1;
1361
1362 it->last_visible_y = window_text_bottom_y (w);
1363
1364 /* For mode lines and alike, arrange for the first glyph having a
1365 left box line if the face specifies a box. */
1366 if (base_face_id != DEFAULT_FACE_ID)
1367 {
1368 struct face *face;
1369
1370 it->face_id = base_face_id;
1371
1372 /* If we have a boxed mode line, make the first character appear
1373 with a left box line. */
1374 face = FACE_FROM_ID (it->f, base_face_id);
1375 if (face->box != FACE_NO_BOX)
1376 it->start_of_box_run_p = 1;
1377 }
1378
1379 /* If a buffer position was specified, set the iterator there,
1380 getting overlays and face properties from that position. */
1381 if (charpos > 0)
1382 {
1383 it->end_charpos = ZV;
1384 it->face_id = -1;
1385 IT_CHARPOS (*it) = charpos;
1386
1387 /* Compute byte position if not specified. */
1388 if (bytepos <= 0)
1389 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
1390 else
1391 IT_BYTEPOS (*it) = bytepos;
1392
1393 /* Compute faces etc. */
1394 reseat (it, it->current.pos, 1);
1395 }
1396
1397 CHECK_IT (it);
1398}
1399
1400
1401/* Initialize IT for the display of window W with window start POS. */
1402
1403void
1404start_display (it, w, pos)
1405 struct it *it;
1406 struct window *w;
1407 struct text_pos pos;
1408{
1409 int start_at_line_beg_p;
1410 struct glyph_row *row;
045dee35 1411 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
1412 int first_y;
1413
1414 row = w->desired_matrix->rows + first_vpos;
1415 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
1416 first_y = it->current_y;
1417
1418 /* If window start is not at a line start, move back to the line
1419 start. This makes sure that we take continuation lines into
1420 account. */
1421 start_at_line_beg_p = (CHARPOS (pos) == BEGV
1422 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
1423 if (!start_at_line_beg_p)
1424 reseat_at_previous_visible_line_start (it);
1425
5f5c8ee5
GM
1426 /* If window start is not at a line start, skip forward to POS to
1427 get the correct continuation_lines_width and current_x. */
1428 if (!start_at_line_beg_p)
1429 {
1430 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
1431
1432 /* If lines are continued, this line may end in the middle of a
1433 multi-glyph character (e.g. a control character displayed as
1434 \003, or in the middle of an overlay string). In this case
1435 move_it_to above will not have taken us to the start of
1436 the continuation line but to the end of the continued line. */
1437 if (!it->truncate_lines_p && it->current_x > 0)
1438 {
1439 if (it->current.dpvec_index >= 0
1440 || it->current.overlay_string_index >= 0)
1441 {
1442 set_iterator_to_next (it);
1443 move_it_in_display_line_to (it, -1, -1, 0);
1444 }
1445 it->continuation_lines_width += it->current_x;
1446 }
1447
1448 it->current_y = first_y;
1449 it->vpos = 0;
1450 it->current_x = it->hpos = 0;
1451 }
1452
1453#if 0 /* Don't assert the following because start_display is sometimes
1454 called intentionally with a window start that is not at a
1455 line start. Please leave this code in as a comment. */
1456
1457 /* Window start should be on a line start, now. */
1458 xassert (it->continuation_lines_width
1459 || IT_CHARPOS (it) == BEGV
1460 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
1461#endif /* 0 */
1462}
1463
1464
1465/* Initialize IT for stepping through current_buffer in window W,
1466 starting at position POS that includes overlay string and display
1467 vector/ control character translation position information. */
1468
1469static void
1470init_from_display_pos (it, w, pos)
1471 struct it *it;
1472 struct window *w;
1473 struct display_pos *pos;
1474{
1475 /* Keep in mind: the call to reseat in init_iterator skips invisible
1476 text, so we might end up at a position different from POS. This
1477 is only a problem when POS is a row start after a newline and an
1478 overlay starts there with an after-string, and the overlay has an
1479 invisible property. Since we don't skip invisible text in
1480 display_line and elsewhere immediately after consuming the
1481 newline before the row start, such a POS will not be in a string,
1482 but the call to init_iterator below will move us to the
1483 after-string. */
1484 init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos),
1485 NULL, DEFAULT_FACE_ID);
1486
1487 /* If position is within an overlay string, set up IT to
1488 the right overlay string. */
1489 if (pos->overlay_string_index >= 0)
1490 {
1491 int relative_index;
1492
1493 /* We already have the first chunk of overlay strings in
1494 IT->overlay_strings. Load more until the one for
1495 pos->overlay_string_index is in IT->overlay_strings. */
1496 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
1497 {
1498 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
1499 it->current.overlay_string_index = 0;
1500 while (n--)
1501 {
1502 load_overlay_strings (it);
1503 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
1504 }
1505 }
1506
1507 it->current.overlay_string_index = pos->overlay_string_index;
1508 relative_index = (it->current.overlay_string_index
1509 % OVERLAY_STRING_CHUNK_SIZE);
1510 it->string = it->overlay_strings[relative_index];
1511 it->current.string_pos = pos->string_pos;
1512 it->method = next_element_from_string;
1513 }
1514 else if (CHARPOS (pos->string_pos) >= 0)
1515 {
1516 /* Recorded position is not in an overlay string, but in another
1517 string. This can only be a string from a `display' property.
1518 IT should already be filled with that string. */
1519 it->current.string_pos = pos->string_pos;
1520 xassert (STRINGP (it->string));
1521 }
1522
1523 /* Restore position in display vector translations or control
1524 character translations. */
1525 if (pos->dpvec_index >= 0)
1526 {
1527 /* This fills IT->dpvec. */
1528 get_next_display_element (it);
1529 xassert (it->dpvec && it->current.dpvec_index == 0);
1530 it->current.dpvec_index = pos->dpvec_index;
1531 }
1532
1533 CHECK_IT (it);
1534}
1535
1536
1537/* Initialize IT for stepping through current_buffer in window W
1538 starting at ROW->start. */
1539
1540static void
1541init_to_row_start (it, w, row)
1542 struct it *it;
1543 struct window *w;
1544 struct glyph_row *row;
1545{
1546 init_from_display_pos (it, w, &row->start);
1547 it->continuation_lines_width = row->continuation_lines_width;
1548 CHECK_IT (it);
1549}
1550
1551
1552/* Initialize IT for stepping through current_buffer in window W
1553 starting in the line following ROW, i.e. starting at ROW->end. */
1554
1555static void
1556init_to_row_end (it, w, row)
1557 struct it *it;
1558 struct window *w;
1559 struct glyph_row *row;
1560{
1561 init_from_display_pos (it, w, &row->end);
1562
1563 if (row->continued_p)
1564 it->continuation_lines_width = (row->continuation_lines_width
1565 + row->pixel_width);
1566 CHECK_IT (it);
1567}
1568
1569
1570
1571\f
1572/***********************************************************************
1573 Text properties
1574 ***********************************************************************/
1575
1576/* Called when IT reaches IT->stop_charpos. Handle text property and
1577 overlay changes. Set IT->stop_charpos to the next position where
1578 to stop. */
1579
1580static void
1581handle_stop (it)
1582 struct it *it;
1583{
1584 enum prop_handled handled;
1585 int handle_overlay_change_p = 1;
1586 struct props *p;
1587
1588 it->dpvec = NULL;
1589 it->current.dpvec_index = -1;
1590
1591 do
1592 {
1593 handled = HANDLED_NORMALLY;
1594
1595 /* Call text property handlers. */
1596 for (p = it_props; p->handler; ++p)
1597 {
1598 handled = p->handler (it);
1599
1600 if (handled == HANDLED_RECOMPUTE_PROPS)
1601 break;
1602 else if (handled == HANDLED_RETURN)
1603 return;
1604 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
1605 handle_overlay_change_p = 0;
1606 }
1607
1608 if (handled != HANDLED_RECOMPUTE_PROPS)
1609 {
1610 /* Don't check for overlay strings below when set to deliver
1611 characters from a display vector. */
1612 if (it->method == next_element_from_display_vector)
1613 handle_overlay_change_p = 0;
1614
1615 /* Handle overlay changes. */
1616 if (handle_overlay_change_p)
1617 handled = handle_overlay_change (it);
1618
1619 /* Determine where to stop next. */
1620 if (handled == HANDLED_NORMALLY)
1621 compute_stop_pos (it);
1622 }
1623 }
1624 while (handled == HANDLED_RECOMPUTE_PROPS);
1625}
1626
1627
1628/* Compute IT->stop_charpos from text property and overlay change
1629 information for IT's current position. */
1630
1631static void
1632compute_stop_pos (it)
1633 struct it *it;
1634{
1635 register INTERVAL iv, next_iv;
1636 Lisp_Object object, limit, position;
1637
1638 /* If nowhere else, stop at the end. */
1639 it->stop_charpos = it->end_charpos;
1640
1641 if (STRINGP (it->string))
1642 {
1643 /* Strings are usually short, so don't limit the search for
1644 properties. */
1645 object = it->string;
1646 limit = Qnil;
1647 XSETFASTINT (position, IT_STRING_CHARPOS (*it));
1648 }
1649 else
1650 {
1651 int charpos;
1652
1653 /* If next overlay change is in front of the current stop pos
1654 (which is IT->end_charpos), stop there. Note: value of
1655 next_overlay_change is point-max if no overlay change
1656 follows. */
1657 charpos = next_overlay_change (IT_CHARPOS (*it));
1658 if (charpos < it->stop_charpos)
1659 it->stop_charpos = charpos;
1660
1661 /* If showing the region, we have to stop at the region
1662 start or end because the face might change there. */
1663 if (it->region_beg_charpos > 0)
1664 {
1665 if (IT_CHARPOS (*it) < it->region_beg_charpos)
1666 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
1667 else if (IT_CHARPOS (*it) < it->region_end_charpos)
1668 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
1669 }
1670
1671 /* Set up variables for computing the stop position from text
1672 property changes. */
1673 XSETBUFFER (object, current_buffer);
1674 XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
1675 XSETFASTINT (position, IT_CHARPOS (*it));
1676
1677 }
1678
1679 /* Get the interval containing IT's position. Value is a null
1680 interval if there isn't such an interval. */
1681 iv = validate_interval_range (object, &position, &position, 0);
1682 if (!NULL_INTERVAL_P (iv))
1683 {
1684 Lisp_Object values_here[LAST_PROP_IDX];
1685 struct props *p;
1686
1687 /* Get properties here. */
1688 for (p = it_props; p->handler; ++p)
1689 values_here[p->idx] = textget (iv->plist, *p->name);
1690
1691 /* Look for an interval following iv that has different
1692 properties. */
1693 for (next_iv = next_interval (iv);
1694 (!NULL_INTERVAL_P (next_iv)
1695 && (NILP (limit)
1696 || XFASTINT (limit) > next_iv->position));
1697 next_iv = next_interval (next_iv))
1698 {
1699 for (p = it_props; p->handler; ++p)
1700 {
1701 Lisp_Object new_value;
1702
1703 new_value = textget (next_iv->plist, *p->name);
1704 if (!EQ (values_here[p->idx], new_value))
1705 break;
1706 }
1707
1708 if (p->handler)
1709 break;
1710 }
1711
1712 if (!NULL_INTERVAL_P (next_iv))
1713 {
1714 if (INTEGERP (limit)
1715 && next_iv->position >= XFASTINT (limit))
1716 /* No text property change up to limit. */
1717 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
1718 else
1719 /* Text properties change in next_iv. */
1720 it->stop_charpos = min (it->stop_charpos, next_iv->position);
1721 }
1722 }
1723
1724 xassert (STRINGP (it->string)
1725 || (it->stop_charpos >= BEGV
1726 && it->stop_charpos >= IT_CHARPOS (*it)));
1727}
1728
1729
1730/* Return the position of the next overlay change after POS in
1731 current_buffer. Value is point-max if no overlay change
1732 follows. This is like `next-overlay-change' but doesn't use
1733 xmalloc. */
1734
1735static int
1736next_overlay_change (pos)
1737 int pos;
1738{
1739 int noverlays;
1740 int endpos;
1741 Lisp_Object *overlays;
1742 int len;
1743 int i;
1744
1745 /* Get all overlays at the given position. */
1746 len = 10;
1747 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
1748 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
1749 if (noverlays > len)
1750 {
1751 len = noverlays;
1752 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
1753 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
1754 }
1755
1756 /* If any of these overlays ends before endpos,
1757 use its ending point instead. */
1758 for (i = 0; i < noverlays; ++i)
1759 {
1760 Lisp_Object oend;
1761 int oendpos;
1762
1763 oend = OVERLAY_END (overlays[i]);
1764 oendpos = OVERLAY_POSITION (oend);
1765 endpos = min (endpos, oendpos);
1766 }
1767
1768 return endpos;
1769}
1770
1771
1772\f
1773/***********************************************************************
1774 Fontification
1775 ***********************************************************************/
1776
1777/* Handle changes in the `fontified' property of the current buffer by
1778 calling hook functions from Qfontification_functions to fontify
1779 regions of text. */
1780
1781static enum prop_handled
1782handle_fontified_prop (it)
1783 struct it *it;
1784{
1785 Lisp_Object prop, pos;
1786 enum prop_handled handled = HANDLED_NORMALLY;
2bf6fa4b 1787 struct gcpro gcpro1;
5f5c8ee5
GM
1788
1789 /* Get the value of the `fontified' property at IT's current buffer
1790 position. (The `fontified' property doesn't have a special
1791 meaning in strings.) If the value is nil, call functions from
1792 Qfontification_functions. */
1793 if (!STRINGP (it->string)
1794 && it->s == NULL
1795 && !NILP (Vfontification_functions)
1796 && (pos = make_number (IT_CHARPOS (*it)),
1797 prop = Fget_char_property (pos, Qfontified, Qnil),
1798 NILP (prop)))
1799 {
1800 Lisp_Object args[2];
1801
2bf6fa4b 1802 GCPRO1 (pos);
5f5c8ee5
GM
1803 /* Run the hook functions. */
1804 args[0] = Qfontification_functions;
1805 args[1] = pos;
1806 Frun_hook_with_args (make_number (2), args);
1807
1808 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
1809 something. This avoids an endless loop if they failed to
1810 fontify the text for which reason ever. */
1811 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
1812 handled = HANDLED_RECOMPUTE_PROPS;
2bf6fa4b 1813 UNGCPRO;
5f5c8ee5
GM
1814 }
1815
1816 return handled;
1817}
1818
1819
1820\f
1821/***********************************************************************
1822 Faces
1823 ***********************************************************************/
1824
1825/* Set up iterator IT from face properties at its current position.
1826 Called from handle_stop. */
1827
1828static enum prop_handled
1829handle_face_prop (it)
1830 struct it *it;
1831{
1832 int new_face_id, next_stop;
1833
1834 if (!STRINGP (it->string))
1835 {
1836 new_face_id
1837 = face_at_buffer_position (it->w,
1838 IT_CHARPOS (*it),
1839 it->region_beg_charpos,
1840 it->region_end_charpos,
1841 &next_stop,
1842 (IT_CHARPOS (*it)
1843 + TEXT_PROP_DISTANCE_LIMIT),
1844 0);
1845
1846 /* Is this a start of a run of characters with box face?
1847 Caveat: this can be called for a freshly initialized
1848 iterator; face_id is -1 is this case. We know that the new
1849 face will not change until limit, i.e. if the new face has a
1850 box, all characters up to limit will have one. But, as
1851 usual, we don't know whether limit is really the end. */
1852 if (new_face_id != it->face_id)
1853 {
1854 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1855
1856 /* If new face has a box but old face has not, this is
1857 the start of a run of characters with box, i.e. it has
1858 a shadow on the left side. The value of face_id of the
1859 iterator will be -1 if this is the initial call that gets
1860 the face. In this case, we have to look in front of IT's
1861 position and see whether there is a face != new_face_id. */
1862 it->start_of_box_run_p
1863 = (new_face->box != FACE_NO_BOX
1864 && (it->face_id >= 0
1865 || IT_CHARPOS (*it) == BEG
1866 || new_face_id != face_before_it_pos (it)));
1867 it->face_box_p = new_face->box != FACE_NO_BOX;
1868 }
1869 }
1870 else
1871 {
1872 new_face_id
1873 = face_at_string_position (it->w,
1874 it->string,
1875 IT_STRING_CHARPOS (*it),
1876 (it->current.overlay_string_index >= 0
1877 ? IT_CHARPOS (*it)
1878 : 0),
1879 it->region_beg_charpos,
1880 it->region_end_charpos,
1881 &next_stop,
1882 it->base_face_id);
1883
1884#if 0 /* This shouldn't be neccessary. Let's check it. */
1885 /* If IT is used to display a mode line we would really like to
1886 use the mode line face instead of the frame's default face. */
1887 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
1888 && new_face_id == DEFAULT_FACE_ID)
1889 new_face_id = MODE_LINE_FACE_ID;
1890#endif
1891
1892 /* Is this a start of a run of characters with box? Caveat:
1893 this can be called for a freshly allocated iterator; face_id
1894 is -1 is this case. We know that the new face will not
1895 change until the next check pos, i.e. if the new face has a
1896 box, all characters up to that position will have a
1897 box. But, as usual, we don't know whether that position
1898 is really the end. */
1899 if (new_face_id != it->face_id)
1900 {
1901 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1902 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
1903
1904 /* If new face has a box but old face hasn't, this is the
1905 start of a run of characters with box, i.e. it has a
1906 shadow on the left side. */
1907 it->start_of_box_run_p
1908 = new_face->box && (old_face == NULL || !old_face->box);
1909 it->face_box_p = new_face->box != FACE_NO_BOX;
1910 }
1911 }
1912
1913 it->face_id = new_face_id;
1914 it->charset = CHARSET_ASCII;
1915 return HANDLED_NORMALLY;
1916}
1917
1918
1919/* Compute the face one character before or after the current position
1920 of IT. BEFORE_P non-zero means get the face in front of IT's
1921 position. Value is the id of the face. */
1922
1923static int
1924face_before_or_after_it_pos (it, before_p)
1925 struct it *it;
1926 int before_p;
1927{
1928 int face_id, limit;
1929 int next_check_charpos;
1930 struct text_pos pos;
1931
1932 xassert (it->s == NULL);
1933
1934 if (STRINGP (it->string))
1935 {
1936 /* No face change past the end of the string (for the case
1937 we are padding with spaces). No face change before the
1938 string start. */
1939 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size
1940 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
1941 return it->face_id;
1942
1943 /* Set pos to the position before or after IT's current position. */
1944 if (before_p)
1945 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
1946 else
1947 pos = string_pos (IT_STRING_CHARPOS (*it) + 1, it->string);
1948
1949 /* Get the face for ASCII, or unibyte. */
1950 face_id
1951 = face_at_string_position (it->w,
1952 it->string,
1953 CHARPOS (pos),
1954 (it->current.overlay_string_index >= 0
1955 ? IT_CHARPOS (*it)
1956 : 0),
1957 it->region_beg_charpos,
1958 it->region_end_charpos,
1959 &next_check_charpos,
1960 it->base_face_id);
1961
1962 /* Correct the face for charsets different from ASCII. Do it
1963 for the multibyte case only. The face returned above is
1964 suitable for unibyte text if IT->string is unibyte. */
1965 if (STRING_MULTIBYTE (it->string))
1966 {
1967 unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
1968 int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
1969 int c, len, charset;
1970
4fdb80f2 1971 c = string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1972 charset = CHAR_CHARSET (c);
1973 if (charset != CHARSET_ASCII)
1974 face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
1975 }
1976 }
1977 else
1978 {
70851746
GM
1979 if ((IT_CHARPOS (*it) >= ZV && !before_p)
1980 || (IT_CHARPOS (*it) <= BEGV && before_p))
1981 return it->face_id;
1982
5f5c8ee5
GM
1983 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
1984 pos = it->current.pos;
1985
1986 if (before_p)
1987 DEC_TEXT_POS (pos);
1988 else
1989 INC_TEXT_POS (pos);
70851746 1990
5f5c8ee5
GM
1991 /* Determine face for CHARSET_ASCII, or unibyte. */
1992 face_id = face_at_buffer_position (it->w,
1993 CHARPOS (pos),
1994 it->region_beg_charpos,
1995 it->region_end_charpos,
1996 &next_check_charpos,
1997 limit, 0);
1998
1999 /* Correct the face for charsets different from ASCII. Do it
2000 for the multibyte case only. The face returned above is
2001 suitable for unibyte text if current_buffer is unibyte. */
2002 if (it->multibyte_p)
2003 {
2004 int charset = charset_at_position (pos);
2005 if (charset != CHARSET_ASCII)
2006 face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
2007 }
2008 }
2009
2010 return face_id;
2011}
2012
2013
2014\f
2015/***********************************************************************
2016 Invisible text
2017 ***********************************************************************/
2018
2019/* Set up iterator IT from invisible properties at its current
2020 position. Called from handle_stop. */
2021
2022static enum prop_handled
2023handle_invisible_prop (it)
2024 struct it *it;
2025{
2026 enum prop_handled handled = HANDLED_NORMALLY;
2027
2028 if (STRINGP (it->string))
2029 {
2030 extern Lisp_Object Qinvisible;
2031 Lisp_Object prop, end_charpos, limit, charpos;
2032
2033 /* Get the value of the invisible text property at the
2034 current position. Value will be nil if there is no such
2035 property. */
2036 XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
2037 prop = Fget_text_property (charpos, Qinvisible, it->string);
2038
2039 if (!NILP (prop))
2040 {
2041 handled = HANDLED_RECOMPUTE_PROPS;
2042
2043 /* Get the position at which the next change of the
2044 invisible text property can be found in IT->string.
2045 Value will be nil if the property value is the same for
2046 all the rest of IT->string. */
2047 XSETINT (limit, XSTRING (it->string)->size);
2048 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2049 it->string, limit);
2050
2051 /* Text at current position is invisible. The next
2052 change in the property is at position end_charpos.
2053 Move IT's current position to that position. */
2054 if (INTEGERP (end_charpos)
2055 && XFASTINT (end_charpos) < XFASTINT (limit))
2056 {
2057 struct text_pos old;
2058 old = it->current.string_pos;
2059 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
2060 compute_string_pos (&it->current.string_pos, old, it->string);
2061 }
2062 else
2063 {
2064 /* The rest of the string is invisible. If this is an
2065 overlay string, proceed with the next overlay string
2066 or whatever comes and return a character from there. */
2067 if (it->current.overlay_string_index >= 0)
2068 {
2069 next_overlay_string (it);
2070 /* Don't check for overlay strings when we just
2071 finished processing them. */
2072 handled = HANDLED_OVERLAY_STRING_CONSUMED;
2073 }
2074 else
2075 {
2076 struct Lisp_String *s = XSTRING (it->string);
2077 IT_STRING_CHARPOS (*it) = s->size;
2078 IT_STRING_BYTEPOS (*it) = STRING_BYTES (s);
2079 }
2080 }
2081 }
2082 }
2083 else
2084 {
2085 int visible_p, newpos, next_stop;
2086 Lisp_Object pos, prop;
2087
2088 /* First of all, is there invisible text at this position? */
2089 XSETFASTINT (pos, IT_CHARPOS (*it));
2090 prop = Fget_char_property (pos, Qinvisible, it->window);
2091
2092 /* If we are on invisible text, skip over it. */
2093 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2094 {
2095 /* Record whether we have to display an ellipsis for the
2096 invisible text. */
2097 int display_ellipsis_p
2098 = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
2099
2100 handled = HANDLED_RECOMPUTE_PROPS;
2101
2102 /* Loop skipping over invisible text. The loop is left at
2103 ZV or with IT on the first char being visible again. */
2104 do
2105 {
2106 /* Try to skip some invisible text. Return value is the
2107 position reached which can be equal to IT's position
2108 if there is nothing invisible here. This skips both
2109 over invisible text properties and overlays with
2110 invisible property. */
2111 newpos = skip_invisible (IT_CHARPOS (*it),
2112 &next_stop, ZV, it->window);
2113
2114 /* If we skipped nothing at all we weren't at invisible
2115 text in the first place. If everything to the end of
2116 the buffer was skipped, end the loop. */
2117 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
2118 visible_p = 1;
2119 else
2120 {
2121 /* We skipped some characters but not necessarily
2122 all there are. Check if we ended up on visible
2123 text. Fget_char_property returns the property of
2124 the char before the given position, i.e. if we
2125 get visible_p = 1, this means that the char at
2126 newpos is visible. */
2127 XSETFASTINT (pos, newpos);
2128 prop = Fget_char_property (pos, Qinvisible, it->window);
2129 visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
2130 }
2131
2132 /* If we ended up on invisible text, proceed to
2133 skip starting with next_stop. */
2134 if (!visible_p)
2135 IT_CHARPOS (*it) = next_stop;
2136 }
2137 while (!visible_p);
2138
2139 /* The position newpos is now either ZV or on visible text. */
2140 IT_CHARPOS (*it) = newpos;
2141 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2142
2143 /* Maybe return `...' next for the end of the invisible text. */
2144 if (display_ellipsis_p)
2145 {
2146 if (it->dp
2147 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
2148 {
2149 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
2150 it->dpvec = v->contents;
2151 it->dpend = v->contents + v->size;
2152 }
2153 else
2154 {
2155 /* Default `...'. */
2156 it->dpvec = default_invis_vector;
2157 it->dpend = default_invis_vector + 3;
2158 }
2159
2160 /* The ellipsis display does not replace the display of
2161 the character at the new position. Indicate this by
2162 setting IT->dpvec_char_len to zero. */
2163 it->dpvec_char_len = 0;
2164
2165 it->current.dpvec_index = 0;
2166 it->method = next_element_from_display_vector;
2167 }
2168 }
2169 }
2170
2171 return handled;
2172}
2173
2174
2175\f
2176/***********************************************************************
2177 'display' property
2178 ***********************************************************************/
2179
2180/* Set up iterator IT from `display' property at its current position.
2181 Called from handle_stop. */
2182
2183static enum prop_handled
2184handle_display_prop (it)
2185 struct it *it;
2186{
2187 Lisp_Object prop, object;
2188 struct text_pos *position;
2189 int space_or_image_found_p;
2190
2191 if (STRINGP (it->string))
2192 {
2193 object = it->string;
2194 position = &it->current.string_pos;
2195 }
2196 else
2197 {
2198 object = Qnil;
2199 position = &it->current.pos;
2200 }
2201
2202 /* Reset those iterator values set from display property values. */
2203 it->font_height = Qnil;
2204 it->space_width = Qnil;
2205 it->voffset = 0;
2206
2207 /* We don't support recursive `display' properties, i.e. string
2208 values that have a string `display' property, that have a string
2209 `display' property etc. */
2210 if (!it->string_from_display_prop_p)
2211 it->area = TEXT_AREA;
2212
2213 prop = Fget_char_property (make_number (position->charpos),
2214 Qdisplay, object);
2215 if (NILP (prop))
2216 return HANDLED_NORMALLY;
2217
2218 space_or_image_found_p = 0;
f3751a65
GM
2219 if (CONSP (prop)
2220 && CONSP (XCAR (prop))
2221 && !EQ (Qmargin, XCAR (XCAR (prop))))
5f5c8ee5 2222 {
f3751a65 2223 /* A list of sub-properties. */
5f5c8ee5
GM
2224 while (CONSP (prop))
2225 {
2226 if (handle_single_display_prop (it, XCAR (prop), object, position))
2227 space_or_image_found_p = 1;
2228 prop = XCDR (prop);
2229 }
2230 }
2231 else if (VECTORP (prop))
2232 {
2233 int i;
2234 for (i = 0; i < XVECTOR (prop)->size; ++i)
2235 if (handle_single_display_prop (it, XVECTOR (prop)->contents[i],
2236 object, position))
2237 space_or_image_found_p = 1;
2238 }
2239 else
2240 {
2241 if (handle_single_display_prop (it, prop, object, position))
2242 space_or_image_found_p = 1;
2243 }
2244
2245 return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY;
2246}
2247
2248
6c577098 2249/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
2250 at START_POS in OBJECT. */
2251
2252static struct text_pos
2253display_prop_end (it, object, start_pos)
2254 struct it *it;
2255 Lisp_Object object;
2256 struct text_pos start_pos;
2257{
2258 Lisp_Object end;
2259 struct text_pos end_pos;
5f5c8ee5 2260
6c577098
GM
2261 end = next_single_char_property_change (make_number (CHARPOS (start_pos)),
2262 Qdisplay, object, Qnil);
2263 CHARPOS (end_pos) = XFASTINT (end);
2264 if (STRINGP (object))
5f5c8ee5
GM
2265 compute_string_pos (&end_pos, start_pos, it->string);
2266 else
6c577098 2267 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
2268
2269 return end_pos;
2270}
2271
2272
2273/* Set up IT from a single `display' sub-property value PROP. OBJECT
2274 is the object in which the `display' property was found. *POSITION
2275 is the position at which it was found.
2276
2277 If PROP is a `space' or `image' sub-property, set *POSITION to the
2278 end position of the `display' property.
2279
2280 Value is non-zero if a `space' or `image' property value was found. */
2281
2282static int
2283handle_single_display_prop (it, prop, object, position)
2284 struct it *it;
2285 Lisp_Object prop;
2286 Lisp_Object object;
2287 struct text_pos *position;
2288{
2289 Lisp_Object value;
2290 int space_or_image_found_p = 0;
2291
2292 Lisp_Object form;
2293
d3acf96b 2294 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
5a4c88c4 2295 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 2296 form = Qt;
d3acf96b 2297 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
2298 {
2299 prop = XCDR (prop);
2300 if (!CONSP (prop))
2301 return 0;
2302 form = XCAR (prop);
2303 prop = XCDR (prop);
5f5c8ee5
GM
2304 }
2305
2306 if (!NILP (form) && !EQ (form, Qt))
2307 {
2308 struct gcpro gcpro1;
2309 struct text_pos end_pos, pt;
2310
2311 end_pos = display_prop_end (it, object, *position);
2312 GCPRO1 (form);
2313
2314 /* Temporarily set point to the end position, and then evaluate
2315 the form. This makes `(eolp)' work as FORM. */
2316 CHARPOS (pt) = PT;
2317 BYTEPOS (pt) = PT_BYTE;
2318 TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
2319 form = eval_form (form);
2320 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
2321 UNGCPRO;
2322 }
2323
2324 if (NILP (form))
2325 return 0;
2326
2327 if (CONSP (prop)
2328 && EQ (XCAR (prop), Qheight)
2329 && CONSP (XCDR (prop)))
2330 {
2331 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2332 return 0;
2333
2334 /* `(height HEIGHT)'. */
2335 it->font_height = XCAR (XCDR (prop));
2336 if (!NILP (it->font_height))
2337 {
2338 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2339 int new_height = -1;
2340
2341 if (CONSP (it->font_height)
2342 && (EQ (XCAR (it->font_height), Qplus)
2343 || EQ (XCAR (it->font_height), Qminus))
2344 && CONSP (XCDR (it->font_height))
2345 && INTEGERP (XCAR (XCDR (it->font_height))))
2346 {
2347 /* `(+ N)' or `(- N)' where N is an integer. */
2348 int steps = XINT (XCAR (XCDR (it->font_height)));
2349 if (EQ (XCAR (it->font_height), Qplus))
2350 steps = - steps;
2351 it->face_id = smaller_face (it->f, it->face_id, steps);
2352 }
2353 else if (SYMBOLP (it->font_height))
2354 {
2355 /* Call function with current height as argument.
2356 Value is the new height. */
2357 Lisp_Object form, height;
2358 struct gcpro gcpro1;
2359
2360 height = face->lface[LFACE_HEIGHT_INDEX];
2361 form = Fcons (it->font_height, Fcons (height, Qnil));
2362 GCPRO1 (form);
2363 height = eval_form (form);
2364 if (NUMBERP (height))
2365 new_height = XFLOATINT (height);
2366 UNGCPRO;
2367 }
2368 else if (NUMBERP (it->font_height))
2369 {
2370 /* Value is a multiple of the canonical char height. */
2371 struct face *face;
2372
2373 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
2374 new_height = (XFLOATINT (it->font_height)
2375 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
2376 }
2377 else
2378 {
2379 /* Evaluate IT->font_height with `height' bound to the
2380 current specified height to get the new height. */
2381 Lisp_Object value;
2382 int count = specpdl_ptr - specpdl;
2383
2384 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
2385 value = eval_form (it->font_height);
2386 unbind_to (count, Qnil);
2387
2388 if (NUMBERP (value))
2389 new_height = XFLOATINT (value);
2390 }
2391
2392 if (new_height > 0)
2393 it->face_id = face_with_height (it->f, it->face_id, new_height);
2394 }
2395 }
2396 else if (CONSP (prop)
2397 && EQ (XCAR (prop), Qspace_width)
2398 && CONSP (XCDR (prop)))
2399 {
2400 /* `(space_width WIDTH)'. */
2401 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2402 return 0;
2403
2404 value = XCAR (XCDR (prop));
2405 if (NUMBERP (value) && XFLOATINT (value) > 0)
2406 it->space_width = value;
2407 }
2408 else if (CONSP (prop)
2409 && EQ (XCAR (prop), Qraise)
2410 && CONSP (XCDR (prop)))
2411 {
2412#ifdef HAVE_WINDOW_SYSTEM
2413 /* `(raise FACTOR)'. */
2414 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2415 return 0;
2416
2417 value = XCAR (XCDR (prop));
2418 if (NUMBERP (value))
2419 {
2420 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2421 it->voffset = - (XFLOATINT (value)
2422 * (face->font->ascent + face->font->descent));
2423 }
2424#endif /* HAVE_WINDOW_SYSTEM */
2425 }
2426 else if (!it->string_from_display_prop_p)
2427 {
f3751a65
GM
2428 /* `((margin left-margin) VALUE)' or `((margin right-margin)
2429 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
2430 Lisp_Object location, value;
2431 struct text_pos start_pos;
2432 int valid_p;
2433
2434 /* Characters having this form of property are not displayed, so
2435 we have to find the end of the property. */
2436 space_or_image_found_p = 1;
2437 start_pos = *position;
2438 *position = display_prop_end (it, object, start_pos);
2439
2440 /* Let's stop at the new position and assume that all
2441 text properties change there. */
2442 it->stop_charpos = position->charpos;
2443
f3751a65
GM
2444 location = Qunbound;
2445 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 2446 {
f3751a65
GM
2447 Lisp_Object tem;
2448
5f5c8ee5 2449 value = XCDR (prop);
f3751a65
GM
2450 if (CONSP (value))
2451 value = XCAR (value);
2452
2453 tem = XCAR (prop);
2454 if (EQ (XCAR (tem), Qmargin)
2455 && (tem = XCDR (tem),
2456 tem = CONSP (tem) ? XCAR (tem) : Qnil,
2457 (NILP (tem)
2458 || EQ (tem, Qleft_margin)
2459 || EQ (tem, Qright_margin))))
2460 location = tem;
5f5c8ee5 2461 }
f3751a65
GM
2462
2463 if (EQ (location, Qunbound))
5f5c8ee5
GM
2464 {
2465 location = Qnil;
2466 value = prop;
2467 }
2468
2469#ifdef HAVE_WINDOW_SYSTEM
2470 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2471 valid_p = STRINGP (value);
2472 else
2473 valid_p = (STRINGP (value)
2474 || (CONSP (value) && EQ (XCAR (value), Qspace))
2475 || valid_image_p (value));
2476#else /* not HAVE_WINDOW_SYSTEM */
2477 valid_p = STRINGP (value);
2478#endif /* not HAVE_WINDOW_SYSTEM */
2479
2480 if ((EQ (location, Qleft_margin)
2481 || EQ (location, Qright_margin)
2482 || NILP (location))
2483 && valid_p)
2484 {
2485 /* Save current settings of IT so that we can restore them
2486 when we are finished with the glyph property value. */
2487 push_it (it);
2488
2489 if (NILP (location))
2490 it->area = TEXT_AREA;
2491 else if (EQ (location, Qleft_margin))
2492 it->area = LEFT_MARGIN_AREA;
2493 else
2494 it->area = RIGHT_MARGIN_AREA;
2495
2496 if (STRINGP (value))
2497 {
2498 it->string = value;
2499 it->multibyte_p = STRING_MULTIBYTE (it->string);
2500 it->current.overlay_string_index = -1;
2501 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2502 it->end_charpos = it->string_nchars
2503 = XSTRING (it->string)->size;
2504 it->method = next_element_from_string;
2505 it->stop_charpos = 0;
2506 it->string_from_display_prop_p = 1;
2507 }
2508 else if (CONSP (value) && EQ (XCAR (value), Qspace))
2509 {
2510 it->method = next_element_from_stretch;
2511 it->object = value;
2512 it->current.pos = it->position = start_pos;
2513 }
2514#ifdef HAVE_WINDOW_SYSTEM
2515 else
2516 {
2517 it->what = IT_IMAGE;
2518 it->image_id = lookup_image (it->f, value);
2519 it->position = start_pos;
2520 it->object = NILP (object) ? it->w->buffer : object;
2521 it->method = next_element_from_image;
2522
2523 /* Say that we don't have consumed the characters with
2524 `display' property yet. The call to pop_it in
2525 set_iterator_to_next will clean this up. */
2526 *position = start_pos;
2527 }
2528#endif /* HAVE_WINDOW_SYSTEM */
2529 }
2530 }
2531
2532 return space_or_image_found_p;
2533}
2534
2535
2536\f
2537/***********************************************************************
2538 Overlay strings
2539 ***********************************************************************/
2540
2541/* The following structure is used to record overlay strings for
2542 later sorting in load_overlay_strings. */
2543
2544struct overlay_entry
2545{
2546 Lisp_Object string;
2547 int priority;
2548 int after_string_p;
2549};
2550
2551
2552/* Set up iterator IT from overlay strings at its current position.
2553 Called from handle_stop. */
2554
2555static enum prop_handled
2556handle_overlay_change (it)
2557 struct it *it;
2558{
2559 /* Overlays are handled in current_buffer only. */
2560 if (STRINGP (it->string))
2561 return HANDLED_NORMALLY;
2562 else
2563 return (get_overlay_strings (it)
2564 ? HANDLED_RECOMPUTE_PROPS
2565 : HANDLED_NORMALLY);
2566}
2567
2568
2569/* Set up the next overlay string for delivery by IT, if there is an
2570 overlay string to deliver. Called by set_iterator_to_next when the
2571 end of the current overlay string is reached. If there are more
2572 overlay strings to display, IT->string and
2573 IT->current.overlay_string_index are set appropriately here.
2574 Otherwise IT->string is set to nil. */
2575
2576static void
2577next_overlay_string (it)
2578 struct it *it;
2579{
2580 ++it->current.overlay_string_index;
2581 if (it->current.overlay_string_index == it->n_overlay_strings)
2582 {
2583 /* No more overlay strings. Restore IT's settings to what
2584 they were before overlay strings were processed, and
2585 continue to deliver from current_buffer. */
2586 pop_it (it);
2587 xassert (it->stop_charpos >= BEGV
2588 && it->stop_charpos <= it->end_charpos);
2589 it->string = Qnil;
2590 it->current.overlay_string_index = -1;
2591 SET_TEXT_POS (it->current.string_pos, -1, -1);
2592 it->n_overlay_strings = 0;
2593 it->method = next_element_from_buffer;
2594 }
2595 else
2596 {
2597 /* There are more overlay strings to process. If
2598 IT->current.overlay_string_index has advanced to a position
2599 where we must load IT->overlay_strings with more strings, do
2600 it. */
2601 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2602
2603 if (it->current.overlay_string_index && i == 0)
2604 load_overlay_strings (it);
2605
2606 /* Initialize IT to deliver display elements from the overlay
2607 string. */
2608 it->string = it->overlay_strings[i];
2609 it->multibyte_p = STRING_MULTIBYTE (it->string);
2610 SET_TEXT_POS (it->current.string_pos, 0, 0);
2611 it->method = next_element_from_string;
2612 it->stop_charpos = 0;
2613 }
2614
2615 CHECK_IT (it);
2616}
2617
2618
2619/* Compare two overlay_entry structures E1 and E2. Used as a
2620 comparison function for qsort in load_overlay_strings. Overlay
2621 strings for the same position are sorted so that
2622
2623 1. All after-strings come in front of before-strings.
2624
2625 2. Within after-strings, strings are sorted so that overlay strings
2626 from overlays with higher priorities come first.
2627
2628 2. Within before-strings, strings are sorted so that overlay
2629 strings from overlays with higher priorities come last.
2630
2631 Value is analogous to strcmp. */
2632
2633
2634static int
2635compare_overlay_entries (e1, e2)
2636 void *e1, *e2;
2637{
2638 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
2639 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
2640 int result;
2641
2642 if (entry1->after_string_p != entry2->after_string_p)
2643 /* Let after-strings appear in front of before-strings. */
2644 result = entry1->after_string_p ? -1 : 1;
2645 else if (entry1->after_string_p)
2646 /* After-strings sorted in order of decreasing priority. */
2647 result = entry2->priority - entry1->priority;
2648 else
2649 /* Before-strings sorted in order of increasing priority. */
2650 result = entry1->priority - entry2->priority;
2651
2652 return result;
2653}
2654
2655
2656/* Load the vector IT->overlay_strings with overlay strings from IT's
2657 current buffer position. Set IT->n_overlays to the total number of
2658 overlay strings found.
2659
2660 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
2661 a time. On entry into load_overlay_strings,
2662 IT->current.overlay_string_index gives the number of overlay
2663 strings that have already been loaded by previous calls to this
2664 function.
2665
2666 Overlay strings are sorted so that after-string strings come in
2667 front of before-string strings. Within before and after-strings,
2668 strings are sorted by overlay priority. See also function
2669 compare_overlay_entries. */
2670
2671static void
2672load_overlay_strings (it)
2673 struct it *it;
2674{
2675 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
2676 Lisp_Object ov, overlay, window, str;
2677 int start, end;
2678 int size = 20;
2679 int n = 0, i, j;
2680 struct overlay_entry *entries
2681 = (struct overlay_entry *) alloca (size * sizeof *entries);
2682
2683 /* Append the overlay string STRING of overlay OVERLAY to vector
2684 `entries' which has size `size' and currently contains `n'
2685 elements. AFTER_P non-zero means STRING is an after-string of
2686 OVERLAY. */
2687#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
2688 do \
2689 { \
2690 Lisp_Object priority; \
2691 \
2692 if (n == size) \
2693 { \
2694 int new_size = 2 * size; \
2695 struct overlay_entry *old = entries; \
2696 entries = \
2697 (struct overlay_entry *) alloca (new_size \
2698 * sizeof *entries); \
2699 bcopy (old, entries, size * sizeof *entries); \
2700 size = new_size; \
2701 } \
2702 \
2703 entries[n].string = (STRING); \
2704 priority = Foverlay_get ((OVERLAY), Qpriority); \
2705 entries[n].priority \
2706 = INTEGERP (priority) ? XFASTINT (priority) : 0; \
2707 entries[n].after_string_p = (AFTER_P); \
2708 ++n; \
2709 } \
2710 while (0)
2711
2712 /* Process overlay before the overlay center. */
2713 for (ov = current_buffer->overlays_before;
2714 CONSP (ov);
9472f927 2715 ov = XCDR (ov))
5f5c8ee5 2716 {
9472f927 2717 overlay = XCAR (ov);
5f5c8ee5
GM
2718 xassert (OVERLAYP (overlay));
2719 start = OVERLAY_POSITION (OVERLAY_START (overlay));
2720 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2721
2722 if (end < IT_CHARPOS (*it))
2723 break;
2724
2725 /* Skip this overlay if it doesn't start or end at IT's current
2726 position. */
2727 if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
2728 continue;
2729
2730 /* Skip this overlay if it doesn't apply to IT->w. */
2731 window = Foverlay_get (overlay, Qwindow);
2732 if (WINDOWP (window) && XWINDOW (window) != it->w)
2733 continue;
2734
2735 /* If overlay has a non-empty before-string, record it. */
2736 if (start == IT_CHARPOS (*it)
2737 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2738 && XSTRING (str)->size)
2739 RECORD_OVERLAY_STRING (overlay, str, 0);
2740
2741 /* If overlay has a non-empty after-string, record it. */
2742 if (end == IT_CHARPOS (*it)
2743 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2744 && XSTRING (str)->size)
2745 RECORD_OVERLAY_STRING (overlay, str, 1);
2746 }
2747
2748 /* Process overlays after the overlay center. */
2749 for (ov = current_buffer->overlays_after;
2750 CONSP (ov);
9472f927 2751 ov = XCDR (ov))
5f5c8ee5 2752 {
9472f927 2753 overlay = XCAR (ov);
5f5c8ee5
GM
2754 xassert (OVERLAYP (overlay));
2755 start = OVERLAY_POSITION (OVERLAY_START (overlay));
2756 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2757
2758 if (start > IT_CHARPOS (*it))
2759 break;
2760
2761 /* Skip this overlay if it doesn't start or end at IT's current
2762 position. */
2763 if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
2764 continue;
2765
2766 /* Skip this overlay if it doesn't apply to IT->w. */
2767 window = Foverlay_get (overlay, Qwindow);
2768 if (WINDOWP (window) && XWINDOW (window) != it->w)
2769 continue;
2770
2771 /* If overlay has a non-empty before-string, record it. */
2772 if (start == IT_CHARPOS (*it)
2773 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2774 && XSTRING (str)->size)
2775 RECORD_OVERLAY_STRING (overlay, str, 0);
2776
2777 /* If overlay has a non-empty after-string, record it. */
2778 if (end == IT_CHARPOS (*it)
2779 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2780 && XSTRING (str)->size)
2781 RECORD_OVERLAY_STRING (overlay, str, 1);
2782 }
2783
2784#undef RECORD_OVERLAY_STRING
2785
2786 /* Sort entries. */
2787 qsort (entries, n, sizeof *entries, compare_overlay_entries);
2788
2789 /* Record the total number of strings to process. */
2790 it->n_overlay_strings = n;
2791
2792 /* IT->current.overlay_string_index is the number of overlay strings
2793 that have already been consumed by IT. Copy some of the
2794 remaining overlay strings to IT->overlay_strings. */
2795 i = 0;
2796 j = it->current.overlay_string_index;
2797 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
2798 it->overlay_strings[i++] = entries[j++].string;
2799
2800 CHECK_IT (it);
2801}
2802
2803
2804/* Get the first chunk of overlay strings at IT's current buffer
2805 position. Value is non-zero if at least one overlay string was
2806 found. */
2807
2808static int
2809get_overlay_strings (it)
2810 struct it *it;
2811{
2812 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
2813 process. This fills IT->overlay_strings with strings, and sets
2814 IT->n_overlay_strings to the total number of strings to process.
2815 IT->pos.overlay_string_index has to be set temporarily to zero
2816 because load_overlay_strings needs this; it must be set to -1
2817 when no overlay strings are found because a zero value would
2818 indicate a position in the first overlay string. */
2819 it->current.overlay_string_index = 0;
2820 load_overlay_strings (it);
2821
2822 /* If we found overlay strings, set up IT to deliver display
2823 elements from the first one. Otherwise set up IT to deliver
2824 from current_buffer. */
2825 if (it->n_overlay_strings)
2826 {
2827 /* Make sure we know settings in current_buffer, so that we can
2828 restore meaningful values when we're done with the overlay
2829 strings. */
2830 compute_stop_pos (it);
2831 xassert (it->face_id >= 0);
2832
2833 /* Save IT's settings. They are restored after all overlay
2834 strings have been processed. */
2835 xassert (it->sp == 0);
2836 push_it (it);
2837
2838 /* Set up IT to deliver display elements from the first overlay
2839 string. */
2840 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2841 it->stop_charpos = 0;
2842 it->string = it->overlay_strings[0];
2843 it->multibyte_p = STRING_MULTIBYTE (it->string);
2844 xassert (STRINGP (it->string));
2845 it->method = next_element_from_string;
2846 }
2847 else
2848 {
2849 it->string = Qnil;
2850 it->current.overlay_string_index = -1;
2851 it->method = next_element_from_buffer;
2852 }
2853
2854 CHECK_IT (it);
2855
2856 /* Value is non-zero if we found at least one overlay string. */
2857 return STRINGP (it->string);
2858}
2859
2860
2861\f
2862/***********************************************************************
2863 Saving and restoring state
2864 ***********************************************************************/
2865
2866/* Save current settings of IT on IT->stack. Called, for example,
2867 before setting up IT for an overlay string, to be able to restore
2868 IT's settings to what they were after the overlay string has been
2869 processed. */
2870
2871static void
2872push_it (it)
2873 struct it *it;
2874{
2875 struct iterator_stack_entry *p;
2876
2877 xassert (it->sp < 2);
2878 p = it->stack + it->sp;
2879
2880 p->stop_charpos = it->stop_charpos;
2881 xassert (it->face_id >= 0);
2882 p->face_id = it->face_id;
2883 p->string = it->string;
2884 p->pos = it->current;
2885 p->end_charpos = it->end_charpos;
2886 p->string_nchars = it->string_nchars;
2887 p->area = it->area;
2888 p->multibyte_p = it->multibyte_p;
2889 p->space_width = it->space_width;
2890 p->font_height = it->font_height;
2891 p->voffset = it->voffset;
2892 p->string_from_display_prop_p = it->string_from_display_prop_p;
2893 ++it->sp;
2894}
2895
2896
2897/* Restore IT's settings from IT->stack. Called, for example, when no
2898 more overlay strings must be processed, and we return to delivering
2899 display elements from a buffer, or when the end of a string from a
2900 `display' property is reached and we return to delivering display
2901 elements from an overlay string, or from a buffer. */
2902
2903static void
2904pop_it (it)
2905 struct it *it;
2906{
2907 struct iterator_stack_entry *p;
2908
2909 xassert (it->sp > 0);
2910 --it->sp;
2911 p = it->stack + it->sp;
2912 it->stop_charpos = p->stop_charpos;
2913 it->face_id = p->face_id;
2914 it->string = p->string;
2915 it->current = p->pos;
2916 it->end_charpos = p->end_charpos;
2917 it->string_nchars = p->string_nchars;
2918 it->area = p->area;
2919 it->multibyte_p = p->multibyte_p;
2920 it->space_width = p->space_width;
2921 it->font_height = p->font_height;
2922 it->voffset = p->voffset;
2923 it->string_from_display_prop_p = p->string_from_display_prop_p;
2924}
2925
2926
2927\f
2928/***********************************************************************
2929 Moving over lines
2930 ***********************************************************************/
2931
2932/* Set IT's current position to the previous line start. */
2933
2934static void
2935back_to_previous_line_start (it)
2936 struct it *it;
2937{
2938 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
2939 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
2940}
2941
2942
2943/* Set IT's current position to the next line start. */
2944
2945static void
2946forward_to_next_line_start (it)
2947 struct it *it;
2948{
2949 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it), 1);
2950 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
2951}
2952
2953
2954/* Set IT's current position to the previous visible line start. Skip
2955 invisible text that is so either due to text properties or due to
2956 selective display. Caution: this does not change IT->current_x and
2957 IT->hpos. */
2958
2959static void
2960back_to_previous_visible_line_start (it)
2961 struct it *it;
2962{
2963 int visible_p = 0;
2964
2965 /* Go back one newline if not on BEGV already. */
2966 if (IT_CHARPOS (*it) > BEGV)
2967 back_to_previous_line_start (it);
2968
2969 /* Move over lines that are invisible because of selective display
2970 or text properties. */
2971 while (IT_CHARPOS (*it) > BEGV
2972 && !visible_p)
2973 {
2974 visible_p = 1;
2975
2976 /* If selective > 0, then lines indented more than that values
2977 are invisible. */
2978 if (it->selective > 0
2979 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
2980 it->selective))
2981 visible_p = 0;
2982#ifdef USE_TEXT_PROPERTIES
2983 else
2984 {
2985 Lisp_Object prop;
2986
2987 prop = Fget_char_property (IT_CHARPOS (*it), Qinvisible, it->window);
2988 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2989 visible_p = 0;
2990 }
2991#endif /* USE_TEXT_PROPERTIES */
2992
2993 /* Back one more newline if the current one is invisible. */
2994 if (!visible_p)
2995 back_to_previous_line_start (it);
2996 }
2997
2998 xassert (IT_CHARPOS (*it) >= BEGV);
2999 xassert (IT_CHARPOS (*it) == BEGV
3000 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3001 CHECK_IT (it);
3002}
3003
3004
3005/* Reseat iterator IT at the previous visible line start. Skip
3006 invisible text that is so either due to text properties or due to
3007 selective display. At the end, update IT's overlay information,
3008 face information etc. */
3009
3010static void
3011reseat_at_previous_visible_line_start (it)
3012 struct it *it;
3013{
3014 back_to_previous_visible_line_start (it);
3015 reseat (it, it->current.pos, 1);
3016 CHECK_IT (it);
3017}
3018
3019
3020/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
3021 buffer. ON_NEWLINE_P non-zero means position IT on the newline
3022 preceding the line start. Skip over invisible text that is so
3023 because of selective display. Compute faces, overlays etc at the
3024 new position. Note that this function does not skip over text that
3025 is invisible because of text properties. */
5f5c8ee5
GM
3026
3027static void
312246d1 3028reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 3029 struct it *it;
312246d1 3030 int on_newline_p;
5f5c8ee5
GM
3031{
3032 /* Restore the buffer position when currently not delivering display
3033 elements from the current buffer. This is the case, for example,
3034 when called at the end of a truncated overlay string. */
3035 while (it->sp)
3036 pop_it (it);
3037 it->method = next_element_from_buffer;
3038
3039 /* Otherwise, scan_buffer would not work. */
3040 if (IT_CHARPOS (*it) < ZV)
3041 {
3042 /* If on a newline, advance past it. Otherwise, find the next
3043 newline which automatically gives us the position following
3044 the newline. */
3045 if (FETCH_BYTE (IT_BYTEPOS (*it)) == '\n')
3046 {
3047 ++IT_CHARPOS (*it);
3048 ++IT_BYTEPOS (*it);
3049 }
3050 else
3051 forward_to_next_line_start (it);
3052
3053 /* We must either have reached the end of the buffer or end up
3054 after a newline. */
3055 xassert (IT_CHARPOS (*it) == ZV
3056 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3057
3058 /* Skip over lines that are invisible because they are indented
3059 more than the value of IT->selective. */
3060 if (it->selective > 0)
3061 while (IT_CHARPOS (*it) < ZV
3062 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3063 it->selective))
3064 forward_to_next_line_start (it);
312246d1
GM
3065
3066 /* Position on the newline if we should. */
3067 if (on_newline_p && IT_CHARPOS (*it) > BEGV)
3068 {
3069 --IT_CHARPOS (*it);
3070 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3071 }
5f5c8ee5
GM
3072
3073 /* Set the iterator there. The 0 as the last parameter of
3074 reseat means don't force a text property lookup. The lookup
3075 is then only done if we've skipped past the iterator's
3076 check_charpos'es. This optimization is important because
3077 text property lookups tend to be expensive. */
3078 reseat (it, it->current.pos, 0);
3079 }
3080
3081 CHECK_IT (it);
3082}
3083
3084
3085\f
3086/***********************************************************************
3087 Changing an iterator's position
3088***********************************************************************/
3089
3090/* Change IT's current position to POS in current_buffer. If FORCE_P
3091 is non-zero, always check for text properties at the new position.
3092 Otherwise, text properties are only looked up if POS >=
3093 IT->check_charpos of a property. */
3094
3095static void
3096reseat (it, pos, force_p)
3097 struct it *it;
3098 struct text_pos pos;
3099 int force_p;
3100{
3101 int original_pos = IT_CHARPOS (*it);
3102
3103 reseat_1 (it, pos, 0);
3104
3105 /* Determine where to check text properties. Avoid doing it
3106 where possible because text property lookup is very expensive. */
3107 if (force_p
3108 || CHARPOS (pos) > it->stop_charpos
3109 || CHARPOS (pos) < original_pos)
3110 handle_stop (it);
3111
3112 CHECK_IT (it);
3113}
3114
3115
3116/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
3117 IT->stop_pos to POS, also. */
3118
3119static void
3120reseat_1 (it, pos, set_stop_p)
3121 struct it *it;
3122 struct text_pos pos;
3123 int set_stop_p;
3124{
3125 /* Don't call this function when scanning a C string. */
3126 xassert (it->s == NULL);
3127
3128 /* POS must be a reasonable value. */
3129 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
3130
3131 it->current.pos = it->position = pos;
3132 XSETBUFFER (it->object, current_buffer);
3133 it->dpvec = NULL;
3134 it->current.dpvec_index = -1;
3135 it->current.overlay_string_index = -1;
3136 IT_STRING_CHARPOS (*it) = -1;
3137 IT_STRING_BYTEPOS (*it) = -1;
3138 it->string = Qnil;
3139 it->method = next_element_from_buffer;
3140 it->sp = 0;
3141
3142 if (set_stop_p)
3143 it->stop_charpos = CHARPOS (pos);
3144}
3145
3146
3147/* Set up IT for displaying a string, starting at CHARPOS in window W.
3148 If S is non-null, it is a C string to iterate over. Otherwise,
3149 STRING gives a Lisp string to iterate over.
3150
3151 If PRECISION > 0, don't return more then PRECISION number of
3152 characters from the string.
3153
3154 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
3155 characters have been returned. FIELD_WIDTH < 0 means an infinite
3156 field width.
3157
3158 MULTIBYTE = 0 means disable processing of multibyte characters,
3159 MULTIBYTE > 0 means enable it,
3160 MULTIBYTE < 0 means use IT->multibyte_p.
3161
3162 IT must be initialized via a prior call to init_iterator before
3163 calling this function. */
3164
3165static void
3166reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
3167 struct it *it;
3168 unsigned char *s;
3169 Lisp_Object string;
3170 int charpos;
3171 int precision, field_width, multibyte;
3172{
3173 /* No region in strings. */
3174 it->region_beg_charpos = it->region_end_charpos = -1;
3175
3176 /* No text property checks performed by default, but see below. */
3177 it->stop_charpos = -1;
3178
3179 /* Set iterator position and end position. */
3180 bzero (&it->current, sizeof it->current);
3181 it->current.overlay_string_index = -1;
3182 it->current.dpvec_index = -1;
3183 it->charset = CHARSET_ASCII;
3184 xassert (charpos >= 0);
3185
3186 /* Use the setting of MULTIBYTE if specified. */
3187 if (multibyte >= 0)
3188 it->multibyte_p = multibyte > 0;
3189
3190 if (s == NULL)
3191 {
3192 xassert (STRINGP (string));
3193 it->string = string;
3194 it->s = NULL;
3195 it->end_charpos = it->string_nchars = XSTRING (string)->size;
3196 it->method = next_element_from_string;
3197 it->current.string_pos = string_pos (charpos, string);
3198 }
3199 else
3200 {
3201 it->s = s;
3202 it->string = Qnil;
3203
3204 /* Note that we use IT->current.pos, not it->current.string_pos,
3205 for displaying C strings. */
3206 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3207 if (it->multibyte_p)
3208 {
3209 it->current.pos = c_string_pos (charpos, s, 1);
3210 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
3211 }
3212 else
3213 {
3214 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
3215 it->end_charpos = it->string_nchars = strlen (s);
3216 }
3217
3218 it->method = next_element_from_c_string;
3219 }
3220
3221 /* PRECISION > 0 means don't return more than PRECISION characters
3222 from the string. */
3223 if (precision > 0 && it->end_charpos - charpos > precision)
3224 it->end_charpos = it->string_nchars = charpos + precision;
3225
3226 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
3227 characters have been returned. FIELD_WIDTH == 0 means don't pad,
3228 FIELD_WIDTH < 0 means infinite field width. This is useful for
3229 padding with `-' at the end of a mode line. */
3230 if (field_width < 0)
3231 field_width = INFINITY;
3232 if (field_width > it->end_charpos - charpos)
3233 it->end_charpos = charpos + field_width;
3234
3235 /* Use the standard display table for displaying strings. */
3236 if (DISP_TABLE_P (Vstandard_display_table))
3237 it->dp = XCHAR_TABLE (Vstandard_display_table);
3238
3239 it->stop_charpos = charpos;
3240 CHECK_IT (it);
3241}
3242
3243
3244\f
3245/***********************************************************************
3246 Iteration
3247 ***********************************************************************/
3248
3249/* Load IT's display element fields with information about the next
3250 display element from the current position of IT. Value is zero if
3251 end of buffer (or C string) is reached. */
3252
3253int
3254get_next_display_element (it)
3255 struct it *it;
3256{
3257 /* Non-zero means that we found an display element. Zero means that
3258 we hit the end of what we iterate over. Performance note: the
3259 function pointer `method' used here turns out to be faster than
3260 using a sequence of if-statements. */
3261 int success_p = (*it->method) (it);
3262 int charset;
3263
3264 if (it->what == IT_CHARACTER)
3265 {
3266 /* Map via display table or translate control characters.
3267 IT->c, IT->len etc. have been set to the next character by
3268 the function call above. If we have a display table, and it
3269 contains an entry for IT->c, translate it. Don't do this if
3270 IT->c itself comes from a display table, otherwise we could
3271 end up in an infinite recursion. (An alternative could be to
3272 count the recursion depth of this function and signal an
3273 error when a certain maximum depth is reached.) Is it worth
3274 it? */
3275 if (success_p && it->dpvec == NULL)
3276 {
3277 Lisp_Object dv;
3278
3279 if (it->dp
3280 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
3281 VECTORP (dv)))
3282 {
3283 struct Lisp_Vector *v = XVECTOR (dv);
3284
3285 /* Return the first character from the display table
3286 entry, if not empty. If empty, don't display the
3287 current character. */
3288 if (v->size)
3289 {
3290 it->dpvec_char_len = it->len;
3291 it->dpvec = v->contents;
3292 it->dpend = v->contents + v->size;
3293 it->current.dpvec_index = 0;
3294 it->method = next_element_from_display_vector;
3295 }
3296
3297 success_p = get_next_display_element (it);
3298 }
3299
3300 /* Translate control characters into `\003' or `^C' form.
3301 Control characters coming from a display table entry are
3302 currently not translated because we use IT->dpvec to hold
3303 the translation. This could easily be changed but I
197516c2
KH
3304 don't believe that it is worth doing.
3305
3306 Non-printable multibyte characters are also translated
3307 octal form. */
5f5c8ee5
GM
3308 else if ((it->c < ' '
3309 && (it->area != TEXT_AREA
c6e89d6c 3310 || (it->c != '\n' && it->c != '\t')))
54c85a23 3311 || (it->c >= 127
197516c2
KH
3312 && it->len == 1)
3313 || !CHAR_PRINTABLE_P (it->c))
5f5c8ee5
GM
3314 {
3315 /* IT->c is a control character which must be displayed
3316 either as '\003' or as `^C' where the '\\' and '^'
3317 can be defined in the display table. Fill
3318 IT->ctl_chars with glyphs for what we have to
3319 display. Then, set IT->dpvec to these glyphs. */
3320 GLYPH g;
3321
54c85a23 3322 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
3323 {
3324 /* Set IT->ctl_chars[0] to the glyph for `^'. */
3325 if (it->dp
3326 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
3327 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
3328 g = XINT (DISP_CTRL_GLYPH (it->dp));
3329 else
3330 g = FAST_MAKE_GLYPH ('^', 0);
3331 XSETINT (it->ctl_chars[0], g);
3332
3333 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
3334 XSETINT (it->ctl_chars[1], g);
3335
3336 /* Set up IT->dpvec and return first character from it. */
3337 it->dpvec_char_len = it->len;
3338 it->dpvec = it->ctl_chars;
3339 it->dpend = it->dpvec + 2;
3340 it->current.dpvec_index = 0;
3341 it->method = next_element_from_display_vector;
3342 get_next_display_element (it);
3343 }
3344 else
3345 {
197516c2
KH
3346 unsigned char work[4], *str;
3347 int len = CHAR_STRING (it->c, work, str);
3348 int i;
3349 GLYPH escape_glyph;
3350
5f5c8ee5
GM
3351 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
3352 if (it->dp
3353 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
3354 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 3355 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 3356 else
197516c2
KH
3357 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
3358
3359 for (i = 0; i < len; i++)
3360 {
3361 XSETINT (it->ctl_chars[i * 4], escape_glyph);
3362 /* Insert three more glyphs into IT->ctl_chars for
3363 the octal display of the character. */
3364 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
3365 XSETINT (it->ctl_chars[i * 4 + 1], g);
3366 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
3367 XSETINT (it->ctl_chars[i * 4 + 2], g);
3368 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
3369 XSETINT (it->ctl_chars[i * 4 + 3], g);
3370 }
5f5c8ee5
GM
3371
3372 /* Set up IT->dpvec and return the first character
3373 from it. */
3374 it->dpvec_char_len = it->len;
3375 it->dpvec = it->ctl_chars;
197516c2 3376 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
3377 it->current.dpvec_index = 0;
3378 it->method = next_element_from_display_vector;
3379 get_next_display_element (it);
3380 }
3381 }
3382 }
3383
3384 /* Adjust face id if charset changes. There are no charset
3385 changes in unibyte text because Emacs' charsets are not
3386 applicable there. */
3387 if (it->multibyte_p
3388 && success_p
3389 && (charset = CHAR_CHARSET (it->c),
3390 charset != it->charset))
3391 {
3392 it->charset = charset;
3393 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, charset);
3394 }
3395 }
3396
3397 /* Is this character the last one of a run of characters with
3398 box? If yes, set IT->end_of_box_run_p to 1. */
3399 if (it->face_box_p
3400 && it->s == NULL)
3401 {
3402 int face_id;
3403 struct face *face;
3404
3405 it->end_of_box_run_p
3406 = ((face_id = face_after_it_pos (it),
3407 face_id != it->face_id)
3408 && (face = FACE_FROM_ID (it->f, face_id),
3409 face->box == FACE_NO_BOX));
3410 }
3411
3412 /* Value is 0 if end of buffer or string reached. */
3413 return success_p;
3414}
3415
3416
3417/* Move IT to the next display element.
3418
3419 Functions get_next_display_element and set_iterator_to_next are
3420 separate because I find this arrangement easier to handle than a
3421 get_next_display_element function that also increments IT's
3422 position. The way it is we can first look at an iterator's current
3423 display element, decide whether it fits on a line, and if it does,
3424 increment the iterator position. The other way around we probably
3425 would either need a flag indicating whether the iterator has to be
3426 incremented the next time, or we would have to implement a
3427 decrement position function which would not be easy to write. */
3428
3429void
3430set_iterator_to_next (it)
3431 struct it *it;
3432{
3433 if (it->method == next_element_from_buffer)
3434 {
3435 /* The current display element of IT is a character from
3436 current_buffer. Advance in the buffer, and maybe skip over
3437 invisible lines that are so because of selective display. */
3438 if (ITERATOR_AT_END_OF_LINE_P (it))
312246d1 3439 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
3440 else
3441 {
3442 xassert (it->len != 0);
3443 IT_BYTEPOS (*it) += it->len;
3444 IT_CHARPOS (*it) += 1;
3445 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
3446 }
3447 }
3448 else if (it->method == next_element_from_c_string)
3449 {
3450 /* Current display element of IT is from a C string. */
3451 IT_BYTEPOS (*it) += it->len;
3452 IT_CHARPOS (*it) += 1;
3453 }
3454 else if (it->method == next_element_from_display_vector)
3455 {
3456 /* Current display element of IT is from a display table entry.
3457 Advance in the display table definition. Reset it to null if
3458 end reached, and continue with characters from buffers/
3459 strings. */
3460 ++it->current.dpvec_index;
286bcbc9
GM
3461
3462 /* Restore face and charset of the iterator to what they were
3463 before the display vector entry (these entries may contain
3464 faces, and of course characters of different charsets). */
5f5c8ee5 3465 it->face_id = it->saved_face_id;
286bcbc9
GM
3466 it->charset = FACE_FROM_ID (it->f, it->face_id)->charset;
3467
5f5c8ee5
GM
3468 if (it->dpvec + it->current.dpvec_index == it->dpend)
3469 {
3470 if (it->s)
3471 it->method = next_element_from_c_string;
3472 else if (STRINGP (it->string))
3473 it->method = next_element_from_string;
3474 else
3475 it->method = next_element_from_buffer;
3476
3477 it->dpvec = NULL;
3478 it->current.dpvec_index = -1;
3479
312246d1
GM
3480 /* Skip over characters which were displayed via IT->dpvec. */
3481 if (it->dpvec_char_len < 0)
3482 reseat_at_next_visible_line_start (it, 1);
3483 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
3484 {
3485 it->len = it->dpvec_char_len;
3486 set_iterator_to_next (it);
3487 }
3488 }
3489 }
3490 else if (it->method == next_element_from_string)
3491 {
3492 /* Current display element is a character from a Lisp string. */
3493 xassert (it->s == NULL && STRINGP (it->string));
3494 IT_STRING_BYTEPOS (*it) += it->len;
3495 IT_STRING_CHARPOS (*it) += 1;
3496
3497 consider_string_end:
3498
3499 if (it->current.overlay_string_index >= 0)
3500 {
3501 /* IT->string is an overlay string. Advance to the
3502 next, if there is one. */
3503 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3504 next_overlay_string (it);
3505 }
3506 else
3507 {
3508 /* IT->string is not an overlay string. If we reached
3509 its end, and there is something on IT->stack, proceed
3510 with what is on the stack. This can be either another
3511 string, this time an overlay string, or a buffer. */
3512 if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size
3513 && it->sp > 0)
3514 {
3515 pop_it (it);
3516 if (!STRINGP (it->string))
3517 it->method = next_element_from_buffer;
3518 }
3519 }
3520 }
3521 else if (it->method == next_element_from_image
3522 || it->method == next_element_from_stretch)
3523 {
3524 /* The position etc with which we have to proceed are on
3525 the stack. The position may be at the end of a string,
3526 if the `display' property takes up the whole string. */
3527 pop_it (it);
3528 it->image_id = 0;
3529 if (STRINGP (it->string))
3530 {
3531 it->method = next_element_from_string;
3532 goto consider_string_end;
3533 }
3534 else
3535 it->method = next_element_from_buffer;
3536 }
3537 else
3538 /* There are no other methods defined, so this should be a bug. */
3539 abort ();
3540
3541 /* Reset flags indicating start and end of a sequence of
3542 characters with box. */
3543 it->start_of_box_run_p = it->end_of_box_run_p = 0;
3544
3545 xassert (it->method != next_element_from_string
3546 || (STRINGP (it->string)
3547 && IT_STRING_CHARPOS (*it) >= 0));
3548}
3549
3550
3551/* Load IT's display element fields with information about the next
3552 display element which comes from a display table entry or from the
3553 result of translating a control character to one of the forms `^C'
3554 or `\003'. IT->dpvec holds the glyphs to return as characters. */
3555
3556static int
3557next_element_from_display_vector (it)
3558 struct it *it;
3559{
3560 /* Precondition. */
3561 xassert (it->dpvec && it->current.dpvec_index >= 0);
3562
3563 /* Remember the current face id in case glyphs specify faces.
3564 IT's face is restored in set_iterator_to_next. */
3565 it->saved_face_id = it->face_id;
3566
3567 if (INTEGERP (*it->dpvec)
3568 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
3569 {
3570 int lface_id;
3571 GLYPH g;
3572
3573 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
3574 it->c = FAST_GLYPH_CHAR (g);
3575 it->len = CHAR_LEN (it->c);
3576
3577 /* The entry may contain a face id to use. Such a face id is
3578 the id of a Lisp face, not a realized face. A face id of
3579 zero means no face. */
3580 lface_id = FAST_GLYPH_FACE (g);
3581 if (lface_id)
3582 {
3583 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
3584 if (face_id >= 0)
3585 {
3586 it->face_id = face_id;
3587 it->charset = CHARSET_ASCII;
3588 }
3589 }
3590 }
3591 else
3592 /* Display table entry is invalid. Return a space. */
3593 it->c = ' ', it->len = 1;
3594
3595 /* Don't change position and object of the iterator here. They are
3596 still the values of the character that had this display table
3597 entry or was translated, and that's what we want. */
3598 it->what = IT_CHARACTER;
3599 return 1;
3600}
3601
3602
3603/* Load IT with the next display element from Lisp string IT->string.
3604 IT->current.string_pos is the current position within the string.
3605 If IT->current.overlay_string_index >= 0, the Lisp string is an
3606 overlay string. */
3607
3608static int
3609next_element_from_string (it)
3610 struct it *it;
3611{
3612 struct text_pos position;
3613
3614 xassert (STRINGP (it->string));
3615 xassert (IT_STRING_CHARPOS (*it) >= 0);
3616 position = it->current.string_pos;
3617
3618 /* Time to check for invisible text? */
3619 if (IT_STRING_CHARPOS (*it) < it->end_charpos
3620 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
3621 {
3622 handle_stop (it);
3623
3624 /* Since a handler may have changed IT->method, we must
3625 recurse here. */
3626 return get_next_display_element (it);
3627 }
3628
3629 if (it->current.overlay_string_index >= 0)
3630 {
3631 /* Get the next character from an overlay string. In overlay
3632 strings, There is no field width or padding with spaces to
3633 do. */
3634 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3635 {
3636 it->what = IT_EOB;
3637 return 0;
3638 }
3639 else if (STRING_MULTIBYTE (it->string))
3640 {
3641 int remaining = (STRING_BYTES (XSTRING (it->string))
3642 - IT_STRING_BYTEPOS (*it));
3643 unsigned char *s = (XSTRING (it->string)->data
3644 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3645 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
3646 }
3647 else
3648 {
3649 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3650 it->len = 1;
3651 }
3652 }
3653 else
3654 {
3655 /* Get the next character from a Lisp string that is not an
3656 overlay string. Such strings come from the mode line, for
3657 example. We may have to pad with spaces, or truncate the
3658 string. See also next_element_from_c_string. */
3659 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
3660 {
3661 it->what = IT_EOB;
3662 return 0;
3663 }
3664 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
3665 {
3666 /* Pad with spaces. */
3667 it->c = ' ', it->len = 1;
3668 CHARPOS (position) = BYTEPOS (position) = -1;
3669 }
3670 else if (STRING_MULTIBYTE (it->string))
3671 {
3672 int maxlen = (STRING_BYTES (XSTRING (it->string))
3673 - IT_STRING_BYTEPOS (*it));
3674 unsigned char *s = (XSTRING (it->string)->data
3675 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3676 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
3677 }
3678 else
3679 {
3680 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3681 it->len = 1;
3682 }
3683 }
3684
3685 /* Record what we have and where it came from. Note that we store a
3686 buffer position in IT->position although it could arguably be a
3687 string position. */
3688 it->what = IT_CHARACTER;
3689 it->object = it->string;
3690 it->position = position;
3691 return 1;
3692}
3693
3694
3695/* Load IT with next display element from C string IT->s.
3696 IT->string_nchars is the maximum number of characters to return
3697 from the string. IT->end_charpos may be greater than
3698 IT->string_nchars when this function is called, in which case we
3699 may have to return padding spaces. Value is zero if end of string
3700 reached, including padding spaces. */
3701
3702static int
3703next_element_from_c_string (it)
3704 struct it *it;
3705{
3706 int success_p = 1;
3707
3708 xassert (it->s);
3709 it->what = IT_CHARACTER;
3710 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
3711 it->object = Qnil;
3712
3713 /* IT's position can be greater IT->string_nchars in case a field
3714 width or precision has been specified when the iterator was
3715 initialized. */
3716 if (IT_CHARPOS (*it) >= it->end_charpos)
3717 {
3718 /* End of the game. */
3719 it->what = IT_EOB;
3720 success_p = 0;
3721 }
3722 else if (IT_CHARPOS (*it) >= it->string_nchars)
3723 {
3724 /* Pad with spaces. */
3725 it->c = ' ', it->len = 1;
3726 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
3727 }
3728 else if (it->multibyte_p)
3729 {
3730 /* Implementation note: The calls to strlen apparently aren't a
3731 performance problem because there is no noticeable performance
3732 difference between Emacs running in unibyte or multibyte mode. */
3733 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
3734 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
3735 maxlen, &it->len);
5f5c8ee5
GM
3736 }
3737 else
3738 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
3739
3740 return success_p;
3741}
3742
3743
3744/* Set up IT to return characters from an ellipsis, if appropriate.
3745 The definition of the ellipsis glyphs may come from a display table
3746 entry. This function Fills IT with the first glyph from the
3747 ellipsis if an ellipsis is to be displayed. */
3748
3749static void
3750next_element_from_ellipsis (it)
3751 struct it *it;
3752{
3753 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
3754 {
3755 /* Use the display table definition for `...'. Invalid glyphs
3756 will be handled by the method returning elements from dpvec. */
3757 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
3758 it->dpvec_char_len = it->len;
3759 it->dpvec = v->contents;
3760 it->dpend = v->contents + v->size;
3761 it->current.dpvec_index = 0;
3762 it->method = next_element_from_display_vector;
3763 get_next_display_element (it);
3764 }
3765 else if (it->selective_display_ellipsis_p)
3766 {
3767 /* Use default `...' which is stored in default_invis_vector. */
3768 it->dpvec_char_len = it->len;
3769 it->dpvec = default_invis_vector;
3770 it->dpend = default_invis_vector + 3;
3771 it->current.dpvec_index = 0;
3772 it->method = next_element_from_display_vector;
3773 get_next_display_element (it);
3774 }
3775}
3776
3777
3778/* Deliver an image display element. The iterator IT is already
3779 filled with image information (done in handle_display_prop). Value
3780 is always 1. */
3781
3782
3783static int
3784next_element_from_image (it)
3785 struct it *it;
3786{
3787 it->what = IT_IMAGE;
3788 return 1;
3789}
3790
3791
3792/* Fill iterator IT with next display element from a stretch glyph
3793 property. IT->object is the value of the text property. Value is
3794 always 1. */
3795
3796static int
3797next_element_from_stretch (it)
3798 struct it *it;
3799{
3800 it->what = IT_STRETCH;
3801 return 1;
3802}
3803
3804
3805/* Load IT with the next display element from current_buffer. Value
3806 is zero if end of buffer reached. IT->stop_charpos is the next
3807 position at which to stop and check for text properties or buffer
3808 end. */
3809
3810static int
3811next_element_from_buffer (it)
3812 struct it *it;
3813{
3814 int success_p = 1;
3815
3816 /* Check this assumption, otherwise, we would never enter the
3817 if-statement, below. */
3818 xassert (IT_CHARPOS (*it) >= BEGV
3819 && IT_CHARPOS (*it) <= it->stop_charpos);
3820
3821 if (IT_CHARPOS (*it) >= it->stop_charpos)
3822 {
3823 if (IT_CHARPOS (*it) >= it->end_charpos)
3824 {
3825 int overlay_strings_follow_p;
3826
3827 /* End of the game, except when overlay strings follow that
3828 haven't been returned yet. */
3829 if (it->overlay_strings_at_end_processed_p)
3830 overlay_strings_follow_p = 0;
3831 else
3832 {
3833 it->overlay_strings_at_end_processed_p = 1;
3834 overlay_strings_follow_p
3835 = get_overlay_strings (it);
3836 }
3837
3838 if (overlay_strings_follow_p)
3839 success_p = get_next_display_element (it);
3840 else
3841 {
3842 it->what = IT_EOB;
3843 it->position = it->current.pos;
3844 success_p = 0;
3845 }
3846 }
3847 else
3848 {
3849 handle_stop (it);
3850 return get_next_display_element (it);
3851 }
3852 }
3853 else
3854 {
3855 /* No face changes, overlays etc. in sight, so just return a
3856 character from current_buffer. */
3857 unsigned char *p;
3858
3859 /* Maybe run the redisplay end trigger hook. Performance note:
3860 This doesn't seem to cost measurable time. */
3861 if (it->redisplay_end_trigger_charpos
3862 && it->glyph_row
3863 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
3864 run_redisplay_end_trigger_hook (it);
3865
3866 /* Get the next character, maybe multibyte. */
3867 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
3868 if (it->multibyte_p)
3869 {
3870 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
3871 - IT_BYTEPOS (*it));
4fdb80f2 3872 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
3873 }
3874 else
3875 it->c = *p, it->len = 1;
3876
3877 /* Record what we have and where it came from. */
3878 it->what = IT_CHARACTER;;
3879 it->object = it->w->buffer;
3880 it->position = it->current.pos;
3881
3882 /* Normally we return the character found above, except when we
3883 really want to return an ellipsis for selective display. */
3884 if (it->selective)
3885 {
3886 if (it->c == '\n')
3887 {
3888 /* A value of selective > 0 means hide lines indented more
3889 than that number of columns. */
3890 if (it->selective > 0
3891 && IT_CHARPOS (*it) + 1 < ZV
3892 && indented_beyond_p (IT_CHARPOS (*it) + 1,
3893 IT_BYTEPOS (*it) + 1,
3894 it->selective))
312246d1
GM
3895 {
3896 next_element_from_ellipsis (it);
3897 it->dpvec_char_len = -1;
3898 }
5f5c8ee5
GM
3899 }
3900 else if (it->c == '\r' && it->selective == -1)
3901 {
3902 /* A value of selective == -1 means that everything from the
3903 CR to the end of the line is invisible, with maybe an
3904 ellipsis displayed for it. */
3905 next_element_from_ellipsis (it);
312246d1 3906 it->dpvec_char_len = -1;
5f5c8ee5
GM
3907 }
3908 }
3909 }
3910
3911 /* Value is zero if end of buffer reached. */
3912 xassert (!success_p || it->len > 0);
3913 return success_p;
3914}
3915
3916
3917/* Run the redisplay end trigger hook for IT. */
3918
3919static void
3920run_redisplay_end_trigger_hook (it)
3921 struct it *it;
3922{
3923 Lisp_Object args[3];
3924
3925 /* IT->glyph_row should be non-null, i.e. we should be actually
3926 displaying something, or otherwise we should not run the hook. */
3927 xassert (it->glyph_row);
3928
3929 /* Set up hook arguments. */
3930 args[0] = Qredisplay_end_trigger_functions;
3931 args[1] = it->window;
3932 XSETINT (args[2], it->redisplay_end_trigger_charpos);
3933 it->redisplay_end_trigger_charpos = 0;
3934
3935 /* Since we are *trying* to run these functions, don't try to run
3936 them again, even if they get an error. */
3937 it->w->redisplay_end_trigger = Qnil;
3938 Frun_hook_with_args (3, args);
3939
3940 /* Notice if it changed the face of the character we are on. */
3941 handle_face_prop (it);
3942}
3943
3944
3945\f
3946/***********************************************************************
3947 Moving an iterator without producing glyphs
3948 ***********************************************************************/
3949
3950/* Move iterator IT to a specified buffer or X position within one
3951 line on the display without producing glyphs.
3952
3953 Begin to skip at IT's current position. Skip to TO_CHARPOS or TO_X
3954 whichever is reached first.
3955
3956 TO_CHARPOS <= 0 means no TO_CHARPOS is specified.
3957
3958 TO_X < 0 means that no TO_X is specified. TO_X is normally a value
3959 0 <= TO_X <= IT->last_visible_x. This means in particular, that
3960 TO_X includes the amount by which a window is horizontally
3961 scrolled.
3962
3963 Value is
3964
3965 MOVE_POS_MATCH_OR_ZV
3966 - when TO_POS or ZV was reached.
3967
3968 MOVE_X_REACHED
3969 -when TO_X was reached before TO_POS or ZV were reached.
3970
3971 MOVE_LINE_CONTINUED
3972 - when we reached the end of the display area and the line must
3973 be continued.
3974
3975 MOVE_LINE_TRUNCATED
3976 - when we reached the end of the display area and the line is
3977 truncated.
3978
3979 MOVE_NEWLINE_OR_CR
3980 - when we stopped at a line end, i.e. a newline or a CR and selective
3981 display is on. */
3982
701552dd 3983static enum move_it_result
5f5c8ee5
GM
3984move_it_in_display_line_to (it, to_charpos, to_x, op)
3985 struct it *it;
3986 int to_charpos, to_x, op;
3987{
3988 enum move_it_result result = MOVE_UNDEFINED;
3989 struct glyph_row *saved_glyph_row;
3990
3991 /* Don't produce glyphs in produce_glyphs. */
3992 saved_glyph_row = it->glyph_row;
3993 it->glyph_row = NULL;
3994
5f5c8ee5
GM
3995 while (1)
3996 {
3997 int x, i;
3998
3999 /* Stop when ZV or TO_CHARPOS reached. */
4000 if (!get_next_display_element (it)
4001 || ((op & MOVE_TO_POS) != 0
4002 && BUFFERP (it->object)
4003 && IT_CHARPOS (*it) >= to_charpos))
4004 {
4005 result = MOVE_POS_MATCH_OR_ZV;
4006 break;
4007 }
4008
4009 /* The call to produce_glyphs will get the metrics of the
4010 display element IT is loaded with. We record in x the
4011 x-position before this display element in case it does not
4012 fit on the line. */
4013 x = it->current_x;
4014 PRODUCE_GLYPHS (it);
4015
4016 if (it->area != TEXT_AREA)
4017 {
4018 set_iterator_to_next (it);
4019 continue;
4020 }
4021
4022 /* The number of glyphs we get back in IT->nglyphs will normally
4023 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
4024 character on a terminal frame, or (iii) a line end. For the
4025 second case, IT->nglyphs - 1 padding glyphs will be present
4026 (on X frames, there is only one glyph produced for a
4027 composite character.
4028
4029 The behavior implemented below means, for continuation lines,
4030 that as many spaces of a TAB as fit on the current line are
4031 displayed there. For terminal frames, as many glyphs of a
4032 multi-glyph character are displayed in the current line, too.
4033 This is what the old redisplay code did, and we keep it that
4034 way. Under X, the whole shape of a complex character must
4035 fit on the line or it will be completely displayed in the
4036 next line.
4037
4038 Note that both for tabs and padding glyphs, all glyphs have
4039 the same width. */
4040 if (it->nglyphs)
4041 {
4042 /* More than one glyph or glyph doesn't fit on line. All
4043 glyphs have the same width. */
4044 int single_glyph_width = it->pixel_width / it->nglyphs;
4045 int new_x;
4046
4047 for (i = 0; i < it->nglyphs; ++i, x = new_x)
4048 {
4049 new_x = x + single_glyph_width;
4050
4051 /* We want to leave anything reaching TO_X to the caller. */
4052 if ((op & MOVE_TO_X) && new_x > to_x)
4053 {
4054 it->current_x = x;
4055 result = MOVE_X_REACHED;
4056 break;
4057 }
4058 else if (/* Lines are continued. */
4059 !it->truncate_lines_p
4060 && (/* And glyph doesn't fit on the line. */
4061 new_x > it->last_visible_x
4062 /* Or it fits exactly and we're on a window
4063 system frame. */
4064 || (new_x == it->last_visible_x
4065 && FRAME_WINDOW_P (it->f))))
4066 {
4067 if (/* IT->hpos == 0 means the very first glyph
4068 doesn't fit on the line, e.g. a wide image. */
4069 it->hpos == 0
4070 || (new_x == it->last_visible_x
4071 && FRAME_WINDOW_P (it->f)))
4072 {
4073 ++it->hpos;
4074 it->current_x = new_x;
4075 if (i == it->nglyphs - 1)
4076 set_iterator_to_next (it);
4077 }
4078 else
4079 it->current_x = x;
4080
4081 result = MOVE_LINE_CONTINUED;
4082 break;
4083 }
4084 else if (new_x > it->first_visible_x)
4085 {
4086 /* Glyph is visible. Increment number of glyphs that
4087 would be displayed. */
4088 ++it->hpos;
4089 }
4090 else
4091 {
4092 /* Glyph is completely off the left margin of the display
4093 area. Nothing to do. */
4094 }
4095 }
4096
4097 if (result != MOVE_UNDEFINED)
4098 break;
4099 }
4100 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
4101 {
4102 /* Stop when TO_X specified and reached. This check is
4103 necessary here because of lines consisting of a line end,
4104 only. The line end will not produce any glyphs and we
4105 would never get MOVE_X_REACHED. */
4106 xassert (it->nglyphs == 0);
4107 result = MOVE_X_REACHED;
4108 break;
4109 }
4110
4111 /* Is this a line end? If yes, we're done. */
4112 if (ITERATOR_AT_END_OF_LINE_P (it))
4113 {
4114 result = MOVE_NEWLINE_OR_CR;
4115 break;
4116 }
4117
4118 /* The current display element has been consumed. Advance
4119 to the next. */
4120 set_iterator_to_next (it);
4121
4122 /* Stop if lines are truncated and IT's current x-position is
4123 past the right edge of the window now. */
4124 if (it->truncate_lines_p
4125 && it->current_x >= it->last_visible_x)
4126 {
4127 result = MOVE_LINE_TRUNCATED;
4128 break;
4129 }
4130 }
4131
4132 /* Restore the iterator settings altered at the beginning of this
4133 function. */
4134 it->glyph_row = saved_glyph_row;
4135 return result;
4136}
4137
4138
4139/* Move IT forward to a specified buffer position TO_CHARPOS, TO_X,
4140 TO_Y, TO_VPOS. OP is a bit-mask that specifies where to stop. See
4141 the description of enum move_operation_enum.
4142
4143 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
4144 screen line, this function will set IT to the next position >
4145 TO_CHARPOS. */
4146
4147void
4148move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
4149 struct it *it;
4150 int to_charpos, to_x, to_y, to_vpos;
4151 int op;
4152{
4153 enum move_it_result skip, skip2 = MOVE_X_REACHED;
4154 int line_height;
4155
5f5c8ee5
GM
4156 while (1)
4157 {
4158 if (op & MOVE_TO_VPOS)
4159 {
4160 /* If no TO_CHARPOS and no TO_X specified, stop at the
4161 start of the line TO_VPOS. */
4162 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
4163 {
4164 if (it->vpos == to_vpos)
4165 break;
4166 skip = move_it_in_display_line_to (it, -1, -1, 0);
4167 }
4168 else
4169 {
4170 /* TO_VPOS >= 0 means stop at TO_X in the line at
4171 TO_VPOS, or at TO_POS, whichever comes first. */
4172 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
4173
4174 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
4175 break;
4176 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
4177 {
4178 /* We have reached TO_X but not in the line we want. */
4179 skip = move_it_in_display_line_to (it, to_charpos,
4180 -1, MOVE_TO_POS);
4181 if (skip == MOVE_POS_MATCH_OR_ZV)
4182 break;
4183 }
4184 }
4185 }
4186 else if (op & MOVE_TO_Y)
4187 {
4188 struct it it_backup;
4189 int done_p;
4190
4191 /* TO_Y specified means stop at TO_X in the line containing
4192 TO_Y---or at TO_CHARPOS if this is reached first. The
4193 problem is that we can't really tell whether the line
4194 contains TO_Y before we have completely scanned it, and
4195 this may skip past TO_X. What we do is to first scan to
4196 TO_X.
4197
4198 If TO_X is not specified, use a TO_X of zero. The reason
4199 is to make the outcome of this function more predictable.
4200 If we didn't use TO_X == 0, we would stop at the end of
4201 the line which is probably not what a caller would expect
4202 to happen. */
4203 skip = move_it_in_display_line_to (it, to_charpos,
4204 ((op & MOVE_TO_X)
4205 ? to_x : 0),
4206 (MOVE_TO_X
4207 | (op & MOVE_TO_POS)));
4208
4209 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
4210 if (skip == MOVE_POS_MATCH_OR_ZV)
4211 break;
4212
4213 /* If TO_X was reached, we would like to know whether TO_Y
4214 is in the line. This can only be said if we know the
4215 total line height which requires us to scan the rest of
4216 the line. */
4217 done_p = 0;
4218 if (skip == MOVE_X_REACHED)
4219 {
4220 it_backup = *it;
4221 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
4222 op & MOVE_TO_POS);
4223 }
4224
4225 /* Now, decide whether TO_Y is in this line. */
4226 line_height = it->max_ascent + it->max_descent;
4227
4228 if (to_y >= it->current_y
4229 && to_y < it->current_y + line_height)
4230 {
4231 if (skip == MOVE_X_REACHED)
4232 /* If TO_Y is in this line and TO_X was reached above,
4233 we scanned too far. We have to restore IT's settings
4234 to the ones before skipping. */
4235 *it = it_backup;
4236 done_p = 1;
4237 }
4238 else if (skip == MOVE_X_REACHED)
4239 {
4240 skip = skip2;
4241 if (skip == MOVE_POS_MATCH_OR_ZV)
4242 done_p = 1;
4243 }
4244
4245 if (done_p)
4246 break;
4247 }
4248 else
4249 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
4250
4251 switch (skip)
4252 {
4253 case MOVE_POS_MATCH_OR_ZV:
4254 return;
4255
4256 case MOVE_NEWLINE_OR_CR:
4257 set_iterator_to_next (it);
4258 it->continuation_lines_width = 0;
4259 break;
4260
4261 case MOVE_LINE_TRUNCATED:
4262 it->continuation_lines_width = 0;
312246d1 4263 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4264 if ((op & MOVE_TO_POS) != 0
4265 && IT_CHARPOS (*it) > to_charpos)
4266 goto out;
4267 break;
4268
4269 case MOVE_LINE_CONTINUED:
4270 it->continuation_lines_width += it->current_x;
4271 break;
4272
4273 default:
4274 abort ();
4275 }
4276
4277 /* Reset/increment for the next run. */
4278 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
4279 it->current_x = it->hpos = 0;
4280 it->current_y += it->max_ascent + it->max_descent;
4281 ++it->vpos;
4282 last_height = it->max_ascent + it->max_descent;
4283 last_max_ascent = it->max_ascent;
4284 it->max_ascent = it->max_descent = 0;
4285 }
4286 out:;
4287}
4288
4289
4290/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
4291
4292 If DY > 0, move IT backward at least that many pixels. DY = 0
4293 means move IT backward to the preceding line start or BEGV. This
4294 function may move over more than DY pixels if IT->current_y - DY
4295 ends up in the middle of a line; in this case IT->current_y will be
4296 set to the top of the line moved to. */
4297
4298void
4299move_it_vertically_backward (it, dy)
4300 struct it *it;
4301 int dy;
4302{
4303 int nlines, h, line_height;
4304 struct it it2;
4305 int start_pos = IT_CHARPOS (*it);
4306
4307 xassert (dy >= 0);
4308
4309 /* Estimate how many newlines we must move back. */
4310 nlines = max (1, dy / CANON_Y_UNIT (it->f));
4311
4312 /* Set the iterator's position that many lines back. */
4313 while (nlines-- && IT_CHARPOS (*it) > BEGV)
4314 back_to_previous_visible_line_start (it);
4315
4316 /* Reseat the iterator here. When moving backward, we don't want
4317 reseat to skip forward over invisible text, set up the iterator
4318 to deliver from overlay strings at the new position etc. So,
4319 use reseat_1 here. */
4320 reseat_1 (it, it->current.pos, 1);
4321
4322 /* We are now surely at a line start. */
4323 it->current_x = it->hpos = 0;
4324
4325 /* Move forward and see what y-distance we moved. First move to the
4326 start of the next line so that we get its height. We need this
4327 height to be able to tell whether we reached the specified
4328 y-distance. */
4329 it2 = *it;
4330 it2.max_ascent = it2.max_descent = 0;
4331 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
4332 MOVE_TO_POS | MOVE_TO_VPOS);
4333 xassert (IT_CHARPOS (*it) >= BEGV);
4334 line_height = it2.max_ascent + it2.max_descent;
4335 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
4336 xassert (IT_CHARPOS (*it) >= BEGV);
4337 h = it2.current_y - it->current_y;
4338 nlines = it2.vpos - it->vpos;
4339
4340 /* Correct IT's y and vpos position. */
4341 it->vpos -= nlines;
4342 it->current_y -= h;
4343
4344 if (dy == 0)
4345 {
4346 /* DY == 0 means move to the start of the screen line. The
4347 value of nlines is > 0 if continuation lines were involved. */
4348 if (nlines > 0)
4349 move_it_by_lines (it, nlines, 1);
4350 xassert (IT_CHARPOS (*it) <= start_pos);
4351 }
4352 else if (nlines)
4353 {
4354 /* The y-position we try to reach. Note that h has been
4355 subtracted in front of the if-statement. */
4356 int target_y = it->current_y + h - dy;
4357
4358 /* If we did not reach target_y, try to move further backward if
4359 we can. If we moved too far backward, try to move forward. */
4360 if (target_y < it->current_y
4361 && IT_CHARPOS (*it) > BEGV)
4362 {
4363 move_it_vertically (it, target_y - it->current_y);
4364 xassert (IT_CHARPOS (*it) >= BEGV);
4365 }
4366 else if (target_y >= it->current_y + line_height
4367 && IT_CHARPOS (*it) < ZV)
4368 {
4369 move_it_vertically (it, target_y - (it->current_y + line_height));
4370 xassert (IT_CHARPOS (*it) >= BEGV);
4371 }
4372 }
4373}
4374
4375
4376/* Move IT by a specified amount of pixel lines DY. DY negative means
4377 move backwards. DY = 0 means move to start of screen line. At the
4378 end, IT will be on the start of a screen line. */
4379
4380void
4381move_it_vertically (it, dy)
4382 struct it *it;
4383 int dy;
4384{
4385 if (dy <= 0)
4386 move_it_vertically_backward (it, -dy);
4387 else if (dy > 0)
4388 {
4389 move_it_to (it, ZV, -1, it->current_y + dy, -1,
4390 MOVE_TO_POS | MOVE_TO_Y);
4391
4392 /* If buffer ends in ZV without a newline, move to the start of
4393 the line to satisfy the post-condition. */
4394 if (IT_CHARPOS (*it) == ZV
4395 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
4396 move_it_by_lines (it, 0, 0);
4397 }
4398}
4399
4400
4401/* Return non-zero if some text between buffer positions START_CHARPOS
4402 and END_CHARPOS is invisible. IT->window is the window for text
4403 property lookup. */
4404
4405static int
4406invisible_text_between_p (it, start_charpos, end_charpos)
4407 struct it *it;
4408 int start_charpos, end_charpos;
4409{
4410#ifdef USE_TEXT_PROPERTIES
4411 Lisp_Object prop, limit;
4412 int invisible_found_p;
4413
4414 xassert (it != NULL && start_charpos <= end_charpos);
4415
4416 /* Is text at START invisible? */
4417 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
4418 it->window);
4419 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4420 invisible_found_p = 1;
4421 else
4422 {
6c577098
GM
4423 limit = next_single_char_property_change (make_number (start_charpos),
4424 Qinvisible, Qnil,
4425 make_number (end_charpos));
5f5c8ee5
GM
4426 invisible_found_p = XFASTINT (limit) < end_charpos;
4427 }
4428
4429 return invisible_found_p;
4430
4431#else /* not USE_TEXT_PROPERTIES */
4432 return 0;
4433#endif /* not USE_TEXT_PROPERTIES */
4434}
4435
4436
4437/* Move IT by a specified number DVPOS of screen lines down. DVPOS
4438 negative means move up. DVPOS == 0 means move to the start of the
4439 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
4440 NEED_Y_P is zero, IT->current_y will be left unchanged.
4441
4442 Further optimization ideas: If we would know that IT->f doesn't use
4443 a face with proportional font, we could be faster for
4444 truncate-lines nil. */
4445
4446void
4447move_it_by_lines (it, dvpos, need_y_p)
4448 struct it *it;
4449 int dvpos, need_y_p;
4450{
4451 struct position pos;
4452
4453 if (!FRAME_WINDOW_P (it->f))
4454 {
4455 struct text_pos textpos;
4456
4457 /* We can use vmotion on frames without proportional fonts. */
4458 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
4459 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
4460 reseat (it, textpos, 1);
4461 it->vpos += pos.vpos;
4462 it->current_y += pos.vpos;
4463 }
4464 else if (dvpos == 0)
4465 {
4466 /* DVPOS == 0 means move to the start of the screen line. */
4467 move_it_vertically_backward (it, 0);
4468 xassert (it->current_x == 0 && it->hpos == 0);
4469 }
4470 else if (dvpos > 0)
4471 {
4472 /* If there are no continuation lines, and if there is no
4473 selective display, try the simple method of moving forward
4474 DVPOS newlines, then see where we are. */
4475 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4476 {
4477 int shortage = 0, charpos;
4478
4479 if (FETCH_BYTE (IT_BYTEPOS (*it) == '\n'))
4480 charpos = IT_CHARPOS (*it) + 1;
4481 else
4482 charpos = scan_buffer ('\n', IT_CHARPOS (*it), 0, dvpos,
4483 &shortage, 0);
4484
4485 if (!invisible_text_between_p (it, IT_CHARPOS (*it), charpos))
4486 {
4487 struct text_pos pos;
4488 CHARPOS (pos) = charpos;
4489 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4490 reseat (it, pos, 1);
4491 it->vpos += dvpos - shortage;
4492 it->hpos = it->current_x = 0;
4493 return;
4494 }
4495 }
4496
4497 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
4498 }
4499 else
4500 {
4501 struct it it2;
4502 int start_charpos, i;
4503
4504 /* If there are no continuation lines, and if there is no
4505 selective display, try the simple method of moving backward
4506 -DVPOS newlines. */
4507 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4508 {
4509 int shortage;
4510 int charpos = IT_CHARPOS (*it);
4511 int bytepos = IT_BYTEPOS (*it);
4512
4513 /* If in the middle of a line, go to its start. */
4514 if (charpos > BEGV && FETCH_BYTE (bytepos - 1) != '\n')
4515 {
4516 charpos = find_next_newline_no_quit (charpos, -1);
4517 bytepos = CHAR_TO_BYTE (charpos);
4518 }
4519
4520 if (charpos == BEGV)
4521 {
4522 struct text_pos pos;
4523 CHARPOS (pos) = charpos;
4524 BYTEPOS (pos) = bytepos;
4525 reseat (it, pos, 1);
4526 it->hpos = it->current_x = 0;
4527 return;
4528 }
4529 else
4530 {
4531 charpos = scan_buffer ('\n', charpos - 1, 0, dvpos, &shortage, 0);
4532 if (!invisible_text_between_p (it, charpos, IT_CHARPOS (*it)))
4533 {
4534 struct text_pos pos;
4535 CHARPOS (pos) = charpos;
4536 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4537 reseat (it, pos, 1);
4538 it->vpos += dvpos + (shortage ? shortage - 1 : 0);
4539 it->hpos = it->current_x = 0;
4540 return;
4541 }
4542 }
4543 }
4544
4545 /* Go back -DVPOS visible lines and reseat the iterator there. */
4546 start_charpos = IT_CHARPOS (*it);
4547 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
4548 back_to_previous_visible_line_start (it);
4549 reseat (it, it->current.pos, 1);
4550 it->current_x = it->hpos = 0;
4551
4552 /* Above call may have moved too far if continuation lines
4553 are involved. Scan forward and see if it did. */
4554 it2 = *it;
4555 it2.vpos = it2.current_y = 0;
4556 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
4557 it->vpos -= it2.vpos;
4558 it->current_y -= it2.current_y;
4559 it->current_x = it->hpos = 0;
4560
4561 /* If we moved too far, move IT some lines forward. */
4562 if (it2.vpos > -dvpos)
4563 {
4564 int delta = it2.vpos + dvpos;
4565 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
4566 }
4567 }
4568}
4569
4570
4571\f
4572/***********************************************************************
4573 Messages
4574 ***********************************************************************/
4575
4576
937248bc
GM
4577/* Add a message with format string FORMAT and arguments ARG1 and ARG2
4578 to *Messages*. */
4579
4580void
4581add_to_log (format, arg1, arg2)
4582 char *format;
4583 Lisp_Object arg1, arg2;
4584{
4585 Lisp_Object args[3];
4586 Lisp_Object msg, fmt;
4587 char *buffer;
4588 int len;
4589 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4590
4591 fmt = msg = Qnil;
4592 GCPRO4 (fmt, msg, arg1, arg2);
4593
4594 args[0] = fmt = build_string (format);
4595 args[1] = arg1;
4596 args[2] = arg2;
4597 msg = Fformat (make_number (3), args);
4598
4599 len = STRING_BYTES (XSTRING (msg)) + 1;
4600 buffer = (char *) alloca (len);
4601 strcpy (buffer, XSTRING (msg)->data);
4602
4603 message_dolog (buffer, len, 1, 0);
4604 UNGCPRO;
4605}
4606
4607
5f5c8ee5
GM
4608/* Output a newline in the *Messages* buffer if "needs" one. */
4609
4610void
4611message_log_maybe_newline ()
4612{
4613 if (message_log_need_newline)
4614 message_dolog ("", 0, 1, 0);
4615}
4616
4617
4618/* Add a string M of length LEN to the message log, optionally
4619 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
4620 nonzero, means interpret the contents of M as multibyte. This
4621 function calls low-level routines in order to bypass text property
4622 hooks, etc. which might not be safe to run. */
4623
4624void
4625message_dolog (m, len, nlflag, multibyte)
4626 char *m;
4627 int len, nlflag, multibyte;
4628{
4629 if (!NILP (Vmessage_log_max))
4630 {
4631 struct buffer *oldbuf;
4632 Lisp_Object oldpoint, oldbegv, oldzv;
4633 int old_windows_or_buffers_changed = windows_or_buffers_changed;
4634 int point_at_end = 0;
4635 int zv_at_end = 0;
4636 Lisp_Object old_deactivate_mark, tem;
4637 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4638
4639 old_deactivate_mark = Vdeactivate_mark;
4640 oldbuf = current_buffer;
4641 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
4642 current_buffer->undo_list = Qt;
4643
4644 oldpoint = Fpoint_marker ();
4645 oldbegv = Fpoint_min_marker ();
4646 oldzv = Fpoint_max_marker ();
4647 GCPRO4 (oldpoint, oldbegv, oldzv, old_deactivate_mark);
4648
4649 if (PT == Z)
4650 point_at_end = 1;
4651 if (ZV == Z)
4652 zv_at_end = 1;
4653
4654 BEGV = BEG;
4655 BEGV_BYTE = BEG_BYTE;
4656 ZV = Z;
4657 ZV_BYTE = Z_BYTE;
4658 TEMP_SET_PT_BOTH (Z, Z_BYTE);
4659
4660 /* Insert the string--maybe converting multibyte to single byte
4661 or vice versa, so that all the text fits the buffer. */
4662 if (multibyte
4663 && NILP (current_buffer->enable_multibyte_characters))
4664 {
4665 int i, c, nbytes;
4666 unsigned char work[1];
4667
4668 /* Convert a multibyte string to single-byte
4669 for the *Message* buffer. */
4670 for (i = 0; i < len; i += nbytes)
4671 {
4fdb80f2 4672 c = string_char_and_length (m + i, len - i, &nbytes);
5f5c8ee5
GM
4673 work[0] = (SINGLE_BYTE_CHAR_P (c)
4674 ? c
4675 : multibyte_char_to_unibyte (c, Qnil));
4676 insert_1_both (work, 1, 1, 1, 0, 0);
4677 }
4678 }
4679 else if (! multibyte
4680 && ! NILP (current_buffer->enable_multibyte_characters))
4681 {
4682 int i, c, nbytes;
4683 unsigned char *msg = (unsigned char *) m;
4684 unsigned char *str, work[4];
4685 /* Convert a single-byte string to multibyte
4686 for the *Message* buffer. */
4687 for (i = 0; i < len; i++)
4688 {
4689 c = unibyte_char_to_multibyte (msg[i]);
4690 nbytes = CHAR_STRING (c, work, str);
4691 insert_1_both (work, 1, nbytes, 1, 0, 0);
4692 }
4693 }
4694 else if (len)
4695 insert_1 (m, len, 1, 0, 0);
4696
4697 if (nlflag)
4698 {
4699 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
4700 insert_1 ("\n", 1, 1, 0, 0);
4701
4702 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
4703 this_bol = PT;
4704 this_bol_byte = PT_BYTE;
4705
4706 if (this_bol > BEG)
4707 {
4708 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
4709 prev_bol = PT;
4710 prev_bol_byte = PT_BYTE;
4711
4712 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
4713 this_bol, this_bol_byte);
4714 if (dup)
4715 {
4716 del_range_both (prev_bol, prev_bol_byte,
4717 this_bol, this_bol_byte, 0);
4718 if (dup > 1)
4719 {
4720 char dupstr[40];
4721 int duplen;
4722
4723 /* If you change this format, don't forget to also
4724 change message_log_check_duplicate. */
4725 sprintf (dupstr, " [%d times]", dup);
4726 duplen = strlen (dupstr);
4727 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
4728 insert_1 (dupstr, duplen, 1, 0, 1);
4729 }
4730 }
4731 }
4732
4733 if (NATNUMP (Vmessage_log_max))
4734 {
4735 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
4736 -XFASTINT (Vmessage_log_max) - 1, 0);
4737 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
4738 }
4739 }
4740 BEGV = XMARKER (oldbegv)->charpos;
4741 BEGV_BYTE = marker_byte_position (oldbegv);
4742
4743 if (zv_at_end)
4744 {
4745 ZV = Z;
4746 ZV_BYTE = Z_BYTE;
4747 }
4748 else
4749 {
4750 ZV = XMARKER (oldzv)->charpos;
4751 ZV_BYTE = marker_byte_position (oldzv);
4752 }
4753
4754 if (point_at_end)
4755 TEMP_SET_PT_BOTH (Z, Z_BYTE);
4756 else
4757 /* We can't do Fgoto_char (oldpoint) because it will run some
4758 Lisp code. */
4759 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
4760 XMARKER (oldpoint)->bytepos);
4761
4762 UNGCPRO;
4763 free_marker (oldpoint);
4764 free_marker (oldbegv);
4765 free_marker (oldzv);
4766
4767 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
4768 set_buffer_internal (oldbuf);
4769 if (NILP (tem))
4770 windows_or_buffers_changed = old_windows_or_buffers_changed;
4771 message_log_need_newline = !nlflag;
4772 Vdeactivate_mark = old_deactivate_mark;
4773 }
4774}
4775
4776
4777/* We are at the end of the buffer after just having inserted a newline.
4778 (Note: We depend on the fact we won't be crossing the gap.)
4779 Check to see if the most recent message looks a lot like the previous one.
4780 Return 0 if different, 1 if the new one should just replace it, or a
4781 value N > 1 if we should also append " [N times]". */
4782
4783static int
4784message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
4785 int prev_bol, this_bol;
4786 int prev_bol_byte, this_bol_byte;
4787{
4788 int i;
4789 int len = Z_BYTE - 1 - this_bol_byte;
4790 int seen_dots = 0;
4791 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
4792 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
4793
4794 for (i = 0; i < len; i++)
4795 {
4796 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
4797 && p1[i] != '\n')
4798 seen_dots = 1;
4799 if (p1[i] != p2[i])
4800 return seen_dots;
4801 }
4802 p1 += len;
4803 if (*p1 == '\n')
4804 return 2;
4805 if (*p1++ == ' ' && *p1++ == '[')
4806 {
4807 int n = 0;
4808 while (*p1 >= '0' && *p1 <= '9')
4809 n = n * 10 + *p1++ - '0';
4810 if (strncmp (p1, " times]\n", 8) == 0)
4811 return n+1;
4812 }
4813 return 0;
4814}
4815
4816
4817/* Display an echo area message M with a specified length of LEN
4818 chars. The string may include null characters. If M is 0, clear
4819 out any existing message, and let the mini-buffer text show through.
4820
4821 The buffer M must continue to exist until after the echo area gets
4822 cleared or some other message gets displayed there. This means do
4823 not pass text that is stored in a Lisp string; do not pass text in
4824 a buffer that was alloca'd. */
4825
4826void
4827message2 (m, len, multibyte)
4828 char *m;
4829 int len;
4830 int multibyte;
4831{
4832 /* First flush out any partial line written with print. */
4833 message_log_maybe_newline ();
4834 if (m)
4835 message_dolog (m, len, 1, multibyte);
4836 message2_nolog (m, len, multibyte);
4837}
4838
4839
4840/* The non-logging counterpart of message2. */
4841
4842void
4843message2_nolog (m, len, multibyte)
4844 char *m;
4845 int len;
4846{
886bd6f2 4847 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
4848 message_enable_multibyte = multibyte;
4849
4850 if (noninteractive)
4851 {
4852 if (noninteractive_need_newline)
4853 putc ('\n', stderr);
4854 noninteractive_need_newline = 0;
4855 if (m)
4856 fwrite (m, len, 1, stderr);
4857 if (cursor_in_echo_area == 0)
4858 fprintf (stderr, "\n");
4859 fflush (stderr);
4860 }
4861 /* A null message buffer means that the frame hasn't really been
4862 initialized yet. Error messages get reported properly by
4863 cmd_error, so this must be just an informative message; toss it. */
4864 else if (INTERACTIVE
886bd6f2
GM
4865 && sf->glyphs_initialized_p
4866 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
4867 {
4868 Lisp_Object mini_window;
4869 struct frame *f;
4870
4871 /* Get the frame containing the mini-buffer
4872 that the selected frame is using. */
886bd6f2 4873 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
4874 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
4875
4876 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 4877 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
4878 && ! FRAME_VISIBLE_P (f))
4879 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
4880
4881 if (m)
4882 {
c6e89d6c 4883 set_message (m, Qnil, len, multibyte);
5f5c8ee5
GM
4884 if (minibuffer_auto_raise)
4885 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
4886 }
4887 else
c6e89d6c 4888 clear_message (1, 1);
5f5c8ee5 4889
c6e89d6c 4890 do_pending_window_change (0);
5f5c8ee5 4891 echo_area_display (1);
c6e89d6c 4892 do_pending_window_change (0);
5f5c8ee5
GM
4893 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
4894 (*frame_up_to_date_hook) (f);
4895 }
4896}
4897
4898
c6e89d6c
GM
4899/* Display an echo area message M with a specified length of NBYTES
4900 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
4901 string, clear out any existing message, and let the mini-buffer
4902 text show through. */
4903
4904void
c6e89d6c 4905message3 (m, nbytes, multibyte)
5f5c8ee5 4906 Lisp_Object m;
c6e89d6c 4907 int nbytes;
5f5c8ee5
GM
4908 int multibyte;
4909{
4910 struct gcpro gcpro1;
4911
4912 GCPRO1 (m);
4913
4914 /* First flush out any partial line written with print. */
4915 message_log_maybe_newline ();
4916 if (STRINGP (m))
c6e89d6c
GM
4917 message_dolog (XSTRING (m)->data, nbytes, 1, multibyte);
4918 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
4919
4920 UNGCPRO;
4921}
4922
4923
4924/* The non-logging version of message3. */
4925
4926void
c6e89d6c 4927message3_nolog (m, nbytes, multibyte)
5f5c8ee5 4928 Lisp_Object m;
c6e89d6c 4929 int nbytes, multibyte;
5f5c8ee5 4930{
886bd6f2 4931 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
4932 message_enable_multibyte = multibyte;
4933
4934 if (noninteractive)
4935 {
4936 if (noninteractive_need_newline)
4937 putc ('\n', stderr);
4938 noninteractive_need_newline = 0;
4939 if (STRINGP (m))
c6e89d6c 4940 fwrite (XSTRING (m)->data, nbytes, 1, stderr);
5f5c8ee5
GM
4941 if (cursor_in_echo_area == 0)
4942 fprintf (stderr, "\n");
4943 fflush (stderr);
4944 }
4945 /* A null message buffer means that the frame hasn't really been
4946 initialized yet. Error messages get reported properly by
4947 cmd_error, so this must be just an informative message; toss it. */
4948 else if (INTERACTIVE
886bd6f2
GM
4949 && sf->glyphs_initialized_p
4950 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
4951 {
4952 Lisp_Object mini_window;
c6e89d6c 4953 Lisp_Object frame;
5f5c8ee5
GM
4954 struct frame *f;
4955
4956 /* Get the frame containing the mini-buffer
4957 that the selected frame is using. */
886bd6f2 4958 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
4959 frame = XWINDOW (mini_window)->frame;
4960 f = XFRAME (frame);
5f5c8ee5
GM
4961
4962 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 4963 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
4964 && !FRAME_VISIBLE_P (f))
4965 Fmake_frame_visible (frame);
5f5c8ee5 4966
c6e89d6c 4967 if (STRINGP (m) && XSTRING (m)->size)
5f5c8ee5 4968 {
c6e89d6c 4969 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
4970 if (minibuffer_auto_raise)
4971 Fraise_frame (frame);
5f5c8ee5
GM
4972 }
4973 else
c6e89d6c 4974 clear_message (1, 1);
5f5c8ee5 4975
c6e89d6c 4976 do_pending_window_change (0);
5f5c8ee5 4977 echo_area_display (1);
c6e89d6c 4978 do_pending_window_change (0);
5f5c8ee5
GM
4979 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
4980 (*frame_up_to_date_hook) (f);
4981 }
4982}
4983
4984
4985/* Display a null-terminated echo area message M. If M is 0, clear
4986 out any existing message, and let the mini-buffer text show through.
4987
4988 The buffer M must continue to exist until after the echo area gets
4989 cleared or some other message gets displayed there. Do not pass
4990 text that is stored in a Lisp string. Do not pass text in a buffer
4991 that was alloca'd. */
4992
4993void
4994message1 (m)
4995 char *m;
4996{
4997 message2 (m, (m ? strlen (m) : 0), 0);
4998}
4999
5000
5001/* The non-logging counterpart of message1. */
5002
5003void
5004message1_nolog (m)
5005 char *m;
5006{
5007 message2_nolog (m, (m ? strlen (m) : 0), 0);
5008}
5009
5010/* Display a message M which contains a single %s
5011 which gets replaced with STRING. */
5012
5013void
5014message_with_string (m, string, log)
5015 char *m;
5016 Lisp_Object string;
5017 int log;
5018{
5019 if (noninteractive)
5020 {
5021 if (m)
5022 {
5023 if (noninteractive_need_newline)
5024 putc ('\n', stderr);
5025 noninteractive_need_newline = 0;
5026 fprintf (stderr, m, XSTRING (string)->data);
5027 if (cursor_in_echo_area == 0)
5028 fprintf (stderr, "\n");
5029 fflush (stderr);
5030 }
5031 }
5032 else if (INTERACTIVE)
5033 {
5034 /* The frame whose minibuffer we're going to display the message on.
5035 It may be larger than the selected frame, so we need
5036 to use its buffer, not the selected frame's buffer. */
5037 Lisp_Object mini_window;
886bd6f2 5038 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5039
5040 /* Get the frame containing the minibuffer
5041 that the selected frame is using. */
886bd6f2 5042 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5043 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5044
5045 /* A null message buffer means that the frame hasn't really been
5046 initialized yet. Error messages get reported properly by
5047 cmd_error, so this must be just an informative message; toss it. */
5048 if (FRAME_MESSAGE_BUF (f))
5049 {
5050 int len;
5051 char *a[1];
5052 a[0] = (char *) XSTRING (string)->data;
5053
5054 len = doprnt (FRAME_MESSAGE_BUF (f),
5055 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5056
5057 if (log)
5058 message2 (FRAME_MESSAGE_BUF (f), len,
5059 STRING_MULTIBYTE (string));
5060 else
5061 message2_nolog (FRAME_MESSAGE_BUF (f), len,
5062 STRING_MULTIBYTE (string));
5063
5064 /* Print should start at the beginning of the message
5065 buffer next time. */
5066 message_buf_print = 0;
5067 }
5068 }
5069}
5070
5071
5f5c8ee5
GM
5072/* Dump an informative message to the minibuf. If M is 0, clear out
5073 any existing message, and let the mini-buffer text show through. */
5074
5075/* VARARGS 1 */
5076void
5077message (m, a1, a2, a3)
5078 char *m;
5079 EMACS_INT a1, a2, a3;
5080{
5081 if (noninteractive)
5082 {
5083 if (m)
5084 {
5085 if (noninteractive_need_newline)
5086 putc ('\n', stderr);
5087 noninteractive_need_newline = 0;
5088 fprintf (stderr, m, a1, a2, a3);
5089 if (cursor_in_echo_area == 0)
5090 fprintf (stderr, "\n");
5091 fflush (stderr);
5092 }
5093 }
5094 else if (INTERACTIVE)
5095 {
5096 /* The frame whose mini-buffer we're going to display the message
5097 on. It may be larger than the selected frame, so we need to
5098 use its buffer, not the selected frame's buffer. */
5099 Lisp_Object mini_window;
886bd6f2 5100 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5101
5102 /* Get the frame containing the mini-buffer
5103 that the selected frame is using. */
886bd6f2 5104 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5105 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5106
5107 /* A null message buffer means that the frame hasn't really been
5108 initialized yet. Error messages get reported properly by
5109 cmd_error, so this must be just an informative message; toss
5110 it. */
5111 if (FRAME_MESSAGE_BUF (f))
5112 {
5113 if (m)
5114 {
5115 int len;
5116#ifdef NO_ARG_ARRAY
5117 char *a[3];
5118 a[0] = (char *) a1;
5119 a[1] = (char *) a2;
5120 a[2] = (char *) a3;
5121
5122 len = doprnt (FRAME_MESSAGE_BUF (f),
5123 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5124#else
5125 len = doprnt (FRAME_MESSAGE_BUF (f),
5126 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
5127 (char **) &a1);
5128#endif /* NO_ARG_ARRAY */
5129
5130 message2 (FRAME_MESSAGE_BUF (f), len, 0);
5131 }
5132 else
5133 message1 (0);
5134
5135 /* Print should start at the beginning of the message
5136 buffer next time. */
5137 message_buf_print = 0;
5138 }
5139 }
5140}
5141
5142
5143/* The non-logging version of message. */
5144
5145void
5146message_nolog (m, a1, a2, a3)
5147 char *m;
5148 EMACS_INT a1, a2, a3;
5149{
5150 Lisp_Object old_log_max;
5151 old_log_max = Vmessage_log_max;
5152 Vmessage_log_max = Qnil;
5153 message (m, a1, a2, a3);
5154 Vmessage_log_max = old_log_max;
5155}
5156
5157
c6e89d6c
GM
5158/* Display the current message in the current mini-buffer. This is
5159 only called from error handlers in process.c, and is not time
5160 critical. */
5f5c8ee5
GM
5161
5162void
5163update_echo_area ()
5164{
c6e89d6c
GM
5165 if (!NILP (echo_area_buffer[0]))
5166 {
5167 Lisp_Object string;
5168 string = Fcurrent_message ();
5169 message3 (string, XSTRING (string)->size,
5170 !NILP (current_buffer->enable_multibyte_characters));
5171 }
5172}
5173
5174
5175/* Call FN with args A1..A5 with either the current or last displayed
5176 echo_area_buffer as current buffer.
5177
5178 WHICH zero means use the current message buffer
5179 echo_area_buffer[0]. If that is nil, choose a suitable buffer
5180 from echo_buffer[] and clear it.
5181
5182 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
5183 suitable buffer from echo_buffer[] and clear it.
5184
5185 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
5186 that the current message becomes the last displayed one, make
5187 choose a suitable buffer for echo_area_buffer[0], and clear it.
5188
5189 Value is what FN returns. */
5190
5191static int
5192with_echo_area_buffer (w, which, fn, a1, a2, a3, a4, a5)
5193 struct window *w;
5194 int which;
5195 int (*fn) ();
5196 int a1, a2, a3, a4, a5;
5197{
5198 Lisp_Object buffer;
5199 int i, this_one, the_other, clear_buffer_p, rc;
5200 int count = specpdl_ptr - specpdl;
5201
5202 /* If buffers aren't life, make new ones. */
5203 for (i = 0; i < 2; ++i)
5204 if (!BUFFERP (echo_buffer[i])
5205 || NILP (XBUFFER (echo_buffer[i])->name))
5206 {
5207 char name[30];
5208 sprintf (name, " *Echo Area %d*", i);
5209 echo_buffer[i] = Fget_buffer_create (build_string (name));
5210 }
5211
5212 clear_buffer_p = 0;
5213
5214 if (which == 0)
5215 this_one = 0, the_other = 1;
5216 else if (which > 0)
5217 this_one = 1, the_other = 0;
5f5c8ee5 5218 else
c6e89d6c
GM
5219 {
5220 this_one = 0, the_other = 1;
5221 clear_buffer_p = 1;
5222
5223 /* We need a fresh one in case the current echo buffer equals
5224 the one containing the last displayed echo area message. */
5225 if (!NILP (echo_area_buffer[this_one])
5226 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
5227 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
5228 }
5229
5230 /* Choose a suitable buffer from echo_buffer[] is we don't
5231 have one. */
5232 if (NILP (echo_area_buffer[this_one]))
5233 {
5234 echo_area_buffer[this_one]
5235 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
5236 ? echo_buffer[the_other]
5237 : echo_buffer[this_one]);
5238 clear_buffer_p = 1;
5239 }
5240
5241 buffer = echo_area_buffer[this_one];
5242
5243 record_unwind_protect (unwind_with_echo_area_buffer,
5244 with_echo_area_buffer_unwind_data (w));
5245
5246 /* Make the echo area buffer current. Note that for display
5247 purposes, it is not necessary that the displayed window's buffer
5248 == current_buffer, except for text property lookup. So, let's
5249 only set that buffer temporarily here without doing a full
5250 Fset_window_buffer. We must also change w->pointm, though,
5251 because otherwise an assertions in unshow_buffer fails, and Emacs
5252 aborts. */
9142dd5b 5253 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
5254 if (w)
5255 {
5256 w->buffer = buffer;
5257 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
5258 }
5259 current_buffer->truncate_lines = Qnil;
5260 current_buffer->undo_list = Qt;
5261 current_buffer->read_only = Qnil;
5262
5263 if (clear_buffer_p && Z > BEG)
5264 del_range (BEG, Z);
5265
5266 xassert (BEGV >= BEG);
5267 xassert (ZV <= Z && ZV >= BEGV);
5268
5269 rc = fn (a1, a2, a3, a4, a5);
5270
5271 xassert (BEGV >= BEG);
5272 xassert (ZV <= Z && ZV >= BEGV);
5273
5274 unbind_to (count, Qnil);
5275 return rc;
5f5c8ee5
GM
5276}
5277
5278
c6e89d6c
GM
5279/* Save state that should be preserved around the call to the function
5280 FN called in with_echo_area_buffer. */
5f5c8ee5 5281
c6e89d6c
GM
5282static Lisp_Object
5283with_echo_area_buffer_unwind_data (w)
5284 struct window *w;
5f5c8ee5 5285{
c6e89d6c
GM
5286 int i = 0;
5287 Lisp_Object vector;
5f5c8ee5 5288
c6e89d6c
GM
5289 /* Reduce consing by keeping one vector in
5290 Vwith_echo_area_save_vector. */
5291 vector = Vwith_echo_area_save_vector;
5292 Vwith_echo_area_save_vector = Qnil;
5293
5294 if (NILP (vector))
9142dd5b 5295 vector = Fmake_vector (make_number (7), Qnil);
c6e89d6c
GM
5296
5297 XSETBUFFER (XVECTOR (vector)->contents[i], current_buffer); ++i;
5298 XVECTOR (vector)->contents[i++] = Vdeactivate_mark;
5299 XVECTOR (vector)->contents[i++] = make_number (windows_or_buffers_changed);
c6e89d6c
GM
5300
5301 if (w)
5302 {
5303 XSETWINDOW (XVECTOR (vector)->contents[i], w); ++i;
5304 XVECTOR (vector)->contents[i++] = w->buffer;
5305 XVECTOR (vector)->contents[i++]
5306 = make_number (XMARKER (w->pointm)->charpos);
5307 XVECTOR (vector)->contents[i++]
5308 = make_number (XMARKER (w->pointm)->bytepos);
5309 }
5310 else
5311 {
5312 int end = i + 4;
5313 while (i < end)
5314 XVECTOR (vector)->contents[i++] = Qnil;
5315 }
5f5c8ee5 5316
c6e89d6c
GM
5317 xassert (i == XVECTOR (vector)->size);
5318 return vector;
5319}
5f5c8ee5 5320
5f5c8ee5 5321
c6e89d6c
GM
5322/* Restore global state from VECTOR which was created by
5323 with_echo_area_buffer_unwind_data. */
5324
5325static Lisp_Object
5326unwind_with_echo_area_buffer (vector)
5327 Lisp_Object vector;
5328{
5329 int i = 0;
5330
9142dd5b 5331 set_buffer_internal_1 (XBUFFER (XVECTOR (vector)->contents[i])); ++i;
c6e89d6c
GM
5332 Vdeactivate_mark = XVECTOR (vector)->contents[i]; ++i;
5333 windows_or_buffers_changed = XFASTINT (XVECTOR (vector)->contents[i]); ++i;
c6e89d6c
GM
5334
5335 if (WINDOWP (XVECTOR (vector)->contents[i]))
5336 {
5337 struct window *w;
5338 Lisp_Object buffer, charpos, bytepos;
5339
5340 w = XWINDOW (XVECTOR (vector)->contents[i]); ++i;
5341 buffer = XVECTOR (vector)->contents[i]; ++i;
5342 charpos = XVECTOR (vector)->contents[i]; ++i;
5343 bytepos = XVECTOR (vector)->contents[i]; ++i;
5344
5345 w->buffer = buffer;
5346 set_marker_both (w->pointm, buffer,
5347 XFASTINT (charpos), XFASTINT (bytepos));
5348 }
5349
5350 Vwith_echo_area_save_vector = vector;
5351 return Qnil;
5352}
5353
5354
5355/* Set up the echo area for use by print functions. MULTIBYTE_P
5356 non-zero means we will print multibyte. */
5357
5358void
5359setup_echo_area_for_printing (multibyte_p)
5360 int multibyte_p;
5361{
5362 if (!message_buf_print)
5363 {
5364 /* A message has been output since the last time we printed.
5365 Choose a fresh echo area buffer. */
5366 if (EQ (echo_area_buffer[1], echo_buffer[0]))
5367 echo_area_buffer[0] = echo_buffer[1];
5368 else
5369 echo_area_buffer[0] = echo_buffer[0];
5370
5371 /* Switch to that buffer and clear it. */
5372 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5373 if (Z > BEG)
5374 del_range (BEG, Z);
5375 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5376
5377 /* Set up the buffer for the multibyteness we need. */
5378 if (multibyte_p
5379 != !NILP (current_buffer->enable_multibyte_characters))
5380 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
5381
5382 /* Raise the frame containing the echo area. */
5383 if (minibuffer_auto_raise)
5384 {
886bd6f2 5385 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5386 Lisp_Object mini_window;
886bd6f2 5387 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5388 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5389 }
5390
5391 message_buf_print = 1;
5392 }
5393 else if (current_buffer != XBUFFER (echo_area_buffer[0]))
5394 /* Someone switched buffers between print requests. */
5395 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5396}
5397
5398
dd2eb166
GM
5399/* Display an echo area message in window W. Value is non-zero if W's
5400 height is changed. If display_last_displayed_message_p is
5401 non-zero, display the message that was last displayed, otherwise
5402 display the current message. */
c6e89d6c
GM
5403
5404static int
5405display_echo_area (w)
5406 struct window *w;
5407{
dd2eb166
GM
5408 int i, no_message_p, window_height_changed_p;
5409
5410 /* If there is no message, we must call display_echo_area_1
5411 nevertheless because it resizes the window. But we will have to
5412 reset the echo_area_buffer in question to nil at the end because
5413 with_echo_area_buffer will sets it to an empty buffer. */
5414 i = display_last_displayed_message_p ? 1 : 0;
5415 no_message_p = NILP (echo_area_buffer[i]);
5416
5417 window_height_changed_p
5418 = with_echo_area_buffer (w, display_last_displayed_message_p,
5419 (int (*) ()) display_echo_area_1, w);
5420
5421 if (no_message_p)
5422 echo_area_buffer[i] = Qnil;
5423
5424 return window_height_changed_p;
c6e89d6c
GM
5425}
5426
5427
5428/* Helper for display_echo_area. Display the current buffer which
5429 contains the current echo area message in window W, a mini-window.
5430 Change the height of W so that all of the message is displayed.
5431 Value is non-zero if height of W was changed. */
5432
5433static int
5434display_echo_area_1 (w)
5435 struct window *w;
5436{
5437 Lisp_Object window;
c6e89d6c
GM
5438 struct text_pos start;
5439 int window_height_changed_p = 0;
5440
5441 /* Do this before displaying, so that we have a large enough glyph
5442 matrix for the display. */
92a90e89 5443 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
5444
5445 /* Display. */
5446 clear_glyph_matrix (w->desired_matrix);
5447 XSETWINDOW (window, w);
5448 SET_TEXT_POS (start, BEG, BEG_BYTE);
5449 try_window (window, start);
5450
c6e89d6c
GM
5451 return window_height_changed_p;
5452}
5453
5454
92a90e89
GM
5455/* Resize the echo area window to exactly the size needed for the
5456 currently displayed message, if there is one. */
5457
5458void
5459resize_echo_area_axactly ()
5460{
5461 if (BUFFERP (echo_area_buffer[0])
5462 && WINDOWP (echo_area_window))
5463 {
5464 struct window *w = XWINDOW (echo_area_window);
5465 int resized_p;
5466
5467 resized_p = with_echo_area_buffer (w, 0,
5468 (int (*) ()) resize_mini_window,
5469 w, 1);
5470 if (resized_p)
5471 {
5472 ++windows_or_buffers_changed;
5473 ++update_mode_lines;
5474 redisplay_internal (0);
5475 }
5476 }
5477}
5478
5479
5480/* Resize mini-window W to fit the size of its contents. EXACT:P
5481 means size the window exactly to the size needed. Otherwise, it's
5482 only enlarged until W's buffer is empty. Value is non-zero if
5483 the window height has been changed. */
c6e89d6c 5484
9472f927 5485int
92a90e89 5486resize_mini_window (w, exact_p)
c6e89d6c 5487 struct window *w;
92a90e89 5488 int exact_p;
c6e89d6c
GM
5489{
5490 struct frame *f = XFRAME (w->frame);
5491 int window_height_changed_p = 0;
5492
5493 xassert (MINI_WINDOW_P (w));
97cafc0f
GM
5494
5495 /* Nil means don't try to resize. */
00f6d59e
GM
5496 if (NILP (Vmax_mini_window_height)
5497 || (FRAME_X_P (f) && f->output_data.x == NULL))
97cafc0f 5498 return 0;
c6e89d6c
GM
5499
5500 if (!FRAME_MINIBUF_ONLY_P (f))
5501 {
5502 struct it it;
dd2eb166
GM
5503 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
5504 int total_height = XFASTINT (root->height) + XFASTINT (w->height);
5505 int height, max_height;
5506 int unit = CANON_Y_UNIT (f);
5507 struct text_pos start;
9142dd5b 5508
c6e89d6c 5509 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 5510
dd2eb166
GM
5511 /* Compute the max. number of lines specified by the user. */
5512 if (FLOATP (Vmax_mini_window_height))
5513 max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
5514 else if (INTEGERP (Vmax_mini_window_height))
5515 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
5516 else
5517 max_height = total_height / 4;
dd2eb166
GM
5518
5519 /* Correct that max. height if it's bogus. */
5520 max_height = max (1, max_height);
5521 max_height = min (total_height, max_height);
5522
5523 /* Find out the height of the text in the window. */
5524 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
5525 height = (unit - 1 + it.current_y + last_height) / unit;
5526 height = max (1, height);
5527
5528 /* Compute a suitable window start. */
5529 if (height > max_height)
5530 {
5531 height = max_height;
5532 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5533 move_it_vertically_backward (&it, (height - 1) * unit);
5534 start = it.current.pos;
5535 }
5536 else
5537 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5538 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 5539
9472f927
GM
5540 /* Let it grow only, until we display an empty message, in which
5541 case the window shrinks again. */
da448723 5542 if (height > XFASTINT (w->height))
dd2eb166 5543 {
d2c48e86 5544 int old_height = XFASTINT (w->height);
da448723
GM
5545 freeze_window_starts (f, 1);
5546 grow_mini_window (w, height - XFASTINT (w->height));
5547 window_height_changed_p = XFASTINT (w->height) != old_height;
5548 }
5549 else if (height < XFASTINT (w->height)
5550 && (exact_p || BEGV == ZV))
5551 {
5552 int old_height = XFASTINT (w->height);
5553 freeze_window_starts (f, 0);
5554 shrink_mini_window (w);
d2c48e86 5555 window_height_changed_p = XFASTINT (w->height) != old_height;
9142dd5b 5556 }
c6e89d6c
GM
5557 }
5558
5559 return window_height_changed_p;
5560}
5561
5562
5563/* Value is the current message, a string, or nil if there is no
5564 current message. */
5565
5566Lisp_Object
5567current_message ()
5568{
5569 Lisp_Object msg;
5570
5571 if (NILP (echo_area_buffer[0]))
5572 msg = Qnil;
5573 else
5574 {
5575 with_echo_area_buffer (0, 0, (int (*) ()) current_message_1, &msg);
5576 if (NILP (msg))
5577 echo_area_buffer[0] = Qnil;
5578 }
5579
5580 return msg;
5581}
5582
5583
5584static int
5585current_message_1 (msg)
5586 Lisp_Object *msg;
5587{
5588 if (Z > BEG)
5589 *msg = make_buffer_string (BEG, Z, 1);
5590 else
5591 *msg = Qnil;
5592 return 0;
5593}
5594
5595
5596/* Push the current message on Vmessage_stack for later restauration
5597 by restore_message. Value is non-zero if the current message isn't
5598 empty. This is a relatively infrequent operation, so it's not
5599 worth optimizing. */
5600
5601int
5602push_message ()
5603{
5604 Lisp_Object msg;
5605 msg = current_message ();
5606 Vmessage_stack = Fcons (msg, Vmessage_stack);
5607 return STRINGP (msg);
5608}
5609
5610
5611/* Restore message display from the top of Vmessage_stack. */
5612
5613void
5614restore_message ()
5615{
5616 Lisp_Object msg;
5617
5618 xassert (CONSP (Vmessage_stack));
5619 msg = XCAR (Vmessage_stack);
5620 if (STRINGP (msg))
5621 message3_nolog (msg, STRING_BYTES (XSTRING (msg)), STRING_MULTIBYTE (msg));
5622 else
5623 message3_nolog (msg, 0, 0);
5624}
5625
5626
5627/* Pop the top-most entry off Vmessage_stack. */
5628
5629void
5630pop_message ()
5631{
5632 xassert (CONSP (Vmessage_stack));
5633 Vmessage_stack = XCDR (Vmessage_stack);
5634}
5635
5636
5637/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
5638 exits. If the stack is not empty, we have a missing pop_message
5639 somewhere. */
5640
5641void
5642check_message_stack ()
5643{
5644 if (!NILP (Vmessage_stack))
5645 abort ();
5646}
5647
5648
5649/* Truncate to NCHARS what will be displayed in the echo area the next
5650 time we display it---but don't redisplay it now. */
5651
5652void
5653truncate_echo_area (nchars)
5654 int nchars;
5655{
5656 if (nchars == 0)
5657 echo_area_buffer[0] = Qnil;
5658 /* A null message buffer means that the frame hasn't really been
5659 initialized yet. Error messages get reported properly by
5660 cmd_error, so this must be just an informative message; toss it. */
5661 else if (!noninteractive
5662 && INTERACTIVE
c6e89d6c 5663 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
5664 {
5665 struct frame *sf = SELECTED_FRAME ();
5666 if (FRAME_MESSAGE_BUF (sf))
5667 with_echo_area_buffer (0, 0, (int (*) ()) truncate_message_1, nchars);
5668 }
c6e89d6c
GM
5669}
5670
5671
5672/* Helper function for truncate_echo_area. Truncate the current
5673 message to at most NCHARS characters. */
5674
5675static int
5676truncate_message_1 (nchars)
5677 int nchars;
5678{
5679 if (BEG + nchars < Z)
5680 del_range (BEG + nchars, Z);
5681 if (Z == BEG)
5682 echo_area_buffer[0] = Qnil;
5683 return 0;
5684}
5685
5686
5687/* Set the current message to a substring of S or STRING.
5688
5689 If STRING is a Lisp string, set the message to the first NBYTES
5690 bytes from STRING. NBYTES zero means use the whole string. If
5691 STRING is multibyte, the message will be displayed multibyte.
5692
5693 If S is not null, set the message to the first LEN bytes of S. LEN
5694 zero means use the whole string. MULTIBYTE_P non-zero means S is
5695 multibyte. Display the message multibyte in that case. */
5696
5697void
5698set_message (s, string, nbytes, multibyte_p)
5699 char *s;
5700 Lisp_Object string;
5701 int nbytes;
5702{
5703 message_enable_multibyte
5704 = ((s && multibyte_p)
5705 || (STRINGP (string) && STRING_MULTIBYTE (string)));
5706
5707 with_echo_area_buffer (0, -1, (int (*) ()) set_message_1,
5708 s, string, nbytes, multibyte_p);
5709 message_buf_print = 0;
5710}
5711
5712
5713/* Helper function for set_message. Arguments have the same meaning
5714 as there. This function is called with the echo area buffer being
5715 current. */
5716
5717static int
5718set_message_1 (s, string, nbytes, multibyte_p)
5719 char *s;
5720 Lisp_Object string;
5721 int nbytes, multibyte_p;
5722{
5723 xassert (BEG == Z);
5724
5725 /* Change multibyteness of the echo buffer appropriately. */
5726 if (message_enable_multibyte
5727 != !NILP (current_buffer->enable_multibyte_characters))
5728 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
5729
5730 /* Insert new message at BEG. */
5731 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5732
5733 if (STRINGP (string))
5734 {
5735 int nchars;
5736
5737 if (nbytes == 0)
5738 nbytes = XSTRING (string)->size_byte;
5739 nchars = string_byte_to_char (string, nbytes);
5740
5741 /* This function takes care of single/multibyte conversion. We
5742 just have to ensure that the echo area buffer has the right
5743 setting of enable_multibyte_characters. */
5744 insert_from_string (string, 0, 0, nchars, nbytes, 1);
5745 }
5746 else if (s)
5747 {
5748 if (nbytes == 0)
5749 nbytes = strlen (s);
5750
5751 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
5752 {
5753 /* Convert from multi-byte to single-byte. */
5754 int i, c, n;
5755 unsigned char work[1];
5756
5757 /* Convert a multibyte string to single-byte. */
5758 for (i = 0; i < nbytes; i += n)
5759 {
5760 c = string_char_and_length (s + i, nbytes - i, &n);
5761 work[0] = (SINGLE_BYTE_CHAR_P (c)
5762 ? c
5763 : multibyte_char_to_unibyte (c, Qnil));
5764 insert_1_both (work, 1, 1, 1, 0, 0);
5765 }
5766 }
5767 else if (!multibyte_p
5768 && !NILP (current_buffer->enable_multibyte_characters))
5769 {
5770 /* Convert from single-byte to multi-byte. */
5771 int i, c, n;
5772 unsigned char *msg = (unsigned char *) s;
5773 unsigned char *str, work[4];
5774
5775 /* Convert a single-byte string to multibyte. */
5776 for (i = 0; i < nbytes; i++)
5777 {
5778 c = unibyte_char_to_multibyte (msg[i]);
5779 n = CHAR_STRING (c, work, str);
5780 insert_1_both (work, 1, n, 1, 0, 0);
5781 }
5782 }
5783 else
5784 insert_1 (s, nbytes, 1, 0, 0);
5785 }
5786
5787 return 0;
5788}
5789
5790
5791/* Clear messages. CURRENT_P non-zero means clear the current
5792 message. LAST_DISPLAYED_P non-zero means clear the message
5793 last displayed. */
5794
5795void
5796clear_message (current_p, last_displayed_p)
5797 int current_p, last_displayed_p;
5798{
5799 if (current_p)
5800 echo_area_buffer[0] = Qnil;
5801
5802 if (last_displayed_p)
5803 echo_area_buffer[1] = Qnil;
5804
5805 message_buf_print = 0;
5806}
5807
5808/* Clear garbaged frames.
5809
5810 This function is used where the old redisplay called
5811 redraw_garbaged_frames which in turn called redraw_frame which in
5812 turn called clear_frame. The call to clear_frame was a source of
5813 flickering. I believe a clear_frame is not necessary. It should
5814 suffice in the new redisplay to invalidate all current matrices,
5815 and ensure a complete redisplay of all windows. */
5816
5817static void
5818clear_garbaged_frames ()
5819{
5f5c8ee5
GM
5820 if (frame_garbaged)
5821 {
5f5c8ee5
GM
5822 Lisp_Object tail, frame;
5823
5824 FOR_EACH_FRAME (tail, frame)
5825 {
5826 struct frame *f = XFRAME (frame);
5827
5828 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
5829 {
5830 clear_current_matrices (f);
5831 f->garbaged = 0;
5832 }
5833 }
5834
5835 frame_garbaged = 0;
5836 ++windows_or_buffers_changed;
5837 }
c6e89d6c 5838}
5f5c8ee5 5839
5f5c8ee5 5840
886bd6f2
GM
5841/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
5842 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 5843 mini-windows height has been changed. */
5f5c8ee5 5844
c6e89d6c
GM
5845static int
5846echo_area_display (update_frame_p)
5847 int update_frame_p;
5848{
5849 Lisp_Object mini_window;
5850 struct window *w;
5851 struct frame *f;
5852 int window_height_changed_p = 0;
886bd6f2 5853 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5854
886bd6f2 5855 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5856 w = XWINDOW (mini_window);
5857 f = XFRAME (WINDOW_FRAME (w));
5858
5859 /* Don't display if frame is invisible or not yet initialized. */
5860 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
5861 return 0;
5f5c8ee5 5862
d9e28aa0
RS
5863#if 0 /* inhibit_window_system is not a valid way of testing
5864 whether a window system is in use.
5865 This code prevents all echo area display
5866 when you run plain `emacs' on a tty. */
c6e89d6c
GM
5867 /* When Emacs starts, selected_frame may be a visible terminal
5868 frame, even if we run under a window system. If we let this
5869 through, a message would be displayed on the terminal. */
5870#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 5871 if (!inhibit_window_system && !FRAME_WINDOW_P (sf))
c6e89d6c
GM
5872 return 0;
5873#endif /* HAVE_WINDOW_SYSTEM */
d9e28aa0 5874#endif
c6e89d6c
GM
5875
5876 /* Redraw garbaged frames. */
5877 if (frame_garbaged)
5878 clear_garbaged_frames ();
5879
5880 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
5881 {
5882 echo_area_window = mini_window;
5883 window_height_changed_p = display_echo_area (w);
5f5c8ee5 5884 w->must_be_updated_p = 1;
c59c668a 5885
5f5c8ee5
GM
5886 if (update_frame_p)
5887 {
c59c668a
GM
5888 /* Not called from redisplay_internal. If we changed
5889 window configuration, we must redisplay thoroughly.
5890 Otherwise, we can do with updating what we displayed
5891 above. */
5892 if (window_height_changed_p)
5893 {
5894 ++windows_or_buffers_changed;
5895 ++update_mode_lines;
5896 redisplay_internal (0);
5897 }
5898 else if (FRAME_WINDOW_P (f))
5f5c8ee5
GM
5899 {
5900 update_single_window (w, 1);
5901 rif->flush_display (f);
5902 }
5903 else
5904 update_frame (f, 1, 1);
5905 }
5906 }
5907 else if (!EQ (mini_window, selected_window))
5908 windows_or_buffers_changed++;
c59c668a
GM
5909
5910 /* Last displayed message is now the current message. */
dd2eb166
GM
5911 echo_area_buffer[1] = echo_area_buffer[0];
5912
5f5c8ee5
GM
5913 /* Prevent redisplay optimization in redisplay_internal by resetting
5914 this_line_start_pos. This is done because the mini-buffer now
5915 displays the message instead of its buffer text. */
5916 if (EQ (mini_window, selected_window))
5917 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
5918
5919 return window_height_changed_p;
5f5c8ee5
GM
5920}
5921
5922
5923\f
5924/***********************************************************************
5925 Frame Titles
5926 ***********************************************************************/
5927
5928
5929#ifdef HAVE_WINDOW_SYSTEM
5930
5931/* A buffer for constructing frame titles in it; allocated from the
5932 heap in init_xdisp and resized as needed in store_frame_title_char. */
5933
5934static char *frame_title_buf;
5935
5936/* The buffer's end, and a current output position in it. */
5937
5938static char *frame_title_buf_end;
5939static char *frame_title_ptr;
5940
5941
5942/* Store a single character C for the frame title in frame_title_buf.
5943 Re-allocate frame_title_buf if necessary. */
5944
5945static void
5946store_frame_title_char (c)
5947 char c;
5948{
5949 /* If output position has reached the end of the allocated buffer,
5950 double the buffer's size. */
5951 if (frame_title_ptr == frame_title_buf_end)
5952 {
5953 int len = frame_title_ptr - frame_title_buf;
5954 int new_size = 2 * len * sizeof *frame_title_buf;
5955 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
5956 frame_title_buf_end = frame_title_buf + new_size;
5957 frame_title_ptr = frame_title_buf + len;
5958 }
5959
5960 *frame_title_ptr++ = c;
5961}
5962
5963
5964/* Store part of a frame title in frame_title_buf, beginning at
5965 frame_title_ptr. STR is the string to store. Do not copy more
5966 than PRECISION number of bytes from STR; PRECISION <= 0 means copy
5967 the whole string. Pad with spaces until FIELD_WIDTH number of
5968 characters have been copied; FIELD_WIDTH <= 0 means don't pad.
5969 Called from display_mode_element when it is used to build a frame
5970 title. */
5971
5972static int
5973store_frame_title (str, field_width, precision)
5974 unsigned char *str;
5975 int field_width, precision;
5976{
5977 int n = 0;
5978
5979 /* Copy at most PRECISION chars from STR. */
5980 while ((precision <= 0 || n < precision)
5981 && *str)
5982 {
5983 store_frame_title_char (*str++);
5984 ++n;
5985 }
5986
5987 /* Fill up with spaces until FIELD_WIDTH reached. */
5988 while (field_width > 0
5989 && n < field_width)
5990 {
5991 store_frame_title_char (' ');
5992 ++n;
5993 }
5994
5995 return n;
5996}
5997
5998
5999/* Set the title of FRAME, if it has changed. The title format is
6000 Vicon_title_format if FRAME is iconified, otherwise it is
6001 frame_title_format. */
6002
6003static void
6004x_consider_frame_title (frame)
6005 Lisp_Object frame;
6006{
6007 struct frame *f = XFRAME (frame);
6008
6009 if (FRAME_WINDOW_P (f)
6010 || FRAME_MINIBUF_ONLY_P (f)
6011 || f->explicit_name)
6012 {
6013 /* Do we have more than one visible frame on this X display? */
6014 Lisp_Object tail;
6015 Lisp_Object fmt;
6016 struct buffer *obuf;
6017 int len;
6018 struct it it;
6019
9472f927 6020 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 6021 {
9472f927 6022 struct frame *tf = XFRAME (XCAR (tail));
5f5c8ee5
GM
6023
6024 if (tf != f
6025 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
6026 && !FRAME_MINIBUF_ONLY_P (tf)
6027 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
6028 break;
6029 }
6030
6031 /* Set global variable indicating that multiple frames exist. */
6032 multiple_frames = CONSP (tail);
6033
6034 /* Switch to the buffer of selected window of the frame. Set up
6035 frame_title_ptr so that display_mode_element will output into it;
6036 then display the title. */
6037 obuf = current_buffer;
6038 Fset_buffer (XWINDOW (f->selected_window)->buffer);
6039 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
6040 frame_title_ptr = frame_title_buf;
6041 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
6042 NULL, DEFAULT_FACE_ID);
6043 len = display_mode_element (&it, 0, -1, -1, fmt);
6044 frame_title_ptr = NULL;
6045 set_buffer_internal (obuf);
6046
6047 /* Set the title only if it's changed. This avoids consing in
6048 the common case where it hasn't. (If it turns out that we've
6049 already wasted too much time by walking through the list with
6050 display_mode_element, then we might need to optimize at a
6051 higher level than this.) */
6052 if (! STRINGP (f->name)
6053 || STRING_BYTES (XSTRING (f->name)) != len
6054 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
6055 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
6056 }
6057}
6058
6059#else /* not HAVE_WINDOW_SYSTEM */
6060
6061#define frame_title_ptr ((char *)0)
6062#define store_frame_title(str, mincol, maxcol) 0
6063
6064#endif /* not HAVE_WINDOW_SYSTEM */
6065
6066
6067
6068\f
6069/***********************************************************************
6070 Menu Bars
6071 ***********************************************************************/
6072
6073
6074/* Prepare for redisplay by updating menu-bar item lists when
6075 appropriate. This can call eval. */
6076
6077void
6078prepare_menu_bars ()
6079{
6080 int all_windows;
6081 struct gcpro gcpro1, gcpro2;
6082 struct frame *f;
6083 struct frame *tooltip_frame;
6084
6085#ifdef HAVE_X_WINDOWS
6086 tooltip_frame = tip_frame;
6087#else
6088 tooltip_frame = NULL;
6089#endif
6090
6091 /* Update all frame titles based on their buffer names, etc. We do
6092 this before the menu bars so that the buffer-menu will show the
6093 up-to-date frame titles. */
6094#ifdef HAVE_WINDOW_SYSTEM
6095 if (windows_or_buffers_changed || update_mode_lines)
6096 {
6097 Lisp_Object tail, frame;
6098
6099 FOR_EACH_FRAME (tail, frame)
6100 {
6101 f = XFRAME (frame);
6102 if (f != tooltip_frame
6103 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
6104 x_consider_frame_title (frame);
6105 }
6106 }
6107#endif /* HAVE_WINDOW_SYSTEM */
6108
6109 /* Update the menu bar item lists, if appropriate. This has to be
6110 done before any actual redisplay or generation of display lines. */
6111 all_windows = (update_mode_lines
6112 || buffer_shared > 1
6113 || windows_or_buffers_changed);
6114 if (all_windows)
6115 {
6116 Lisp_Object tail, frame;
6117 int count = specpdl_ptr - specpdl;
6118
6119 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6120
6121 FOR_EACH_FRAME (tail, frame)
6122 {
6123 f = XFRAME (frame);
6124
6125 /* Ignore tooltip frame. */
6126 if (f == tooltip_frame)
6127 continue;
6128
6129 /* If a window on this frame changed size, report that to
6130 the user and clear the size-change flag. */
6131 if (FRAME_WINDOW_SIZES_CHANGED (f))
6132 {
6133 Lisp_Object functions;
6134
6135 /* Clear flag first in case we get an error below. */
6136 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
6137 functions = Vwindow_size_change_functions;
6138 GCPRO2 (tail, functions);
6139
6140 while (CONSP (functions))
6141 {
6142 call1 (XCAR (functions), frame);
6143 functions = XCDR (functions);
6144 }
6145 UNGCPRO;
6146 }
6147
6148 GCPRO1 (tail);
6149 update_menu_bar (f, 0);
6150#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 6151 update_tool_bar (f, 0);
5f5c8ee5
GM
6152#endif
6153 UNGCPRO;
6154 }
6155
6156 unbind_to (count, Qnil);
6157 }
6158 else
6159 {
886bd6f2
GM
6160 struct frame *sf = SELECTED_FRAME ();
6161 update_menu_bar (sf, 1);
5f5c8ee5 6162#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 6163 update_tool_bar (sf, 1);
5f5c8ee5
GM
6164#endif
6165 }
6166
6167 /* Motif needs this. See comment in xmenu.c. Turn it off when
6168 pending_menu_activation is not defined. */
6169#ifdef USE_X_TOOLKIT
6170 pending_menu_activation = 0;
6171#endif
6172}
6173
6174
6175/* Update the menu bar item list for frame F. This has to be done
6176 before we start to fill in any display lines, because it can call
6177 eval.
6178
6179 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
6180
6181static void
6182update_menu_bar (f, save_match_data)
6183 struct frame *f;
6184 int save_match_data;
6185{
6186 Lisp_Object window;
6187 register struct window *w;
6188
6189 window = FRAME_SELECTED_WINDOW (f);
6190 w = XWINDOW (window);
6191
6192 if (update_mode_lines)
6193 w->update_mode_line = Qt;
6194
6195 if (FRAME_WINDOW_P (f)
6196 ?
6197#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6198 FRAME_EXTERNAL_MENU_BAR (f)
6199#else
6200 FRAME_MENU_BAR_LINES (f) > 0
6201#endif
6202 : FRAME_MENU_BAR_LINES (f) > 0)
6203 {
6204 /* If the user has switched buffers or windows, we need to
6205 recompute to reflect the new bindings. But we'll
6206 recompute when update_mode_lines is set too; that means
6207 that people can use force-mode-line-update to request
6208 that the menu bar be recomputed. The adverse effect on
6209 the rest of the redisplay algorithm is about the same as
6210 windows_or_buffers_changed anyway. */
6211 if (windows_or_buffers_changed
6212 || !NILP (w->update_mode_line)
6213 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6214 < BUF_MODIFF (XBUFFER (w->buffer)))
6215 != !NILP (w->last_had_star))
6216 || ((!NILP (Vtransient_mark_mode)
6217 && !NILP (XBUFFER (w->buffer)->mark_active))
6218 != !NILP (w->region_showing)))
6219 {
6220 struct buffer *prev = current_buffer;
6221 int count = specpdl_ptr - specpdl;
6222
6223 set_buffer_internal_1 (XBUFFER (w->buffer));
6224 if (save_match_data)
6225 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6226 if (NILP (Voverriding_local_map_menu_flag))
6227 {
6228 specbind (Qoverriding_terminal_local_map, Qnil);
6229 specbind (Qoverriding_local_map, Qnil);
6230 }
6231
6232 /* Run the Lucid hook. */
6233 call1 (Vrun_hooks, Qactivate_menubar_hook);
6234
6235 /* If it has changed current-menubar from previous value,
6236 really recompute the menu-bar from the value. */
6237 if (! NILP (Vlucid_menu_bar_dirty_flag))
6238 call0 (Qrecompute_lucid_menubar);
6239
6240 safe_run_hooks (Qmenu_bar_update_hook);
6241 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
6242
6243 /* Redisplay the menu bar in case we changed it. */
6244#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6245 if (FRAME_WINDOW_P (f))
6246 set_frame_menubar (f, 0, 0);
6247 else
6248 /* On a terminal screen, the menu bar is an ordinary screen
6249 line, and this makes it get updated. */
6250 w->update_mode_line = Qt;
6251#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6252 /* In the non-toolkit version, the menu bar is an ordinary screen
6253 line, and this makes it get updated. */
6254 w->update_mode_line = Qt;
6255#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6256
6257 unbind_to (count, Qnil);
6258 set_buffer_internal_1 (prev);
6259 }
6260 }
6261}
6262
6263
6264\f
6265/***********************************************************************
e037b9ec 6266 Tool-bars
5f5c8ee5
GM
6267 ***********************************************************************/
6268
6269#ifdef HAVE_WINDOW_SYSTEM
6270
e037b9ec 6271/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
6272 before we start to fill in any display lines. Called from
6273 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
6274 and restore it here. */
6275
6276static void
e037b9ec 6277update_tool_bar (f, save_match_data)
5f5c8ee5
GM
6278 struct frame *f;
6279 int save_match_data;
6280{
e037b9ec
GM
6281 if (WINDOWP (f->tool_bar_window)
6282 && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
5f5c8ee5
GM
6283 {
6284 Lisp_Object window;
6285 struct window *w;
6286
6287 window = FRAME_SELECTED_WINDOW (f);
6288 w = XWINDOW (window);
6289
6290 /* If the user has switched buffers or windows, we need to
6291 recompute to reflect the new bindings. But we'll
6292 recompute when update_mode_lines is set too; that means
6293 that people can use force-mode-line-update to request
6294 that the menu bar be recomputed. The adverse effect on
6295 the rest of the redisplay algorithm is about the same as
6296 windows_or_buffers_changed anyway. */
6297 if (windows_or_buffers_changed
6298 || !NILP (w->update_mode_line)
6299 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6300 < BUF_MODIFF (XBUFFER (w->buffer)))
6301 != !NILP (w->last_had_star))
6302 || ((!NILP (Vtransient_mark_mode)
6303 && !NILP (XBUFFER (w->buffer)->mark_active))
6304 != !NILP (w->region_showing)))
6305 {
6306 struct buffer *prev = current_buffer;
6307 int count = specpdl_ptr - specpdl;
a2889657 6308
5f5c8ee5
GM
6309 /* Set current_buffer to the buffer of the selected
6310 window of the frame, so that we get the right local
6311 keymaps. */
6312 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 6313
5f5c8ee5
GM
6314 /* Save match data, if we must. */
6315 if (save_match_data)
6316 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6317
6318 /* Make sure that we don't accidentally use bogus keymaps. */
6319 if (NILP (Voverriding_local_map_menu_flag))
6320 {
6321 specbind (Qoverriding_terminal_local_map, Qnil);
6322 specbind (Qoverriding_local_map, Qnil);
1f40cad2 6323 }
1f40cad2 6324
e037b9ec
GM
6325 /* Build desired tool-bar items from keymaps. */
6326 f->desired_tool_bar_items
6327 = tool_bar_items (f->desired_tool_bar_items,
6328 &f->n_desired_tool_bar_items);
5f5c8ee5 6329
e037b9ec 6330 /* Redisplay the tool-bar in case we changed it. */
5f5c8ee5
GM
6331 w->update_mode_line = Qt;
6332
6333 unbind_to (count, Qnil);
6334 set_buffer_internal_1 (prev);
81d478f3 6335 }
a2889657
JB
6336 }
6337}
6338
6c4429a5 6339
e037b9ec
GM
6340/* Set F->desired_tool_bar_string to a Lisp string representing frame
6341 F's desired tool-bar contents. F->desired_tool_bar_items must have
5f5c8ee5
GM
6342 been set up previously by calling prepare_menu_bars. */
6343
a2889657 6344static void
e037b9ec 6345build_desired_tool_bar_string (f)
5f5c8ee5 6346 struct frame *f;
a2889657 6347{
5f5c8ee5
GM
6348 int i, size, size_needed, string_idx;
6349 struct gcpro gcpro1, gcpro2, gcpro3;
6350 Lisp_Object image, plist, props;
a2889657 6351
5f5c8ee5
GM
6352 image = plist = props = Qnil;
6353 GCPRO3 (image, plist, props);
a2889657 6354
e037b9ec 6355 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5
GM
6356 Otherwise, make a new string. */
6357
6358 /* The size of the string we might be able to reuse. */
e037b9ec
GM
6359 size = (STRINGP (f->desired_tool_bar_string)
6360 ? XSTRING (f->desired_tool_bar_string)->size
5f5c8ee5
GM
6361 : 0);
6362
6363 /* Each image in the string we build is preceded by a space,
6364 and there is a space at the end. */
e037b9ec 6365 size_needed = f->n_desired_tool_bar_items + 1;
5f5c8ee5 6366
e037b9ec 6367 /* Reuse f->desired_tool_bar_string, if possible. */
5f5c8ee5 6368 if (size < size_needed)
e037b9ec 6369 f->desired_tool_bar_string = Fmake_string (make_number (size_needed), ' ');
5f5c8ee5
GM
6370 else
6371 {
6372 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
6373 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 6374 props, f->desired_tool_bar_string);
5f5c8ee5 6375 }
a2889657 6376
5f5c8ee5 6377 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
6378 put a `menu_item' property on tool-bar items with a value that
6379 is the index of the item in F's tool-bar item vector. */
5f5c8ee5 6380 for (i = 0, string_idx = 0;
e037b9ec 6381 i < f->n_desired_tool_bar_items;
5f5c8ee5 6382 ++i, string_idx += 1)
a2889657 6383 {
5f5c8ee5 6384#define PROP(IDX) \
e037b9ec
GM
6385 (XVECTOR (f->desired_tool_bar_items) \
6386 ->contents[i * TOOL_BAR_ITEM_NSLOTS + (IDX)])
5f5c8ee5 6387
e037b9ec
GM
6388 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
6389 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
5f5c8ee5
GM
6390 int margin, relief;
6391 extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
6392 extern Lisp_Object Qlaplace;
6393
6394 /* If image is a vector, choose the image according to the
6395 button state. */
e037b9ec 6396 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
6397 if (VECTORP (image))
6398 {
e037b9ec 6399 enum tool_bar_item_image idx;
5f5c8ee5
GM
6400
6401 if (enabled_p)
6402 idx = (selected_p
e037b9ec
GM
6403 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6404 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
6405 else
6406 idx = (selected_p
e037b9ec
GM
6407 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6408 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
5f5c8ee5
GM
6409
6410 xassert (XVECTOR (image)->size >= idx);
6411 image = XVECTOR (image)->contents[idx];
6412 }
6413
6414 /* Ignore invalid image specifications. */
6415 if (!valid_image_p (image))
6416 continue;
6417
e037b9ec 6418 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
6419 plist = Fcopy_sequence (XCDR (image));
6420
6421 /* Compute margin and relief to draw. */
e037b9ec
GM
6422 relief = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
6423 margin = relief + max (0, tool_bar_button_margin);
5f5c8ee5 6424
e037b9ec 6425 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
6426 {
6427 /* Add a `:relief' property to the image spec if the item is
6428 selected. */
6429 if (selected_p)
6430 {
6431 plist = Fplist_put (plist, QCrelief, make_number (-relief));
6432 margin -= relief;
6433 }
6434 }
6435 else
6436 {
6437 /* If image is selected, display it pressed, i.e. with a
6438 negative relief. If it's not selected, display it with a
6439 raised relief. */
6440 plist = Fplist_put (plist, QCrelief,
6441 (selected_p
6442 ? make_number (-relief)
6443 : make_number (relief)));
6444 margin -= relief;
6445 }
6446
6447 /* Put a margin around the image. */
6448 if (margin)
6449 plist = Fplist_put (plist, QCmargin, make_number (margin));
6450
6451 /* If button is not enabled, make the image appear disabled by
6452 applying an appropriate algorithm to it. */
6453 if (!enabled_p)
6454 plist = Fplist_put (plist, QCalgorithm, Qlaplace);
6455
6456 /* Put a `display' text property on the string for the image to
6457 display. Put a `menu-item' property on the string that gives
e037b9ec 6458 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
6459 vector. */
6460 image = Fcons (Qimage, plist);
6461 props = list4 (Qdisplay, image,
e037b9ec 6462 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)),
5f5c8ee5
GM
6463 Fadd_text_properties (make_number (string_idx),
6464 make_number (string_idx + 1),
e037b9ec 6465 props, f->desired_tool_bar_string);
5f5c8ee5 6466#undef PROP
a2889657
JB
6467 }
6468
5f5c8ee5
GM
6469 UNGCPRO;
6470}
6471
6472
e037b9ec 6473/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
6474
6475static void
e037b9ec 6476display_tool_bar_line (it)
5f5c8ee5
GM
6477 struct it *it;
6478{
6479 struct glyph_row *row = it->glyph_row;
6480 int max_x = it->last_visible_x;
6481 struct glyph *last;
6482
6483 prepare_desired_row (row);
6484 row->y = it->current_y;
6485
6486 while (it->current_x < max_x)
a2889657 6487 {
5f5c8ee5 6488 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 6489
5f5c8ee5
GM
6490 /* Get the next display element. */
6491 if (!get_next_display_element (it))
6492 break;
73af359d 6493
5f5c8ee5
GM
6494 /* Produce glyphs. */
6495 x_before = it->current_x;
6496 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
6497 PRODUCE_GLYPHS (it);
daa37602 6498
5f5c8ee5
GM
6499 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
6500 i = 0;
6501 x = x_before;
6502 while (i < nglyphs)
6503 {
6504 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
6505
6506 if (x + glyph->pixel_width > max_x)
6507 {
6508 /* Glyph doesn't fit on line. */
6509 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
6510 it->current_x = x;
6511 goto out;
6512 }
daa37602 6513
5f5c8ee5
GM
6514 ++it->hpos;
6515 x += glyph->pixel_width;
6516 ++i;
6517 }
6518
6519 /* Stop at line ends. */
6520 if (ITERATOR_AT_END_OF_LINE_P (it))
6521 break;
6522
6523 set_iterator_to_next (it);
a2889657 6524 }
a2889657 6525
5f5c8ee5 6526 out:;
a2889657 6527
5f5c8ee5
GM
6528 row->displays_text_p = row->used[TEXT_AREA] != 0;
6529 extend_face_to_end_of_line (it);
6530 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
6531 last->right_box_line_p = 1;
6532 compute_line_metrics (it);
6533
e037b9ec 6534 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
6535 if (!row->displays_text_p)
6536 {
312246d1
GM
6537 row->height = row->phys_height = it->last_visible_y - row->y;
6538 row->ascent = row->phys_ascent = 0;
5f5c8ee5
GM
6539 }
6540
6541 row->full_width_p = 1;
6542 row->continued_p = 0;
6543 row->truncated_on_left_p = 0;
6544 row->truncated_on_right_p = 0;
6545
6546 it->current_x = it->hpos = 0;
6547 it->current_y += row->height;
6548 ++it->vpos;
6549 ++it->glyph_row;
a2889657 6550}
96a410bc 6551
5f5c8ee5 6552
e037b9ec 6553/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 6554 items of frame F visible. */
96a410bc 6555
d39b6696 6556static int
e037b9ec 6557tool_bar_lines_needed (f)
5f5c8ee5 6558 struct frame *f;
d39b6696 6559{
e037b9ec 6560 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5
GM
6561 struct it it;
6562
e037b9ec
GM
6563 /* Initialize an iterator for iteration over
6564 F->desired_tool_bar_string in the tool-bar window of frame F. */
6565 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
6566 it.first_visible_x = 0;
6567 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
e037b9ec 6568 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
6569
6570 while (!ITERATOR_AT_END_P (&it))
6571 {
6572 it.glyph_row = w->desired_matrix->rows;
6573 clear_glyph_row (it.glyph_row);
e037b9ec 6574 display_tool_bar_line (&it);
5f5c8ee5
GM
6575 }
6576
6577 return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
d39b6696 6578}
96a410bc 6579
5f5c8ee5 6580
e037b9ec 6581/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
6582 height should be changed. */
6583
6584static int
e037b9ec 6585redisplay_tool_bar (f)
5f5c8ee5 6586 struct frame *f;
96a410bc 6587{
5f5c8ee5
GM
6588 struct window *w;
6589 struct it it;
6590 struct glyph_row *row;
6591 int change_height_p = 0;
6592
e037b9ec
GM
6593 /* If frame hasn't a tool-bar window or if it is zero-height, don't
6594 do anything. This means you must start with tool-bar-lines
5f5c8ee5 6595 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
6596 can turn off tool-bars by specifying tool-bar-lines zero. */
6597 if (!WINDOWP (f->tool_bar_window)
6598 || (w = XWINDOW (f->tool_bar_window),
5f5c8ee5
GM
6599 XFASTINT (w->height) == 0))
6600 return 0;
96a410bc 6601
e037b9ec
GM
6602 /* Set up an iterator for the tool-bar window. */
6603 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
6604 it.first_visible_x = 0;
6605 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
6606 row = it.glyph_row;
3450d04c 6607
e037b9ec
GM
6608 /* Build a string that represents the contents of the tool-bar. */
6609 build_desired_tool_bar_string (f);
6610 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 6611
e037b9ec 6612 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 6613 while (it.current_y < it.last_visible_y)
e037b9ec 6614 display_tool_bar_line (&it);
3450d04c 6615
e037b9ec 6616 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
6617 window, so don't do it. */
6618 w->desired_matrix->no_scrolling_p = 1;
6619 w->must_be_updated_p = 1;
3450d04c 6620
e037b9ec 6621 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
6622 {
6623 int nlines;
6624
6625 /* If there are blank lines at the end, except for a partially
6626 visible blank line at the end that is smaller than
e037b9ec 6627 CANON_Y_UNIT, change the tool-bar's height. */
5f5c8ee5
GM
6628 row = it.glyph_row - 1;
6629 if (!row->displays_text_p
6630 && row->height >= CANON_Y_UNIT (f))
6631 change_height_p = 1;
6632
e037b9ec
GM
6633 /* If row displays tool-bar items, but is partially visible,
6634 change the tool-bar's height. */
5f5c8ee5
GM
6635 if (row->displays_text_p
6636 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
6637 change_height_p = 1;
6638
e037b9ec 6639 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
6640 frame parameter. */
6641 if (change_height_p
e037b9ec 6642 && (nlines = tool_bar_lines_needed (f),
5f5c8ee5
GM
6643 nlines != XFASTINT (w->height)))
6644 {
e037b9ec 6645 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5
GM
6646 Lisp_Object frame;
6647
6648 XSETFRAME (frame, f);
6649 clear_glyph_matrix (w->desired_matrix);
6650 Fmodify_frame_parameters (frame,
e037b9ec 6651 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
6652 make_number (nlines)),
6653 Qnil));
6654 fonts_changed_p = 1;
6655 }
6656 }
3450d04c 6657
5f5c8ee5 6658 return change_height_p;
96a410bc 6659}
90adcf20 6660
5f5c8ee5 6661
e037b9ec
GM
6662/* Get information about the tool-bar item which is displayed in GLYPH
6663 on frame F. Return in *PROP_IDX the index where tool-bar item
6664 properties start in F->current_tool_bar_items. Value is zero if
6665 GLYPH doesn't display a tool-bar item. */
5f5c8ee5
GM
6666
6667int
e037b9ec 6668tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
6669 struct frame *f;
6670 struct glyph *glyph;
6671 int *prop_idx;
90adcf20 6672{
5f5c8ee5
GM
6673 Lisp_Object prop;
6674 int success_p;
6675
6676 /* Get the text property `menu-item' at pos. The value of that
6677 property is the start index of this item's properties in
e037b9ec 6678 F->current_tool_bar_items. */
5f5c8ee5 6679 prop = Fget_text_property (make_number (glyph->charpos),
e037b9ec 6680 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
6681 if (INTEGERP (prop))
6682 {
6683 *prop_idx = XINT (prop);
6684 success_p = 1;
6685 }
6686 else
6687 success_p = 0;
90adcf20 6688
5f5c8ee5
GM
6689 return success_p;
6690}
6691
6692#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 6693
feb0c42f 6694
5f5c8ee5
GM
6695\f
6696/************************************************************************
6697 Horizontal scrolling
6698 ************************************************************************/
feb0c42f 6699
5f5c8ee5
GM
6700static int hscroll_window_tree P_ ((Lisp_Object));
6701static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 6702
5f5c8ee5
GM
6703/* For all leaf windows in the window tree rooted at WINDOW, set their
6704 hscroll value so that PT is (i) visible in the window, and (ii) so
6705 that it is not within a certain margin at the window's left and
6706 right border. Value is non-zero if any window's hscroll has been
6707 changed. */
6708
6709static int
6710hscroll_window_tree (window)
6711 Lisp_Object window;
6712{
6713 int hscrolled_p = 0;
6714
6715 while (WINDOWP (window))
90adcf20 6716 {
5f5c8ee5
GM
6717 struct window *w = XWINDOW (window);
6718
6719 if (WINDOWP (w->hchild))
6720 hscrolled_p |= hscroll_window_tree (w->hchild);
6721 else if (WINDOWP (w->vchild))
6722 hscrolled_p |= hscroll_window_tree (w->vchild);
6723 else if (w->cursor.vpos >= 0)
6724 {
6725 int hscroll_margin, text_area_x, text_area_y;
6726 int text_area_width, text_area_height;
92a90e89
GM
6727 struct glyph_row *current_cursor_row
6728 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
6729 struct glyph_row *desired_cursor_row
6730 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
6731 struct glyph_row *cursor_row
6732 = (desired_cursor_row->enabled_p
6733 ? desired_cursor_row
6734 : current_cursor_row);
a2725ab2 6735
5f5c8ee5
GM
6736 window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
6737 &text_area_width, &text_area_height);
90adcf20 6738
5f5c8ee5
GM
6739 /* Scroll when cursor is inside this scroll margin. */
6740 hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
6741
6742 if ((XFASTINT (w->hscroll)
6743 && w->cursor.x < hscroll_margin)
92a90e89
GM
6744 || (cursor_row->enabled_p
6745 && cursor_row->truncated_on_right_p
5f5c8ee5 6746 && (w->cursor.x > text_area_width - hscroll_margin)))
08b610e4 6747 {
5f5c8ee5
GM
6748 struct it it;
6749 int hscroll;
6750 struct buffer *saved_current_buffer;
6751 int pt;
6752
6753 /* Find point in a display of infinite width. */
6754 saved_current_buffer = current_buffer;
6755 current_buffer = XBUFFER (w->buffer);
6756
6757 if (w == XWINDOW (selected_window))
6758 pt = BUF_PT (current_buffer);
6759 else
08b610e4 6760 {
5f5c8ee5
GM
6761 pt = marker_position (w->pointm);
6762 pt = max (BEGV, pt);
6763 pt = min (ZV, pt);
6764 }
6765
6766 /* Move iterator to pt starting at cursor_row->start in
6767 a line with infinite width. */
6768 init_to_row_start (&it, w, cursor_row);
6769 it.last_visible_x = INFINITY;
6770 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
6771 current_buffer = saved_current_buffer;
6772
6773 /* Center cursor in window. */
6774 hscroll = (max (0, it.current_x - text_area_width / 2)
6775 / CANON_X_UNIT (it.f));
6776
6777 /* Don't call Fset_window_hscroll if value hasn't
6778 changed because it will prevent redisplay
6779 optimizations. */
6780 if (XFASTINT (w->hscroll) != hscroll)
6781 {
6782 Fset_window_hscroll (window, make_number (hscroll));
6783 hscrolled_p = 1;
08b610e4 6784 }
08b610e4 6785 }
08b610e4 6786 }
a2725ab2 6787
5f5c8ee5 6788 window = w->next;
90adcf20 6789 }
cd6dfed6 6790
5f5c8ee5
GM
6791 /* Value is non-zero if hscroll of any leaf window has been changed. */
6792 return hscrolled_p;
6793}
6794
6795
6796/* Set hscroll so that cursor is visible and not inside horizontal
6797 scroll margins for all windows in the tree rooted at WINDOW. See
6798 also hscroll_window_tree above. Value is non-zero if any window's
6799 hscroll has been changed. If it has, desired matrices on the frame
6800 of WINDOW are cleared. */
6801
6802static int
6803hscroll_windows (window)
6804 Lisp_Object window;
6805{
6806 int hscrolled_p = hscroll_window_tree (window);
6807 if (hscrolled_p)
6808 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
6809 return hscrolled_p;
90adcf20 6810}
5f5c8ee5
GM
6811
6812
90adcf20 6813\f
5f5c8ee5
GM
6814/************************************************************************
6815 Redisplay
6816 ************************************************************************/
6817
6818/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
6819 to a non-zero value. This is sometimes handy to have in a debugger
6820 session. */
6821
6822#if GLYPH_DEBUG
a2889657 6823
5f5c8ee5
GM
6824/* First and last unchanged row for try_window_id. */
6825
6826int debug_first_unchanged_at_end_vpos;
6827int debug_last_unchanged_at_beg_vpos;
6828
6829/* Delta vpos and y. */
6830
6831int debug_dvpos, debug_dy;
6832
6833/* Delta in characters and bytes for try_window_id. */
6834
6835int debug_delta, debug_delta_bytes;
6836
6837/* Values of window_end_pos and window_end_vpos at the end of
6838 try_window_id. */
6839
6840int debug_end_pos, debug_end_vpos;
6841
6842/* Append a string to W->desired_matrix->method. FMT is a printf
6843 format string. A1...A9 are a supplement for a variable-length
6844 argument list. If trace_redisplay_p is non-zero also printf the
6845 resulting string to stderr. */
6846
6847static void
6848debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
6849 struct window *w;
6850 char *fmt;
6851 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
6852{
6853 char buffer[512];
6854 char *method = w->desired_matrix->method;
6855 int len = strlen (method);
6856 int size = sizeof w->desired_matrix->method;
6857 int remaining = size - len - 1;
6858
6859 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
6860 if (len && remaining)
6861 {
6862 method[len] = '|';
6863 --remaining, ++len;
6864 }
6865
6866 strncpy (method + len, buffer, remaining);
6867
6868 if (trace_redisplay_p)
6869 fprintf (stderr, "%p (%s): %s\n",
6870 w,
6871 ((BUFFERP (w->buffer)
6872 && STRINGP (XBUFFER (w->buffer)->name))
6873 ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
6874 : "no buffer"),
6875 buffer);
6876}
a2889657 6877
5f5c8ee5 6878#endif /* GLYPH_DEBUG */
90adcf20 6879
a2889657 6880
5f5c8ee5
GM
6881/* This counter is used to clear the face cache every once in a while
6882 in redisplay_internal. It is incremented for each redisplay.
6883 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
6884 cleared. */
0d231165 6885
5f5c8ee5 6886#define CLEAR_FACE_CACHE_COUNT 10000
463f6b91
RS
6887static int clear_face_cache_count;
6888
20de20dc 6889/* Record the previous terminal frame we displayed. */
5f5c8ee5
GM
6890
6891static struct frame *previous_terminal_frame;
6892
6893/* Non-zero while redisplay_internal is in progress. */
6894
6895int redisplaying_p;
6896
6897
6898/* Value is non-zero if all changes in window W, which displays
6899 current_buffer, are in the text between START and END. START is a
6900 buffer position, END is given as a distance from Z. Used in
6901 redisplay_internal for display optimization. */
6902
6903static INLINE int
6904text_outside_line_unchanged_p (w, start, end)
6905 struct window *w;
6906 int start, end;
6907{
6908 int unchanged_p = 1;
6909
6910 /* If text or overlays have changed, see where. */
6911 if (XFASTINT (w->last_modified) < MODIFF
6912 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
6913 {
6914 /* Gap in the line? */
6915 if (GPT < start || Z - GPT < end)
6916 unchanged_p = 0;
6917
6918 /* Changes start in front of the line, or end after it? */
6919 if (unchanged_p
9142dd5b
GM
6920 && (BEG_UNCHANGED < start - 1
6921 || END_UNCHANGED < end))
5f5c8ee5
GM
6922 unchanged_p = 0;
6923
6924 /* If selective display, can't optimize if changes start at the
6925 beginning of the line. */
6926 if (unchanged_p
6927 && INTEGERP (current_buffer->selective_display)
6928 && XINT (current_buffer->selective_display) > 0
9142dd5b 6929 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5
GM
6930 unchanged_p = 0;
6931 }
6932
6933 return unchanged_p;
6934}
6935
6936
6937/* Do a frame update, taking possible shortcuts into account. This is
6938 the main external entry point for redisplay.
6939
6940 If the last redisplay displayed an echo area message and that message
6941 is no longer requested, we clear the echo area or bring back the
6942 mini-buffer if that is in use. */
20de20dc 6943
a2889657
JB
6944void
6945redisplay ()
e9874cee
RS
6946{
6947 redisplay_internal (0);
6948}
6949
5f5c8ee5 6950
9142dd5b
GM
6951/* Reconsider the setting of B->clip_changed which is displayed
6952 in window W. */
6953
6954static INLINE void
6955reconsider_clip_changes (w, b)
6956 struct window *w;
6957 struct buffer *b;
6958{
6959 if (b->prevent_redisplay_optimizations_p)
6960 b->clip_changed = 1;
6961 else if (b->clip_changed
6962 && !NILP (w->window_end_valid)
6963 && w->current_matrix->buffer == b
6964 && w->current_matrix->zv == BUF_ZV (b)
6965 && w->current_matrix->begv == BUF_BEGV (b))
6966 b->clip_changed = 0;
6967}
6968
6969
5f5c8ee5
GM
6970/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
6971 response to any user action; therefore, we should preserve the echo
6972 area. (Actually, our caller does that job.) Perhaps in the future
6973 avoid recentering windows if it is not necessary; currently that
6974 causes some problems. */
e9874cee
RS
6975
6976static void
6977redisplay_internal (preserve_echo_area)
6978 int preserve_echo_area;
a2889657 6979{
5f5c8ee5
GM
6980 struct window *w = XWINDOW (selected_window);
6981 struct frame *f = XFRAME (w->frame);
6982 int pause;
a2889657 6983 int must_finish = 0;
5f5c8ee5 6984 struct text_pos tlbufpos, tlendpos;
89819bdd 6985 int number_of_visible_frames;
28514cd9 6986 int count;
886bd6f2 6987 struct frame *sf = SELECTED_FRAME ();
a2889657 6988
5f5c8ee5
GM
6989 /* Non-zero means redisplay has to consider all windows on all
6990 frames. Zero means, only selected_window is considered. */
6991 int consider_all_windows_p;
6992
6993 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
6994
6995 /* No redisplay if running in batch mode or frame is not yet fully
6996 initialized, or redisplay is explicitly turned off by setting
6997 Vinhibit_redisplay. */
6998 if (noninteractive
6999 || !NILP (Vinhibit_redisplay)
7000 || !f->glyphs_initialized_p)
a2889657
JB
7001 return;
7002
5f5c8ee5
GM
7003 /* The flag redisplay_performed_directly_p is set by
7004 direct_output_for_insert when it already did the whole screen
7005 update necessary. */
7006 if (redisplay_performed_directly_p)
7007 {
7008 redisplay_performed_directly_p = 0;
7009 if (!hscroll_windows (selected_window))
7010 return;
7011 }
7012
15f0cf78
RS
7013#ifdef USE_X_TOOLKIT
7014 if (popup_activated ())
7015 return;
7016#endif
7017
28514cd9 7018 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 7019 if (redisplaying_p)
735c094c
KH
7020 return;
7021
28514cd9
GM
7022 /* Record a function that resets redisplaying_p to its old value
7023 when we leave this function. */
7024 count = specpdl_ptr - specpdl;
7025 record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
7026 ++redisplaying_p;
7027
8b32d885
RS
7028 retry:
7029
9142dd5b
GM
7030 reconsider_clip_changes (w, current_buffer);
7031
5f5c8ee5
GM
7032 /* If new fonts have been loaded that make a glyph matrix adjustment
7033 necessary, do it. */
7034 if (fonts_changed_p)
7035 {
7036 adjust_glyphs (NULL);
7037 ++windows_or_buffers_changed;
7038 fonts_changed_p = 0;
7039 }
7040
886bd6f2
GM
7041 if (! FRAME_WINDOW_P (sf)
7042 && previous_terminal_frame != sf)
20de20dc 7043 {
5f5c8ee5
GM
7044 /* Since frames on an ASCII terminal share the same display
7045 area, displaying a different frame means redisplay the whole
7046 thing. */
20de20dc 7047 windows_or_buffers_changed++;
886bd6f2
GM
7048 SET_FRAME_GARBAGED (sf);
7049 XSETFRAME (Vterminal_frame, sf);
20de20dc 7050 }
886bd6f2 7051 previous_terminal_frame = sf;
20de20dc 7052
5f5c8ee5
GM
7053 /* Set the visible flags for all frames. Do this before checking
7054 for resized or garbaged frames; they want to know if their frames
7055 are visible. See the comment in frame.h for
7056 FRAME_SAMPLE_VISIBILITY. */
d724d989 7057 {
35f56f96 7058 Lisp_Object tail, frame;
d724d989 7059
89819bdd
RS
7060 number_of_visible_frames = 0;
7061
35f56f96 7062 FOR_EACH_FRAME (tail, frame)
f82aff7c 7063 {
5f5c8ee5
GM
7064 struct frame *f = XFRAME (frame);
7065
7066 FRAME_SAMPLE_VISIBILITY (f);
7067 if (FRAME_VISIBLE_P (f))
7068 ++number_of_visible_frames;
7069 clear_desired_matrices (f);
f82aff7c 7070 }
d724d989
JB
7071 }
7072
44fa5b1e 7073 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 7074 do_pending_window_change (1);
a2889657 7075
5f5c8ee5 7076 /* Clear frames marked as garbaged. */
44fa5b1e 7077 if (frame_garbaged)
c6e89d6c 7078 clear_garbaged_frames ();
a2889657 7079
e037b9ec 7080 /* Build menubar and tool-bar items. */
f82aff7c
RS
7081 prepare_menu_bars ();
7082
28995e67 7083 if (windows_or_buffers_changed)
a2889657
JB
7084 update_mode_lines++;
7085
538f13d4
RS
7086 /* Detect case that we need to write or remove a star in the mode line. */
7087 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
7088 {
7089 w->update_mode_line = Qt;
7090 if (buffer_shared > 1)
7091 update_mode_lines++;
7092 }
7093
5f5c8ee5 7094 /* If %c is in the mode line, update it if needed. */
28995e67
RS
7095 if (!NILP (w->column_number_displayed)
7096 /* This alternative quickly identifies a common case
7097 where no change is needed. */
7098 && !(PT == XFASTINT (w->last_point)
8850a573
RS
7099 && XFASTINT (w->last_modified) >= MODIFF
7100 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
7101 && XFASTINT (w->column_number_displayed) != current_column ())
7102 w->update_mode_line = Qt;
7103
44fa5b1e 7104 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 7105
5f5c8ee5
GM
7106 /* The variable buffer_shared is set in redisplay_window and
7107 indicates that we redisplay a buffer in different windows. See
7108 there. */
7109 consider_all_windows_p = update_mode_lines || buffer_shared > 1;
a2889657
JB
7110
7111 /* If specs for an arrow have changed, do thorough redisplay
7112 to ensure we remove any arrow that should no longer exist. */
d45de95b 7113 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 7114 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 7115 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 7116
90adcf20
RS
7117 /* Normally the message* functions will have already displayed and
7118 updated the echo area, but the frame may have been trashed, or
7119 the update may have been preempted, so display the echo area
c6e89d6c
GM
7120 again here. Checking both message buffers captures the case that
7121 the echo area should be cleared. */
7122 if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
90adcf20 7123 {
c6e89d6c 7124 int window_height_changed_p = echo_area_display (0);
90adcf20 7125 must_finish = 1;
dd2eb166 7126
c6e89d6c
GM
7127 if (fonts_changed_p)
7128 goto retry;
7129 else if (window_height_changed_p)
7130 {
7131 consider_all_windows_p = 1;
7132 ++update_mode_lines;
7133 ++windows_or_buffers_changed;
9142dd5b
GM
7134
7135 /* If window configuration was changed, frames may have been
7136 marked garbaged. Clear them or we will experience
7137 surprises wrt scrolling. */
7138 if (frame_garbaged)
7139 clear_garbaged_frames ();
c6e89d6c 7140 }
90adcf20 7141 }
dd2eb166
GM
7142 else if (w == XWINDOW (minibuf_window)
7143 && (current_buffer->clip_changed
7144 || XFASTINT (w->last_modified) < MODIFF
7145 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 7146 && resize_mini_window (w, 0))
c6e89d6c
GM
7147 {
7148 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
7149 showing if its contents might have changed. */
7150 must_finish = 1;
7151 consider_all_windows_p = 1;
c6e89d6c 7152 ++windows_or_buffers_changed;
dd2eb166 7153 ++update_mode_lines;
9142dd5b
GM
7154
7155 /* If window configuration was changed, frames may have been
7156 marked garbaged. Clear them or we will experience
7157 surprises wrt scrolling. */
7158 if (frame_garbaged)
7159 clear_garbaged_frames ();
c6e89d6c
GM
7160 }
7161
90adcf20 7162
5f5c8ee5
GM
7163 /* If showing the region, and mark has changed, we must redisplay
7164 the whole window. The assignment to this_line_start_pos prevents
7165 the optimization directly below this if-statement. */
bd66d1ba
RS
7166 if (((!NILP (Vtransient_mark_mode)
7167 && !NILP (XBUFFER (w->buffer)->mark_active))
7168 != !NILP (w->region_showing))
82d04750
JB
7169 || (!NILP (w->region_showing)
7170 && !EQ (w->region_showing,
7171 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
7172 CHARPOS (this_line_start_pos) = 0;
7173
7174 /* Optimize the case that only the line containing the cursor in the
7175 selected window has changed. Variables starting with this_ are
7176 set in display_line and record information about the line
7177 containing the cursor. */
7178 tlbufpos = this_line_start_pos;
7179 tlendpos = this_line_end_pos;
7180 if (!consider_all_windows_p
7181 && CHARPOS (tlbufpos) > 0
7182 && NILP (w->update_mode_line)
73af359d 7183 && !current_buffer->clip_changed
44fa5b1e 7184 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 7185 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 7186 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
7187 && this_line_buffer == current_buffer
7188 && current_buffer == XBUFFER (w->buffer)
265a9e55 7189 && NILP (w->force_start)
5f5c8ee5
GM
7190 /* Point must be on the line that we have info recorded about. */
7191 && PT >= CHARPOS (tlbufpos)
7192 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
7193 /* All text outside that line, including its final newline,
7194 must be unchanged */
5f5c8ee5
GM
7195 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
7196 CHARPOS (tlendpos)))
7197 {
7198 if (CHARPOS (tlbufpos) > BEGV
7199 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
7200 && (CHARPOS (tlbufpos) == ZV
7201 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
7202 /* Former continuation line has disappeared by becoming empty */
7203 goto cancel;
7204 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 7205 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
7206 || MINI_WINDOW_P (w))
7207 {
1c9241f5
KH
7208 /* We have to handle the case of continuation around a
7209 wide-column character (See the comment in indent.c around
7210 line 885).
7211
7212 For instance, in the following case:
7213
7214 -------- Insert --------
7215 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
7216 J_I_ ==> J_I_ `^^' are cursors.
7217 ^^ ^^
7218 -------- --------
7219
7220 As we have to redraw the line above, we should goto cancel. */
7221
5f5c8ee5
GM
7222 struct it it;
7223 int line_height_before = this_line_pixel_height;
7224
7225 /* Note that start_display will handle the case that the
7226 line starting at tlbufpos is a continuation lines. */
7227 start_display (&it, w, tlbufpos);
7228
7229 /* Implementation note: It this still necessary? */
7230 if (it.current_x != this_line_start_x)
1c9241f5
KH
7231 goto cancel;
7232
5f5c8ee5
GM
7233 TRACE ((stderr, "trying display optimization 1\n"));
7234 w->cursor.vpos = -1;
a2889657 7235 overlay_arrow_seen = 0;
5f5c8ee5
GM
7236 it.vpos = this_line_vpos;
7237 it.current_y = this_line_y;
7238 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
7239 display_line (&it);
7240
a2889657 7241 /* If line contains point, is not continued,
5f5c8ee5
GM
7242 and ends at same distance from eob as before, we win */
7243 if (w->cursor.vpos >= 0
7244 /* Line is not continued, otherwise this_line_start_pos
7245 would have been set to 0 in display_line. */
7246 && CHARPOS (this_line_start_pos)
7247 /* Line ends as before. */
7248 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
7249 /* Line has same height as before. Otherwise other lines
7250 would have to be shifted up or down. */
7251 && this_line_pixel_height == line_height_before)
a2889657 7252 {
5f5c8ee5
GM
7253 /* If this is not the window's last line, we must adjust
7254 the charstarts of the lines below. */
7255 if (it.current_y < it.last_visible_y)
7256 {
7257 struct glyph_row *row
7258 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
7259 int delta, delta_bytes;
7260
7261 if (Z - CHARPOS (tlendpos) == ZV)
7262 {
7263 /* This line ends at end of (accessible part of)
7264 buffer. There is no newline to count. */
7265 delta = (Z
7266 - CHARPOS (tlendpos)
7267 - MATRIX_ROW_START_CHARPOS (row));
7268 delta_bytes = (Z_BYTE
7269 - BYTEPOS (tlendpos)
7270 - MATRIX_ROW_START_BYTEPOS (row));
7271 }
7272 else
7273 {
7274 /* This line ends in a newline. Must take
7275 account of the newline and the rest of the
7276 text that follows. */
7277 delta = (Z
7278 - CHARPOS (tlendpos)
7279 - MATRIX_ROW_START_CHARPOS (row));
7280 delta_bytes = (Z_BYTE
7281 - BYTEPOS (tlendpos)
7282 - MATRIX_ROW_START_BYTEPOS (row));
7283 }
7284
7285 increment_glyph_matrix_buffer_positions (w->current_matrix,
7286 this_line_vpos + 1,
7287 w->current_matrix->nrows,
7288 delta, delta_bytes);
85bcef6c 7289 }
46db8486 7290
5f5c8ee5
GM
7291 /* If this row displays text now but previously didn't,
7292 or vice versa, w->window_end_vpos may have to be
7293 adjusted. */
7294 if ((it.glyph_row - 1)->displays_text_p)
7295 {
7296 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
7297 XSETINT (w->window_end_vpos, this_line_vpos);
7298 }
7299 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
7300 && this_line_vpos > 0)
7301 XSETINT (w->window_end_vpos, this_line_vpos - 1);
7302 w->window_end_valid = Qnil;
7303
7304 /* Update hint: No need to try to scroll in update_window. */
7305 w->desired_matrix->no_scrolling_p = 1;
7306
7307#if GLYPH_DEBUG
7308 *w->desired_matrix->method = 0;
7309 debug_method_add (w, "optimization 1");
7310#endif
a2889657
JB
7311 goto update;
7312 }
7313 else
7314 goto cancel;
7315 }
5f5c8ee5
GM
7316 else if (/* Cursor position hasn't changed. */
7317 PT == XFASTINT (w->last_point)
b6f0fe04
RS
7318 /* Make sure the cursor was last displayed
7319 in this window. Otherwise we have to reposition it. */
5f5c8ee5
GM
7320 && 0 <= w->cursor.vpos
7321 && XINT (w->height) > w->cursor.vpos)
a2889657
JB
7322 {
7323 if (!must_finish)
7324 {
c6e89d6c 7325 do_pending_window_change (1);
5f5c8ee5
GM
7326
7327 /* We used to always goto end_of_redisplay here, but this
7328 isn't enough if we have a blinking cursor. */
7329 if (w->cursor_off_p == w->last_cursor_off_p)
7330 goto end_of_redisplay;
a2889657
JB
7331 }
7332 goto update;
7333 }
8b51f1e3
KH
7334 /* If highlighting the region, or if the cursor is in the echo area,
7335 then we can't just move the cursor. */
bd66d1ba
RS
7336 else if (! (!NILP (Vtransient_mark_mode)
7337 && !NILP (current_buffer->mark_active))
293a54ce
RS
7338 && (w == XWINDOW (current_buffer->last_selected_window)
7339 || highlight_nonselected_windows)
8b51f1e3 7340 && NILP (w->region_showing)
8f897821 7341 && NILP (Vshow_trailing_whitespace)
8b51f1e3 7342 && !cursor_in_echo_area)
a2889657 7343 {
5f5c8ee5
GM
7344 struct it it;
7345 struct glyph_row *row;
7346
7347 /* Skip from tlbufpos to PT and see where it is. Note that
7348 PT may be in invisible text. If so, we will end at the
7349 next visible position. */
7350 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
7351 NULL, DEFAULT_FACE_ID);
7352 it.current_x = this_line_start_x;
7353 it.current_y = this_line_y;
7354 it.vpos = this_line_vpos;
7355
7356 /* The call to move_it_to stops in front of PT, but
7357 moves over before-strings. */
7358 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
7359
7360 if (it.vpos == this_line_vpos
7361 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
7362 row->enabled_p))
a2889657 7363 {
5f5c8ee5
GM
7364 xassert (this_line_vpos == it.vpos);
7365 xassert (this_line_y == it.current_y);
7366 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
a2889657
JB
7367 goto update;
7368 }
7369 else
7370 goto cancel;
7371 }
5f5c8ee5 7372
a2889657 7373 cancel:
5f5c8ee5
GM
7374 /* Text changed drastically or point moved off of line. */
7375 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
7376 }
7377
5f5c8ee5
GM
7378 CHARPOS (this_line_start_pos) = 0;
7379 consider_all_windows_p |= buffer_shared > 1;
7380 ++clear_face_cache_count;
a2889657 7381
5f5c8ee5
GM
7382
7383 /* Build desired matrices. If consider_all_windows_p is non-zero,
7384 do it for all windows on all frames. Otherwise do it for
7385 selected_window, only. */
463f6b91 7386
5f5c8ee5 7387 if (consider_all_windows_p)
a2889657 7388 {
35f56f96 7389 Lisp_Object tail, frame;
a2889657 7390
5f5c8ee5
GM
7391 /* Clear the face cache eventually. */
7392 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 7393 {
5f5c8ee5 7394 clear_face_cache (0);
463f6b91
RS
7395 clear_face_cache_count = 0;
7396 }
31b24551 7397
5f5c8ee5
GM
7398 /* Recompute # windows showing selected buffer. This will be
7399 incremented each time such a window is displayed. */
a2889657
JB
7400 buffer_shared = 0;
7401
35f56f96 7402 FOR_EACH_FRAME (tail, frame)
30c566e4 7403 {
5f5c8ee5 7404 struct frame *f = XFRAME (frame);
886bd6f2 7405 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 7406 {
5f5c8ee5
GM
7407 /* Mark all the scroll bars to be removed; we'll redeem
7408 the ones we want when we redisplay their windows. */
9769686d
RS
7409 if (condemn_scroll_bars_hook)
7410 (*condemn_scroll_bars_hook) (f);
30c566e4 7411
f21ef775 7412 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 7413 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 7414
5f5c8ee5
GM
7415 /* Any scroll bars which redisplay_windows should have
7416 nuked should now go away. */
9769686d
RS
7417 if (judge_scroll_bars_hook)
7418 (*judge_scroll_bars_hook) (f);
7419 }
30c566e4 7420 }
a2889657 7421 }
886bd6f2
GM
7422 else if (FRAME_VISIBLE_P (sf)
7423 && !FRAME_OBSCURED_P (sf))
5f5c8ee5
GM
7424 redisplay_window (selected_window, 1);
7425
7426
7427 /* Compare desired and current matrices, perform output. */
7428
7429update:
7430
7431 /* If fonts changed, display again. */
7432 if (fonts_changed_p)
7433 goto retry;
a2889657 7434
a2889657
JB
7435 /* Prevent various kinds of signals during display update.
7436 stdio is not robust about handling signals,
7437 which can cause an apparent I/O error. */
7438 if (interrupt_input)
7439 unrequest_sigio ();
7440 stop_polling ();
7441
5f5c8ee5 7442 if (consider_all_windows_p)
a2889657
JB
7443 {
7444 Lisp_Object tail;
92a90e89
GM
7445 struct frame *f;
7446 int hscrolled_p;
a2889657
JB
7447
7448 pause = 0;
92a90e89 7449 hscrolled_p = 0;
a2889657 7450
92a90e89 7451 /* See if we have to hscroll. */
9472f927 7452 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
92a90e89
GM
7453 if (FRAMEP (XCAR (tail)))
7454 {
7455 f = XFRAME (XCAR (tail));
7456
7457 if ((FRAME_WINDOW_P (f)
886bd6f2 7458 || f == sf)
92a90e89
GM
7459 && FRAME_VISIBLE_P (f)
7460 && !FRAME_OBSCURED_P (f)
7461 && hscroll_windows (f->root_window))
7462 hscrolled_p = 1;
7463 }
7464
7465 if (hscrolled_p)
7466 goto retry;
a2889657 7467
92a90e89
GM
7468 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
7469 {
9472f927 7470 if (!FRAMEP (XCAR (tail)))
a2889657
JB
7471 continue;
7472
9472f927 7473 f = XFRAME (XCAR (tail));
1af9f229 7474
886bd6f2 7475 if ((FRAME_WINDOW_P (f) || f == sf)
f21ef775 7476 && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
a2889657 7477 {
5f5c8ee5
GM
7478 /* Mark all windows as to be updated. */
7479 set_window_update_flags (XWINDOW (f->root_window), 1);
44fa5b1e 7480 pause |= update_frame (f, 0, 0);
a2889657 7481 if (!pause)
efc63ef0
RS
7482 {
7483 mark_window_display_accurate (f->root_window, 1);
7484 if (frame_up_to_date_hook != 0)
7485 (*frame_up_to_date_hook) (f);
7486 }
a2889657
JB
7487 }
7488 }
7489 }
7490 else
6e8290aa 7491 {
886bd6f2
GM
7492 if (FRAME_VISIBLE_P (sf)
7493 && !FRAME_OBSCURED_P (sf))
5f5c8ee5 7494 {
92a90e89
GM
7495 if (hscroll_windows (selected_window))
7496 goto retry;
7497
5f5c8ee5 7498 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 7499 pause = update_frame (sf, 0, 0);
5f5c8ee5 7500 }
4d641a15
KH
7501 else
7502 pause = 0;
d724d989 7503
8de2d90b 7504 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
7505 function. If the echo area is on another frame, that may
7506 have put text on a frame other than the selected one, so the
7507 above call to update_frame would not have caught it. Catch
8de2d90b
JB
7508 it here. */
7509 {
84faf44c 7510 Lisp_Object mini_window;
5f5c8ee5 7511 struct frame *mini_frame;
84faf44c 7512
886bd6f2 7513 mini_window = FRAME_MINIBUF_WINDOW (sf);
84faf44c 7514 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
8de2d90b 7515
886bd6f2 7516 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
5f5c8ee5
GM
7517 {
7518 XWINDOW (mini_window)->must_be_updated_p = 1;
7519 pause |= update_frame (mini_frame, 0, 0);
7520 if (!pause && hscroll_windows (mini_window))
7521 goto retry;
7522 }
8de2d90b 7523 }
6e8290aa 7524 }
a2889657 7525
5f5c8ee5
GM
7526 /* If display was paused because of pending input, make sure we do a
7527 thorough update the next time. */
a2889657
JB
7528 if (pause)
7529 {
5f5c8ee5
GM
7530 /* Prevent the optimization at the beginning of
7531 redisplay_internal that tries a single-line update of the
7532 line containing the cursor in the selected window. */
7533 CHARPOS (this_line_start_pos) = 0;
7534
7535 /* Let the overlay arrow be updated the next time. */
265a9e55 7536 if (!NILP (last_arrow_position))
a2889657
JB
7537 {
7538 last_arrow_position = Qt;
7539 last_arrow_string = Qt;
7540 }
5f5c8ee5
GM
7541
7542 /* If we pause after scrolling, some rows in the current
7543 matrices of some windows are not valid. */
7544 if (!WINDOW_FULL_WIDTH_P (w)
7545 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
7546 update_mode_lines = 1;
7547 }
7548
5f5c8ee5
GM
7549 /* Now text on frame agrees with windows, so put info into the
7550 windows for partial redisplay to follow. */
a2889657
JB
7551 if (!pause)
7552 {
7553 register struct buffer *b = XBUFFER (w->buffer);
7554
9142dd5b
GM
7555 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
7556 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
7557 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
7558 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
a2889657 7559
5f5c8ee5 7560 if (consider_all_windows_p)
886bd6f2 7561 mark_window_display_accurate (FRAME_ROOT_WINDOW (sf), 1);
a2889657
JB
7562 else
7563 {
5f5c8ee5
GM
7564 XSETFASTINT (w->last_point, BUF_PT (b));
7565 w->last_cursor = w->cursor;
7566 w->last_cursor_off_p = w->cursor_off_p;
7567
28995e67 7568 b->clip_changed = 0;
9142dd5b 7569 b->prevent_redisplay_optimizations_p = 0;
a2889657 7570 w->update_mode_line = Qnil;
c2213350 7571 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
8850a573 7572 XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
538f13d4
RS
7573 w->last_had_star
7574 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
7575 ? Qt : Qnil);
3ee4159a
RS
7576
7577 /* Record if we are showing a region, so can make sure to
7578 update it fully at next redisplay. */
7579 w->region_showing = (!NILP (Vtransient_mark_mode)
293a54ce
RS
7580 && (w == XWINDOW (current_buffer->last_selected_window)
7581 || highlight_nonselected_windows)
3ee4159a
RS
7582 && !NILP (XBUFFER (w->buffer)->mark_active)
7583 ? Fmarker_position (XBUFFER (w->buffer)->mark)
7584 : Qnil);
7585
d2f84654 7586 w->window_end_valid = w->buffer;
d45de95b 7587 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657 7588 last_arrow_string = Voverlay_arrow_string;
efc63ef0 7589 if (frame_up_to_date_hook != 0)
886bd6f2 7590 (*frame_up_to_date_hook) (sf);
9142dd5b
GM
7591
7592 w->current_matrix->buffer = b;
7593 w->current_matrix->begv = BUF_BEGV (b);
7594 w->current_matrix->zv = BUF_ZV (b);
a2889657 7595 }
5f5c8ee5 7596
a2889657
JB
7597 update_mode_lines = 0;
7598 windows_or_buffers_changed = 0;
7599 }
7600
5f5c8ee5
GM
7601 /* Start SIGIO interrupts coming again. Having them off during the
7602 code above makes it less likely one will discard output, but not
7603 impossible, since there might be stuff in the system buffer here.
a2889657 7604 But it is much hairier to try to do anything about that. */
a2889657
JB
7605 if (interrupt_input)
7606 request_sigio ();
7607 start_polling ();
7608
5f5c8ee5
GM
7609 /* If a frame has become visible which was not before, redisplay
7610 again, so that we display it. Expose events for such a frame
7611 (which it gets when becoming visible) don't call the parts of
7612 redisplay constructing glyphs, so simply exposing a frame won't
7613 display anything in this case. So, we have to display these
7614 frames here explicitly. */
11c52c4f
RS
7615 if (!pause)
7616 {
7617 Lisp_Object tail, frame;
7618 int new_count = 0;
7619
7620 FOR_EACH_FRAME (tail, frame)
7621 {
7622 int this_is_visible = 0;
8e83f802
RS
7623
7624 if (XFRAME (frame)->visible)
7625 this_is_visible = 1;
7626 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
7627 if (XFRAME (frame)->visible)
7628 this_is_visible = 1;
11c52c4f
RS
7629
7630 if (this_is_visible)
7631 new_count++;
7632 }
7633
89819bdd 7634 if (new_count != number_of_visible_frames)
11c52c4f
RS
7635 windows_or_buffers_changed++;
7636 }
7637
44fa5b1e 7638 /* Change frame size now if a change is pending. */
c6e89d6c 7639 do_pending_window_change (1);
d8e242fd 7640
8b32d885
RS
7641 /* If we just did a pending size change, or have additional
7642 visible frames, redisplay again. */
3c8c72e0 7643 if (windows_or_buffers_changed && !pause)
8b32d885 7644 goto retry;
5f5c8ee5
GM
7645
7646 end_of_redisplay:;
c6e89d6c 7647
28514cd9 7648 unbind_to (count, Qnil);
a2889657
JB
7649}
7650
5f5c8ee5
GM
7651
7652/* Redisplay, but leave alone any recent echo area message unless
7653 another message has been requested in its place.
a2889657
JB
7654
7655 This is useful in situations where you need to redisplay but no
7656 user action has occurred, making it inappropriate for the message
7657 area to be cleared. See tracking_off and
7658 wait_reading_process_input for examples of these situations. */
7659
8991bb31 7660void
a2889657
JB
7661redisplay_preserve_echo_area ()
7662{
c6e89d6c 7663 if (!NILP (echo_area_buffer[1]))
a2889657 7664 {
c6e89d6c
GM
7665 /* We have a previously displayed message, but no current
7666 message. Redisplay the previous message. */
7667 display_last_displayed_message_p = 1;
e9874cee 7668 redisplay_internal (1);
c6e89d6c 7669 display_last_displayed_message_p = 0;
a2889657
JB
7670 }
7671 else
e9874cee 7672 redisplay_internal (1);
a2889657
JB
7673}
7674
5f5c8ee5 7675
28514cd9
GM
7676/* Function registered with record_unwind_protect in
7677 redisplay_internal. Clears the flag indicating that a redisplay is
7678 in progress. */
7679
7680static Lisp_Object
7681unwind_redisplay (old_redisplaying_p)
7682 Lisp_Object old_redisplaying_p;
7683{
7684 redisplaying_p = XFASTINT (old_redisplaying_p);
c6e89d6c 7685 return Qnil;
28514cd9
GM
7686}
7687
7688
5f5c8ee5
GM
7689/* Mark the display of windows in the window tree rooted at WINDOW as
7690 accurate or inaccurate. If FLAG is non-zero mark display of WINDOW
7691 as accurate. If FLAG is zero arrange for WINDOW to be redisplayed
7692 the next time redisplay_internal is called. */
7693
a2889657 7694void
5f5c8ee5 7695mark_window_display_accurate (window, accurate_p)
a2889657 7696 Lisp_Object window;
5f5c8ee5 7697 int accurate_p;
a2889657 7698{
5f5c8ee5
GM
7699 struct window *w;
7700
7701 for (; !NILP (window); window = w->next)
a2889657
JB
7702 {
7703 w = XWINDOW (window);
7704
5f5c8ee5 7705 if (BUFFERP (w->buffer))
bd66d1ba 7706 {
5f5c8ee5
GM
7707 struct buffer *b = XBUFFER (w->buffer);
7708
c2213350 7709 XSETFASTINT (w->last_modified,
5f5c8ee5 7710 accurate_p ? BUF_MODIFF (b) : 0);
8850a573 7711 XSETFASTINT (w->last_overlay_modified,
5f5c8ee5
GM
7712 accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
7713 w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)
7714 ? Qt : Qnil);
bd66d1ba 7715
5f5c8ee5
GM
7716#if 0 /* I don't think this is necessary because display_line does it.
7717 Let's check it. */
bd66d1ba
RS
7718 /* Record if we are showing a region, so can make sure to
7719 update it fully at next redisplay. */
5f5c8ee5
GM
7720 w->region_showing
7721 = (!NILP (Vtransient_mark_mode)
7722 && (w == XWINDOW (current_buffer->last_selected_window)
7723 || highlight_nonselected_windows)
7724 && (!NILP (b->mark_active)
7725 ? Fmarker_position (b->mark)
7726 : Qnil));
7727#endif
7728
7729 if (accurate_p)
7730 {
7731 b->clip_changed = 0;
9142dd5b
GM
7732 b->prevent_redisplay_optimizations_p = 0;
7733 w->current_matrix->buffer = b;
7734 w->current_matrix->begv = BUF_BEGV (b);
7735 w->current_matrix->zv = BUF_ZV (b);
5f5c8ee5
GM
7736 w->last_cursor = w->cursor;
7737 w->last_cursor_off_p = w->cursor_off_p;
7738 if (w == XWINDOW (selected_window))
7739 w->last_point = BUF_PT (b);
7740 else
7741 w->last_point = XMARKER (w->pointm)->charpos;
7742 }
bd66d1ba
RS
7743 }
7744
d2f84654 7745 w->window_end_valid = w->buffer;
a2889657
JB
7746 w->update_mode_line = Qnil;
7747
265a9e55 7748 if (!NILP (w->vchild))
5f5c8ee5 7749 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 7750 if (!NILP (w->hchild))
5f5c8ee5 7751 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
7752 }
7753
5f5c8ee5 7754 if (accurate_p)
a2889657 7755 {
d45de95b 7756 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
7757 last_arrow_string = Voverlay_arrow_string;
7758 }
7759 else
7760 {
5f5c8ee5
GM
7761 /* Force a thorough redisplay the next time by setting
7762 last_arrow_position and last_arrow_string to t, which is
7763 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
7764 last_arrow_position = Qt;
7765 last_arrow_string = Qt;
7766 }
7767}
5f5c8ee5
GM
7768
7769
7770/* Return value in display table DP (Lisp_Char_Table *) for character
7771 C. Since a display table doesn't have any parent, we don't have to
7772 follow parent. Do not call this function directly but use the
7773 macro DISP_CHAR_VECTOR. */
7774
7775Lisp_Object
7776disp_char_vector (dp, c)
7777 struct Lisp_Char_Table *dp;
7778 int c;
7779{
7780 int code[4], i;
7781 Lisp_Object val;
7782
7783 if (SINGLE_BYTE_CHAR_P (c))
7784 return (dp->contents[c]);
7785
7786 SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
7787 if (code[0] != CHARSET_COMPOSITION)
7788 {
7789 if (code[1] < 32)
7790 code[1] = -1;
7791 else if (code[2] < 32)
7792 code[2] = -1;
7793 }
7794
7795 /* Here, the possible range of code[0] (== charset ID) is
7796 128..max_charset. Since the top level char table contains data
7797 for multibyte characters after 256th element, we must increment
7798 code[0] by 128 to get a correct index. */
7799 code[0] += 128;
7800 code[3] = -1; /* anchor */
7801
7802 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
7803 {
7804 val = dp->contents[code[i]];
7805 if (!SUB_CHAR_TABLE_P (val))
7806 return (NILP (val) ? dp->defalt : val);
7807 }
7808
7809 /* Here, val is a sub char table. We return the default value of
7810 it. */
7811 return (dp->defalt);
7812}
7813
7814
a2889657 7815\f
5f5c8ee5
GM
7816/***********************************************************************
7817 Window Redisplay
7818 ***********************************************************************/
a2725ab2 7819
5f5c8ee5 7820/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
7821
7822static void
5f5c8ee5
GM
7823redisplay_windows (window)
7824 Lisp_Object window;
90adcf20 7825{
5f5c8ee5
GM
7826 while (!NILP (window))
7827 {
7828 struct window *w = XWINDOW (window);
7829
7830 if (!NILP (w->hchild))
7831 redisplay_windows (w->hchild);
7832 else if (!NILP (w->vchild))
7833 redisplay_windows (w->vchild);
7834 else
7835 redisplay_window (window, 0);
a2725ab2 7836
5f5c8ee5
GM
7837 window = w->next;
7838 }
7839}
7840
7841
7842/* Set cursor position of W. PT is assumed to be displayed in ROW.
7843 DELTA is the number of bytes by which positions recorded in ROW
7844 differ from current buffer positions. */
7845
7846void
7847set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
7848 struct window *w;
7849 struct glyph_row *row;
7850 struct glyph_matrix *matrix;
7851 int delta, delta_bytes, dy, dvpos;
7852{
7853 struct glyph *glyph = row->glyphs[TEXT_AREA];
7854 struct glyph *end = glyph + row->used[TEXT_AREA];
7855 int x = row->x;
7856 int pt_old = PT - delta;
7857
7858 /* Skip over glyphs not having an object at the start of the row.
7859 These are special glyphs like truncation marks on terminal
7860 frames. */
7861 if (row->displays_text_p)
7862 while (glyph < end
7863 && !glyph->object
7864 && glyph->charpos < 0)
7865 {
7866 x += glyph->pixel_width;
7867 ++glyph;
7868 }
7869
7870 while (glyph < end
7871 && glyph->object
7872 && (!BUFFERP (glyph->object)
7873 || glyph->charpos < pt_old))
7874 {
7875 x += glyph->pixel_width;
7876 ++glyph;
7877 }
7878
7879 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
7880 w->cursor.x = x;
7881 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
7882 w->cursor.y = row->y + dy;
7883
7884 if (w == XWINDOW (selected_window))
7885 {
7886 if (!row->continued_p
7887 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
7888 && row->x == 0)
7889 {
7890 this_line_buffer = XBUFFER (w->buffer);
7891
7892 CHARPOS (this_line_start_pos)
7893 = MATRIX_ROW_START_CHARPOS (row) + delta;
7894 BYTEPOS (this_line_start_pos)
7895 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
7896
7897 CHARPOS (this_line_end_pos)
7898 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
7899 BYTEPOS (this_line_end_pos)
7900 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
7901
7902 this_line_y = w->cursor.y;
7903 this_line_pixel_height = row->height;
7904 this_line_vpos = w->cursor.vpos;
7905 this_line_start_x = row->x;
7906 }
7907 else
7908 CHARPOS (this_line_start_pos) = 0;
7909 }
7910}
7911
7912
7913/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
7914 start STARTP. Sets the window start of WINDOW to that position.
7915
7916 We assume that the window's buffer is really current. */
5f5c8ee5
GM
7917
7918static INLINE struct text_pos
7919run_window_scroll_functions (window, startp)
7920 Lisp_Object window;
7921 struct text_pos startp;
7922{
7923 struct window *w = XWINDOW (window);
7924 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
7925
7926 if (current_buffer != XBUFFER (w->buffer))
7927 abort ();
7928
5f5c8ee5
GM
7929 if (!NILP (Vwindow_scroll_functions))
7930 {
7931 run_hook_with_args_2 (Qwindow_scroll_functions, window,
7932 make_number (CHARPOS (startp)));
7933 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
7934 /* In case the hook functions switch buffers. */
7935 if (current_buffer != XBUFFER (w->buffer))
7936 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 7937 }
90adcf20 7938
5f5c8ee5
GM
7939 return startp;
7940}
7941
7942
7943/* Modify the desired matrix of window W and W->vscroll so that the
7944 line containing the cursor is fully visible. */
7945
7946static void
7947make_cursor_line_fully_visible (w)
7948 struct window *w;
7949{
7950 struct glyph_matrix *matrix;
7951 struct glyph_row *row;
045dee35 7952 int header_line_height;
5f5c8ee5
GM
7953
7954 /* It's not always possible to find the cursor, e.g, when a window
7955 is full of overlay strings. Don't do anything in that case. */
7956 if (w->cursor.vpos < 0)
7957 return;
7958
7959 matrix = w->desired_matrix;
7960 row = MATRIX_ROW (matrix, w->cursor.vpos);
7961
7962 /* If row->y == top y of window display area, the window isn't tall
7963 enough to display a single line. There is nothing we can do
7964 about it. */
045dee35
GM
7965 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
7966 if (row->y == header_line_height)
5f5c8ee5
GM
7967 return;
7968
7969 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
7970 {
7971 int dy = row->height - row->visible_height;
7972 w->vscroll = 0;
7973 w->cursor.y += dy;
7974 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
7975 }
7976 else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
7977 {
7978 int dy = - (row->height - row->visible_height);
7979 w->vscroll = dy;
7980 w->cursor.y += dy;
7981 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
7982 }
7983
7984 /* When we change the cursor y-position of the selected window,
7985 change this_line_y as well so that the display optimization for
7986 the cursor line of the selected window in redisplay_internal uses
7987 the correct y-position. */
7988 if (w == XWINDOW (selected_window))
7989 this_line_y = w->cursor.y;
7990}
7991
7992
7993/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
7994 non-zero means only WINDOW is redisplayed in redisplay_internal.
7995 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
7996 in redisplay_window to bring a partially visible line into view in
7997 the case that only the cursor has moved.
7998
7999 Value is
8000
8001 1 if scrolling succeeded
8002
8003 0 if scrolling didn't find point.
8004
8005 -1 if new fonts have been loaded so that we must interrupt
8006 redisplay, adjust glyph matrices, and try again. */
8007
8008static int
8009try_scrolling (window, just_this_one_p, scroll_conservatively,
8010 scroll_step, temp_scroll_step)
8011 Lisp_Object window;
8012 int just_this_one_p;
8013 int scroll_conservatively, scroll_step;
8014 int temp_scroll_step;
8015{
8016 struct window *w = XWINDOW (window);
8017 struct frame *f = XFRAME (w->frame);
8018 struct text_pos scroll_margin_pos;
8019 struct text_pos pos;
8020 struct text_pos startp;
8021 struct it it;
8022 Lisp_Object window_end;
8023 int this_scroll_margin;
8024 int dy = 0;
8025 int scroll_max;
8026 int line_height, rc;
8027 int amount_to_scroll = 0;
8028 Lisp_Object aggressive;
8029 int height;
8030
8031#if GLYPH_DEBUG
8032 debug_method_add (w, "try_scrolling");
78614721 8033#endif
5f5c8ee5
GM
8034
8035 SET_TEXT_POS_FROM_MARKER (startp, w->start);
8036
8037 /* Compute scroll margin height in pixels. We scroll when point is
8038 within this distance from the top or bottom of the window. */
8039 if (scroll_margin > 0)
90adcf20 8040 {
5f5c8ee5
GM
8041 this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
8042 this_scroll_margin *= CANON_Y_UNIT (f);
8043 }
8044 else
8045 this_scroll_margin = 0;
8046
8047 /* Compute how much we should try to scroll maximally to bring point
8048 into view. */
8049 if (scroll_step)
8050 scroll_max = scroll_step;
8051 else if (scroll_conservatively)
8052 scroll_max = scroll_conservatively;
8053 else if (temp_scroll_step)
8054 scroll_max = temp_scroll_step;
8055 else if (NUMBERP (current_buffer->scroll_down_aggressively)
8056 || NUMBERP (current_buffer->scroll_up_aggressively))
8057 /* We're trying to scroll because of aggressive scrolling
8058 but no scroll_step is set. Choose an arbitrary one. Maybe
8059 there should be a variable for this. */
8060 scroll_max = 10;
8061 else
8062 scroll_max = 0;
8063 scroll_max *= CANON_Y_UNIT (f);
8064
8065 /* Decide whether we have to scroll down. Start at the window end
8066 and move this_scroll_margin up to find the position of the scroll
8067 margin. */
8068 window_end = Fwindow_end (window, Qt);
8069 CHARPOS (scroll_margin_pos) = XINT (window_end);
8070 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
8071 if (this_scroll_margin)
8072 {
8073 start_display (&it, w, scroll_margin_pos);
8074 move_it_vertically (&it, - this_scroll_margin);
8075 scroll_margin_pos = it.current.pos;
8076 }
8077
8078 if (PT >= CHARPOS (scroll_margin_pos))
8079 {
8080 int y0;
8081
8082 /* Point is in the scroll margin at the bottom of the window, or
8083 below. Compute a new window start that makes point visible. */
8084
8085 /* Compute the distance from the scroll margin to PT.
8086 Give up if the distance is greater than scroll_max. */
8087 start_display (&it, w, scroll_margin_pos);
8088 y0 = it.current_y;
8089 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8090 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8091 line_height = (it.max_ascent + it.max_descent
8092 ? it.max_ascent + it.max_descent
8093 : last_height);
8094 dy = it.current_y + line_height - y0;
8095 if (dy > scroll_max)
8096 return 0;
8097
8098 /* Move the window start down. If scrolling conservatively,
8099 move it just enough down to make point visible. If
8100 scroll_step is set, move it down by scroll_step. */
8101 start_display (&it, w, startp);
8102
8103 if (scroll_conservatively)
8104 amount_to_scroll = dy;
8105 else if (scroll_step || temp_scroll_step)
8106 amount_to_scroll = scroll_max;
8107 else
90adcf20 8108 {
5f5c8ee5
GM
8109 aggressive = current_buffer->scroll_down_aggressively;
8110 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8111 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8112 if (NUMBERP (aggressive))
8113 amount_to_scroll = XFLOATINT (aggressive) * height;
8114 }
a2725ab2 8115
5f5c8ee5
GM
8116 if (amount_to_scroll <= 0)
8117 return 0;
a2725ab2 8118
5f5c8ee5
GM
8119 move_it_vertically (&it, amount_to_scroll);
8120 startp = it.current.pos;
8121 }
8122 else
8123 {
8124 /* See if point is inside the scroll margin at the top of the
8125 window. */
8126 scroll_margin_pos = startp;
8127 if (this_scroll_margin)
8128 {
8129 start_display (&it, w, startp);
8130 move_it_vertically (&it, this_scroll_margin);
8131 scroll_margin_pos = it.current.pos;
8132 }
8133
8134 if (PT < CHARPOS (scroll_margin_pos))
8135 {
8136 /* Point is in the scroll margin at the top of the window or
8137 above what is displayed in the window. */
8138 int y0;
8139
8140 /* Compute the vertical distance from PT to the scroll
8141 margin position. Give up if distance is greater than
8142 scroll_max. */
8143 SET_TEXT_POS (pos, PT, PT_BYTE);
8144 start_display (&it, w, pos);
8145 y0 = it.current_y;
8146 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
8147 it.last_visible_y, -1,
8148 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8149 dy = it.current_y - y0;
8150 if (dy > scroll_max)
8151 return 0;
8152
8153 /* Compute new window start. */
8154 start_display (&it, w, startp);
8155
8156 if (scroll_conservatively)
8157 amount_to_scroll = dy;
8158 else if (scroll_step || temp_scroll_step)
8159 amount_to_scroll = scroll_max;
538f13d4 8160 else
5f5c8ee5
GM
8161 {
8162 aggressive = current_buffer->scroll_up_aggressively;
8163 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8164 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8165 if (NUMBERP (aggressive))
8166 amount_to_scroll = XFLOATINT (aggressive) * height;
8167 }
a2725ab2 8168
5f5c8ee5
GM
8169 if (amount_to_scroll <= 0)
8170 return 0;
8171
8172 move_it_vertically (&it, - amount_to_scroll);
8173 startp = it.current.pos;
90adcf20
RS
8174 }
8175 }
a2889657 8176
5f5c8ee5
GM
8177 /* Run window scroll functions. */
8178 startp = run_window_scroll_functions (window, startp);
90adcf20 8179
5f5c8ee5
GM
8180 /* Display the window. Give up if new fonts are loaded, or if point
8181 doesn't appear. */
8182 if (!try_window (window, startp))
8183 rc = -1;
8184 else if (w->cursor.vpos < 0)
8185 {
8186 clear_glyph_matrix (w->desired_matrix);
8187 rc = 0;
8188 }
8189 else
8190 {
8191 /* Maybe forget recorded base line for line number display. */
8192 if (!just_this_one_p
8193 || current_buffer->clip_changed
9142dd5b 8194 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5
GM
8195 w->base_line_number = Qnil;
8196
8197 /* If cursor ends up on a partially visible line, shift display
8198 lines up or down. */
8199 make_cursor_line_fully_visible (w);
8200 rc = 1;
8201 }
8202
8203 return rc;
a2889657
JB
8204}
8205
5f5c8ee5
GM
8206
8207/* Compute a suitable window start for window W if display of W starts
8208 on a continuation line. Value is non-zero if a new window start
8209 was computed.
8210
8211 The new window start will be computed, based on W's width, starting
8212 from the start of the continued line. It is the start of the
8213 screen line with the minimum distance from the old start W->start. */
8214
8215static int
8216compute_window_start_on_continuation_line (w)
8217 struct window *w;
1f1ff51d 8218{
5f5c8ee5
GM
8219 struct text_pos pos, start_pos;
8220 int window_start_changed_p = 0;
1f1ff51d 8221
5f5c8ee5 8222 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 8223
5f5c8ee5
GM
8224 /* If window start is on a continuation line... Window start may be
8225 < BEGV in case there's invisible text at the start of the
8226 buffer (M-x rmail, for example). */
8227 if (CHARPOS (start_pos) > BEGV
8228 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 8229 {
5f5c8ee5
GM
8230 struct it it;
8231 struct glyph_row *row;
f3751a65
GM
8232
8233 /* Handle the case that the window start is out of range. */
8234 if (CHARPOS (start_pos) < BEGV)
8235 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
8236 else if (CHARPOS (start_pos) > ZV)
8237 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
5f5c8ee5
GM
8238
8239 /* Find the start of the continued line. This should be fast
8240 because scan_buffer is fast (newline cache). */
045dee35 8241 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
8242 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
8243 row, DEFAULT_FACE_ID);
8244 reseat_at_previous_visible_line_start (&it);
8245
8246 /* If the line start is "too far" away from the window start,
8247 say it takes too much time to compute a new window start. */
8248 if (CHARPOS (start_pos) - IT_CHARPOS (it)
8249 < XFASTINT (w->height) * XFASTINT (w->width))
8250 {
8251 int min_distance, distance;
8252
8253 /* Move forward by display lines to find the new window
8254 start. If window width was enlarged, the new start can
8255 be expected to be > the old start. If window width was
8256 decreased, the new window start will be < the old start.
8257 So, we're looking for the display line start with the
8258 minimum distance from the old window start. */
8259 pos = it.current.pos;
8260 min_distance = INFINITY;
8261 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
8262 distance < min_distance)
8263 {
8264 min_distance = distance;
8265 pos = it.current.pos;
8266 move_it_by_lines (&it, 1, 0);
8267 }
8268
8269 /* Set the window start there. */
8270 SET_MARKER_FROM_TEXT_POS (w->start, pos);
8271 window_start_changed_p = 1;
8272 }
1f1ff51d 8273 }
5f5c8ee5
GM
8274
8275 return window_start_changed_p;
1f1ff51d
KH
8276}
8277
5f5c8ee5
GM
8278
8279/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
8280 selected_window is redisplayed. */
90adcf20 8281
a2889657 8282static void
5f5c8ee5 8283redisplay_window (window, just_this_one_p)
a2889657 8284 Lisp_Object window;
5f5c8ee5 8285 int just_this_one_p;
a2889657 8286{
5f5c8ee5
GM
8287 struct window *w = XWINDOW (window);
8288 struct frame *f = XFRAME (w->frame);
8289 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 8290 struct buffer *old = current_buffer;
5f5c8ee5 8291 struct text_pos lpoint, opoint, startp;
e481f960 8292 int update_mode_line;
5f5c8ee5
GM
8293 int tem;
8294 struct it it;
8295 /* Record it now because it's overwritten. */
8296 int current_matrix_up_to_date_p = 0;
5ba50c51 8297 int really_switched_buffer = 0;
5f5c8ee5 8298 int temp_scroll_step = 0;
2e54982e 8299 int count = specpdl_ptr - specpdl;
a2889657 8300
5f5c8ee5
GM
8301 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8302 opoint = lpoint;
a2889657 8303
5f5c8ee5
GM
8304 /* W must be a leaf window here. */
8305 xassert (!NILP (w->buffer));
8306#if GLYPH_DEBUG
8307 *w->desired_matrix->method = 0;
8308#endif
2e54982e
RS
8309
8310 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
8311
8312 reconsider_clip_changes (w, buffer);
8313
5f5c8ee5
GM
8314 /* Has the mode line to be updated? */
8315 update_mode_line = (!NILP (w->update_mode_line)
8316 || update_mode_lines
8317 || buffer->clip_changed);
8de2d90b
JB
8318
8319 if (MINI_WINDOW_P (w))
8320 {
5f5c8ee5 8321 if (w == XWINDOW (echo_area_window)
c6e89d6c 8322 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
8323 {
8324 if (update_mode_line)
8325 /* We may have to update a tty frame's menu bar or a
e037b9ec 8326 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
8327 goto finish_menu_bars;
8328 else
8329 /* We've already displayed the echo area glyphs in this window. */
8330 goto finish_scroll_bars;
8331 }
73af359d 8332 else if (w != XWINDOW (minibuf_window))
8de2d90b 8333 {
5f5c8ee5
GM
8334 /* W is a mini-buffer window, but it's not the currently
8335 active one, so clear it. */
8336 int yb = window_text_bottom_y (w);
8337 struct glyph_row *row;
8338 int y;
8339
8340 for (y = 0, row = w->desired_matrix->rows;
8341 y < yb;
8342 y += row->height, ++row)
8343 blank_row (w, row, y);
88f22aff 8344 goto finish_scroll_bars;
8de2d90b
JB
8345 }
8346 }
a2889657 8347
5f5c8ee5
GM
8348 /* Otherwise set up data on this window; select its buffer and point
8349 value. */
e481f960 8350 if (update_mode_line)
5ba50c51 8351 {
5f5c8ee5
GM
8352 /* Really select the buffer, for the sake of buffer-local
8353 variables. */
5ba50c51
RS
8354 set_buffer_internal_1 (XBUFFER (w->buffer));
8355 really_switched_buffer = 1;
8356 }
e481f960
RS
8357 else
8358 set_buffer_temp (XBUFFER (w->buffer));
5f5c8ee5
GM
8359 SET_TEXT_POS (opoint, PT, PT_BYTE);
8360
8361 current_matrix_up_to_date_p
8362 = (!NILP (w->window_end_valid)
8363 && !current_buffer->clip_changed
8364 && XFASTINT (w->last_modified) >= MODIFF
8365 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 8366
5f5c8ee5
GM
8367 /* When windows_or_buffers_changed is non-zero, we can't rely on
8368 the window end being valid, so set it to nil there. */
8369 if (windows_or_buffers_changed)
8370 {
8371 /* If window starts on a continuation line, maybe adjust the
8372 window start in case the window's width changed. */
8373 if (XMARKER (w->start)->buffer == current_buffer)
8374 compute_window_start_on_continuation_line (w);
8375
8376 w->window_end_valid = Qnil;
8377 }
12adba34 8378
5f5c8ee5
GM
8379 /* Some sanity checks. */
8380 CHECK_WINDOW_END (w);
8381 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 8382 abort ();
5f5c8ee5 8383 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 8384 abort ();
a2889657 8385
28995e67
RS
8386 /* If %c is in mode line, update it if needed. */
8387 if (!NILP (w->column_number_displayed)
8388 /* This alternative quickly identifies a common case
8389 where no change is needed. */
8390 && !(PT == XFASTINT (w->last_point)
8850a573
RS
8391 && XFASTINT (w->last_modified) >= MODIFF
8392 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
8393 && XFASTINT (w->column_number_displayed) != current_column ())
8394 update_mode_line = 1;
8395
5f5c8ee5
GM
8396 /* Count number of windows showing the selected buffer. An indirect
8397 buffer counts as its base buffer. */
8398 if (!just_this_one_p)
42640f83
RS
8399 {
8400 struct buffer *current_base, *window_base;
8401 current_base = current_buffer;
8402 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
8403 if (current_base->base_buffer)
8404 current_base = current_base->base_buffer;
8405 if (window_base->base_buffer)
8406 window_base = window_base->base_buffer;
8407 if (current_base == window_base)
8408 buffer_shared++;
8409 }
a2889657 8410
5f5c8ee5
GM
8411 /* Point refers normally to the selected window. For any other
8412 window, set up appropriate value. */
a2889657
JB
8413 if (!EQ (window, selected_window))
8414 {
12adba34
RS
8415 int new_pt = XMARKER (w->pointm)->charpos;
8416 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 8417 if (new_pt < BEGV)
a2889657 8418 {
f67a0f51 8419 new_pt = BEGV;
12adba34
RS
8420 new_pt_byte = BEGV_BYTE;
8421 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 8422 }
f67a0f51 8423 else if (new_pt > (ZV - 1))
a2889657 8424 {
f67a0f51 8425 new_pt = ZV;
12adba34
RS
8426 new_pt_byte = ZV_BYTE;
8427 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 8428 }
5f5c8ee5 8429
f67a0f51 8430 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 8431 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
8432 }
8433
f4faa47c 8434 /* If any of the character widths specified in the display table
5f5c8ee5
GM
8435 have changed, invalidate the width run cache. It's true that
8436 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
8437 redisplay goes (non-fatally) haywire when the display table is
8438 changed, so why should we worry about doing any better? */
8439 if (current_buffer->width_run_cache)
8440 {
f908610f 8441 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
8442
8443 if (! disptab_matches_widthtab (disptab,
8444 XVECTOR (current_buffer->width_table)))
8445 {
8446 invalidate_region_cache (current_buffer,
8447 current_buffer->width_run_cache,
8448 BEG, Z);
8449 recompute_width_table (current_buffer, disptab);
8450 }
8451 }
8452
a2889657 8453 /* If window-start is screwed up, choose a new one. */
a2889657
JB
8454 if (XMARKER (w->start)->buffer != current_buffer)
8455 goto recenter;
8456
5f5c8ee5 8457 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 8458
cf0df6ab
RS
8459 /* If someone specified a new starting point but did not insist,
8460 check whether it can be used. */
5f5c8ee5 8461 if (!NILP (w->optional_new_start))
cf0df6ab
RS
8462 {
8463 w->optional_new_start = Qnil;
5f5c8ee5
GM
8464 /* This takes a mini-buffer prompt into account. */
8465 start_display (&it, w, startp);
8466 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8467 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8468 if (IT_CHARPOS (it) == PT)
cf0df6ab
RS
8469 w->force_start = Qt;
8470 }
8471
8de2d90b 8472 /* Handle case where place to start displaying has been specified,
aa6d10fa 8473 unless the specified location is outside the accessible range. */
9472f927
GM
8474 if (!NILP (w->force_start)
8475 || w->frozen_window_start_p)
a2889657 8476 {
e63574d7 8477 w->force_start = Qnil;
5f5c8ee5 8478 w->vscroll = 0;
b5174a51 8479 w->window_end_valid = Qnil;
5f5c8ee5
GM
8480
8481 /* Forget any recorded base line for line number display. */
8482 if (!current_matrix_up_to_date_p
8483 || current_buffer->clip_changed)
8484 w->base_line_number = Qnil;
8485
75c43375
RS
8486 /* Redisplay the mode line. Select the buffer properly for that.
8487 Also, run the hook window-scroll-functions
8488 because we have scrolled. */
e63574d7
RS
8489 /* Note, we do this after clearing force_start because
8490 if there's an error, it is better to forget about force_start
8491 than to get into an infinite loop calling the hook functions
8492 and having them get more errors. */
75c43375
RS
8493 if (!update_mode_line
8494 || ! NILP (Vwindow_scroll_functions))
e481f960 8495 {
5ba50c51
RS
8496 if (!really_switched_buffer)
8497 {
8498 set_buffer_temp (old);
8499 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8500 really_switched_buffer = 1;
5ba50c51 8501 }
5f5c8ee5 8502
e481f960
RS
8503 update_mode_line = 1;
8504 w->update_mode_line = Qt;
5f5c8ee5 8505 startp = run_window_scroll_functions (window, startp);
e481f960 8506 }
5f5c8ee5 8507
c2213350 8508 XSETFASTINT (w->last_modified, 0);
8850a573 8509 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5
GM
8510 if (CHARPOS (startp) < BEGV)
8511 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
8512 else if (CHARPOS (startp) > ZV)
8513 SET_TEXT_POS (startp, ZV, ZV_BYTE);
8514
8515 /* Redisplay, then check if cursor has been set during the
8516 redisplay. Give up if new fonts were loaded. */
8517 if (!try_window (window, startp))
8518 {
8519 w->force_start = Qt;
8520 clear_glyph_matrix (w->desired_matrix);
8521 goto restore_buffers;
8522 }
8523
9472f927 8524 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5
GM
8525 {
8526 /* If point does not appear, or on a line that is not fully
8527 visible, move point so it does appear. The desired
8528 matrix has been built above, so we can use it. */
8529 int height = window_box_height (w) / 2;
8530 struct glyph_row *row = MATRIX_ROW (w->desired_matrix, 0);
8531
8532 while (row->y < height)
8533 ++row;
8534
8535 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
8536 MATRIX_ROW_START_BYTEPOS (row));
8537
90adcf20 8538 if (w != XWINDOW (selected_window))
12adba34 8539 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
8540 else if (current_buffer == old)
8541 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8542
8543 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
8544
8545 /* If we are highlighting the region, then we just changed
8546 the region, so redisplay to show it. */
df0b5ea1
RS
8547 if (!NILP (Vtransient_mark_mode)
8548 && !NILP (current_buffer->mark_active))
6f27fa9b 8549 {
5f5c8ee5
GM
8550 clear_glyph_matrix (w->desired_matrix);
8551 if (!try_window (window, startp))
8552 goto restore_buffers;
6f27fa9b 8553 }
a2889657 8554 }
5f5c8ee5
GM
8555
8556 make_cursor_line_fully_visible (w);
8557#if GLYPH_DEBUG
8558 debug_method_add (w, "forced window start");
8559#endif
a2889657
JB
8560 goto done;
8561 }
8562
5f5c8ee5
GM
8563 /* Handle case where text has not changed, only point, and it has
8564 not moved off the frame. */
8565 if (current_matrix_up_to_date_p
8566 /* Point may be in this window. */
8567 && PT >= CHARPOS (startp)
8568 /* If we don't check this, we are called to move the cursor in a
8569 horizontally split window with a current matrix that doesn't
8570 fit the display. */
8571 && !windows_or_buffers_changed
8572 /* Selective display hasn't changed. */
8573 && !current_buffer->clip_changed
b1aa6cb3
RS
8574 /* If force-mode-line-update was called, really redisplay;
8575 that's how redisplay is forced after e.g. changing
8576 buffer-invisibility-spec. */
632ab665 8577 && NILP (w->update_mode_line)
5f5c8ee5
GM
8578 /* Can't use this case if highlighting a region. When a
8579 region exists, cursor movement has to do more than just
8580 set the cursor. */
8581 && !(!NILP (Vtransient_mark_mode)
8582 && !NILP (current_buffer->mark_active))
bd66d1ba 8583 && NILP (w->region_showing)
8f897821 8584 && NILP (Vshow_trailing_whitespace)
5f5c8ee5
GM
8585 /* Right after splitting windows, last_point may be nil. */
8586 && INTEGERP (w->last_point)
8587 /* This code is not used for mini-buffer for the sake of the case
8588 of redisplaying to replace an echo area message; since in
8589 that case the mini-buffer contents per se are usually
8590 unchanged. This code is of no real use in the mini-buffer
8591 since the handling of this_line_start_pos, etc., in redisplay
8592 handles the same cases. */
d45de95b 8593 && !EQ (window, minibuf_window)
5f5c8ee5
GM
8594 /* When splitting windows or for new windows, it happens that
8595 redisplay is called with a nil window_end_vpos or one being
8596 larger than the window. This should really be fixed in
8597 window.c. I don't have this on my list, now, so we do
8598 approximately the same as the old redisplay code. --gerd. */
8599 && INTEGERP (w->window_end_vpos)
8600 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
8601 && (FRAME_WINDOW_P (f)
8602 || !MARKERP (Voverlay_arrow_position)
377dbd97 8603 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
a2889657 8604 {
5f5c8ee5
GM
8605 int this_scroll_margin;
8606 struct glyph_row *row;
8607 int scroll_p;
a2889657 8608
5f5c8ee5
GM
8609#if GLYPH_DEBUG
8610 debug_method_add (w, "cursor movement");
8611#endif
9afd2168 8612
5f5c8ee5
GM
8613 /* Scroll if point within this distance from the top or bottom
8614 of the window. This is a pixel value. */
8615 this_scroll_margin = max (0, scroll_margin);
8616 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
8617 this_scroll_margin *= CANON_Y_UNIT (f);
8618
8619 /* Start with the row the cursor was displayed during the last
8620 not paused redisplay. Give up if that row is not valid. */
8621 if (w->last_cursor.vpos >= w->current_matrix->nrows)
8622 goto try_to_scroll;
8623 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
8624 if (row->mode_line_p)
8625 ++row;
8626 if (!row->enabled_p)
8627 goto try_to_scroll;
8628
8629 scroll_p = 0;
8630 if (PT > XFASTINT (w->last_point))
8631 {
8632 /* Point has moved forward. */
8633 int last_y = window_text_bottom_y (w) - this_scroll_margin;
8634
8635 while ((MATRIX_ROW_END_CHARPOS (row) < PT
8636 /* The end position of a row equals the start
8637 position of the next row. If PT is there, we
8638 would rather display it in the next line, except
8639 when this line ends in ZV. */
8640 || (MATRIX_ROW_END_CHARPOS (row) == PT
8641 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
8642 || !row->ends_at_zv_p)))
8643 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
8644 {
8645 xassert (row->enabled_p);
8646 ++row;
8647 }
9afd2168 8648
5f5c8ee5
GM
8649 /* If within the scroll margin, scroll. Note that
8650 MATRIX_ROW_BOTTOM_Y gives the pixel position at which the
8651 next line would be drawn, and that this_scroll_margin can
8652 be zero. */
8653 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
8654 || PT > MATRIX_ROW_END_CHARPOS (row)
8655 /* Line is completely visible last line in window and PT
8656 is to be set in the next line. */
8657 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
8658 && PT == MATRIX_ROW_END_CHARPOS (row)
8659 && !row->ends_at_zv_p
8660 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
8661 scroll_p = 1;
8662 }
8663 else if (PT < XFASTINT (w->last_point))
a2889657 8664 {
5f5c8ee5
GM
8665 /* Cursor has to be moved backward. Note that PT >=
8666 CHARPOS (startp) because of the outer if-statement. */
8667 while (!row->mode_line_p
8668 && (MATRIX_ROW_START_CHARPOS (row) > PT
8669 || (MATRIX_ROW_START_CHARPOS (row) == PT
8670 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
8671 && (row->y > this_scroll_margin
8672 || CHARPOS (startp) == BEGV))
a2889657 8673 {
5f5c8ee5
GM
8674 xassert (row->enabled_p);
8675 --row;
a2889657 8676 }
abb4c08f 8677
5f5c8ee5
GM
8678 /* Consider the following case: Window starts at BEGV, there
8679 is invisible, intangible text at BEGV, so that display
8680 starts at some point START > BEGV. It can happen that
8681 we are called with PT somewhere between BEGV and START.
8682 Try to handle that case. */
8683 if (row < w->current_matrix->rows
8684 || row->mode_line_p)
8685 {
8686 row = w->current_matrix->rows;
8687 if (row->mode_line_p)
8688 ++row;
8689 }
8690
8691 /* Due to newlines in overlay strings, we may have to skip
8692 forward over overlay strings. */
8693 while (MATRIX_ROW_END_CHARPOS (row) == PT
8694 && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row)
8695 && !row->ends_at_zv_p)
8696 ++row;
8697
8698 /* If within the scroll margin, scroll. */
8699 if (row->y < this_scroll_margin
8700 && CHARPOS (startp) != BEGV)
8701 scroll_p = 1;
8702 }
8703
8704 /* if PT is not in the glyph row, give up. */
8705 if (PT < MATRIX_ROW_START_CHARPOS (row)
8706 || PT > MATRIX_ROW_END_CHARPOS (row))
8707 goto try_to_scroll;
8708
8709 /* If we end up in a partially visible line, let's make it fully
8710 visible. This can be done most easily by using the existing
8711 scrolling code. */
8712 if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
8713 {
8714 temp_scroll_step = 1;
8715 goto try_to_scroll;
a2889657 8716 }
5f5c8ee5
GM
8717 else if (scroll_p)
8718 goto try_to_scroll;
8719
8720 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
8721 goto done;
a2889657 8722 }
5f5c8ee5 8723
a2889657
JB
8724 /* If current starting point was originally the beginning of a line
8725 but no longer is, find a new starting point. */
265a9e55 8726 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
8727 && !(CHARPOS (startp) <= BEGV
8728 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 8729 {
5f5c8ee5
GM
8730#if GLYPH_DEBUG
8731 debug_method_add (w, "recenter 1");
8732#endif
a2889657
JB
8733 goto recenter;
8734 }
5f5c8ee5
GM
8735
8736 /* Try scrolling with try_window_id. */
9142dd5b
GM
8737 else if (/* Windows and buffers haven't changed. */
8738 !windows_or_buffers_changed
5f5c8ee5
GM
8739 /* Window must be either use window-based redisplay or
8740 be full width. */
8741 && (FRAME_WINDOW_P (f)
c59c668a 8742 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)))
5f5c8ee5
GM
8743 && !MINI_WINDOW_P (w)
8744 /* Point is not known NOT to appear in window. */
8745 && PT >= CHARPOS (startp)
a2889657 8746 && XFASTINT (w->last_modified)
5f5c8ee5
GM
8747 /* Window is not hscrolled. */
8748 && XFASTINT (w->hscroll) == 0
8749 /* Selective display has not changed. */
8750 && !current_buffer->clip_changed
8751 /* Current matrix is up to date. */
8752 && !NILP (w->window_end_valid)
8753 /* Can't use this case if highlighting a region because
8754 a cursor movement will do more than just set the cursor. */
bd66d1ba
RS
8755 && !(!NILP (Vtransient_mark_mode)
8756 && !NILP (current_buffer->mark_active))
8757 && NILP (w->region_showing)
8f897821 8758 && NILP (Vshow_trailing_whitespace)
5f5c8ee5 8759 /* Overlay arrow position and string not changed. */
d45de95b 8760 && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
a2889657 8761 && EQ (last_arrow_string, Voverlay_arrow_string)
5f5c8ee5
GM
8762 /* Value is > 0 if update has been done, it is -1 if we
8763 know that the same window start will not work. It is 0
8764 if unsuccessful for some other reason. */
8765 && (tem = try_window_id (w)) != 0)
a2889657 8766 {
5f5c8ee5
GM
8767#if GLYPH_DEBUG
8768 debug_method_add (w, "try_window_id");
8769#endif
8770
8771 if (fonts_changed_p)
8772 goto restore_buffers;
a2889657
JB
8773 if (tem > 0)
8774 goto done;
5f5c8ee5
GM
8775 /* Otherwise try_window_id has returned -1 which means that we
8776 don't want the alternative below this comment to execute. */
a2889657 8777 }
5f5c8ee5
GM
8778 else if (CHARPOS (startp) >= BEGV
8779 && CHARPOS (startp) <= ZV
8780 && PT >= CHARPOS (startp)
8781 && (CHARPOS (startp) < ZV
e9874cee 8782 /* Avoid starting at end of buffer. */
5f5c8ee5 8783 || CHARPOS (startp) == BEGV
8850a573
RS
8784 || (XFASTINT (w->last_modified) >= MODIFF
8785 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 8786 {
5f5c8ee5
GM
8787#if GLYPH_DEBUG
8788 debug_method_add (w, "same window start");
8789#endif
8790
8791 /* Try to redisplay starting at same place as before.
8792 If point has not moved off frame, accept the results. */
8793 if (!current_matrix_up_to_date_p
8794 /* Don't use try_window_reusing_current_matrix in this case
8795 because it can have changed the buffer. */
8796 || !NILP (Vwindow_scroll_functions)
8797 || MINI_WINDOW_P (w)
8798 || !try_window_reusing_current_matrix (w))
8799 {
8800 IF_DEBUG (debug_method_add (w, "1"));
8801 try_window (window, startp);
8802 }
8803
8804 if (fonts_changed_p)
8805 goto restore_buffers;
8806
8807 if (w->cursor.vpos >= 0)
aa6d10fa 8808 {
5f5c8ee5
GM
8809 if (!just_this_one_p
8810 || current_buffer->clip_changed
9142dd5b 8811 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
8812 /* Forget any recorded base line for line number display. */
8813 w->base_line_number = Qnil;
5f5c8ee5
GM
8814
8815 make_cursor_line_fully_visible (w);
aa6d10fa
RS
8816 goto done;
8817 }
a2889657 8818 else
5f5c8ee5 8819 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
8820 }
8821
5f5c8ee5
GM
8822 try_to_scroll:
8823
c2213350 8824 XSETFASTINT (w->last_modified, 0);
8850a573 8825 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5 8826
e481f960
RS
8827 /* Redisplay the mode line. Select the buffer properly for that. */
8828 if (!update_mode_line)
8829 {
5ba50c51
RS
8830 if (!really_switched_buffer)
8831 {
8832 set_buffer_temp (old);
8833 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8834 really_switched_buffer = 1;
5ba50c51 8835 }
e481f960
RS
8836 update_mode_line = 1;
8837 w->update_mode_line = Qt;
8838 }
a2889657 8839
5f5c8ee5
GM
8840 /* Try to scroll by specified few lines. */
8841 if ((scroll_conservatively
8842 || scroll_step
8843 || temp_scroll_step
8844 || NUMBERP (current_buffer->scroll_up_aggressively)
8845 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 8846 && !current_buffer->clip_changed
5f5c8ee5
GM
8847 && CHARPOS (startp) >= BEGV
8848 && CHARPOS (startp) <= ZV)
0789adb2 8849 {
5f5c8ee5
GM
8850 /* The function returns -1 if new fonts were loaded, 1 if
8851 successful, 0 if not successful. */
8852 int rc = try_scrolling (window, just_this_one_p,
8853 scroll_conservatively,
8854 scroll_step,
8855 temp_scroll_step);
8856 if (rc > 0)
8857 goto done;
8858 else if (rc < 0)
8859 goto restore_buffers;
8860 }
f9c8af06 8861
5f5c8ee5 8862 /* Finally, just choose place to start which centers point */
5936754e 8863
5f5c8ee5 8864 recenter:
44173109 8865
5f5c8ee5
GM
8866#if GLYPH_DEBUG
8867 debug_method_add (w, "recenter");
8868#endif
0789adb2 8869
5f5c8ee5 8870 /* w->vscroll = 0; */
0789adb2 8871
5f5c8ee5
GM
8872 /* Forget any previously recorded base line for line number display. */
8873 if (!current_matrix_up_to_date_p
8874 || current_buffer->clip_changed)
8875 w->base_line_number = Qnil;
8876
8877 /* Move backward half the height of the window. */
8878 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
8879 it.current_y = it.last_visible_y;
8880 move_it_vertically_backward (&it, it.last_visible_y / 2);
8881 xassert (IT_CHARPOS (it) >= BEGV);
8882
8883 /* The function move_it_vertically_backward may move over more
8884 than the specified y-distance. If it->w is small, e.g. a
8885 mini-buffer window, we may end up in front of the window's
8886 display area. Start displaying at the start of the line
8887 containing PT in this case. */
8888 if (it.current_y <= 0)
8889 {
8890 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
8891 move_it_vertically (&it, 0);
8892 xassert (IT_CHARPOS (it) <= PT);
8893 it.current_y = 0;
0789adb2
RS
8894 }
8895
5f5c8ee5
GM
8896 it.current_x = it.hpos = 0;
8897
8898 /* Set startp here explicitly in case that helps avoid an infinite loop
8899 in case the window-scroll-functions functions get errors. */
8900 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
8901
8902 /* Run scroll hooks. */
8903 startp = run_window_scroll_functions (window, it.current.pos);
8904
8905 /* Redisplay the window. */
8906 if (!current_matrix_up_to_date_p
8907 || windows_or_buffers_changed
8908 /* Don't use try_window_reusing_current_matrix in this case
8909 because it can have changed the buffer. */
8910 || !NILP (Vwindow_scroll_functions)
8911 || !just_this_one_p
8912 || MINI_WINDOW_P (w)
8913 || !try_window_reusing_current_matrix (w))
8914 try_window (window, startp);
8915
8916 /* If new fonts have been loaded (due to fontsets), give up. We
8917 have to start a new redisplay since we need to re-adjust glyph
8918 matrices. */
8919 if (fonts_changed_p)
8920 goto restore_buffers;
8921
8922 /* If cursor did not appear assume that the middle of the window is
8923 in the first line of the window. Do it again with the next line.
8924 (Imagine a window of height 100, displaying two lines of height
8925 60. Moving back 50 from it->last_visible_y will end in the first
8926 line.) */
8927 if (w->cursor.vpos < 0)
a2889657 8928 {
5f5c8ee5
GM
8929 if (!NILP (w->window_end_valid)
8930 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 8931 {
5f5c8ee5
GM
8932 clear_glyph_matrix (w->desired_matrix);
8933 move_it_by_lines (&it, 1, 0);
8934 try_window (window, it.current.pos);
a2889657 8935 }
5f5c8ee5 8936 else if (PT < IT_CHARPOS (it))
a2889657 8937 {
5f5c8ee5
GM
8938 clear_glyph_matrix (w->desired_matrix);
8939 move_it_by_lines (&it, -1, 0);
8940 try_window (window, it.current.pos);
8941 }
8942 else
8943 {
8944 /* Not much we can do about it. */
a2889657 8945 }
a2889657 8946 }
010494d0 8947
5f5c8ee5
GM
8948 /* Consider the following case: Window starts at BEGV, there is
8949 invisible, intangible text at BEGV, so that display starts at
8950 some point START > BEGV. It can happen that we are called with
8951 PT somewhere between BEGV and START. Try to handle that case. */
8952 if (w->cursor.vpos < 0)
835766b6 8953 {
5f5c8ee5
GM
8954 struct glyph_row *row = w->current_matrix->rows;
8955 if (row->mode_line_p)
8956 ++row;
8957 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 8958 }
5f5c8ee5
GM
8959
8960 make_cursor_line_fully_visible (w);
b5174a51 8961
74d481ac
GM
8962 done:
8963
5f5c8ee5
GM
8964 SET_TEXT_POS_FROM_MARKER (startp, w->start);
8965 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
8966 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
8967 ? Qt : Qnil);
a2889657 8968
5f5c8ee5 8969 /* Display the mode line, if we must. */
e481f960 8970 if ((update_mode_line
aa6d10fa 8971 /* If window not full width, must redo its mode line
5f5c8ee5
GM
8972 if (a) the window to its side is being redone and
8973 (b) we do a frame-based redisplay. This is a consequence
8974 of how inverted lines are drawn in frame-based redisplay. */
8975 || (!just_this_one_p
8976 && !FRAME_WINDOW_P (f)
8977 && !WINDOW_FULL_WIDTH_P (w))
8978 /* Line number to display. */
155ef550 8979 || INTEGERP (w->base_line_pos)
5f5c8ee5 8980 /* Column number is displayed and different from the one displayed. */
155ef550
KH
8981 || (!NILP (w->column_number_displayed)
8982 && XFASTINT (w->column_number_displayed) != current_column ()))
5f5c8ee5
GM
8983 /* This means that the window has a mode line. */
8984 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 8985 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 8986 {
5f5c8ee5
GM
8987 display_mode_lines (w);
8988
8989 /* If mode line height has changed, arrange for a thorough
8990 immediate redisplay using the correct mode line height. */
8991 if (WINDOW_WANTS_MODELINE_P (w)
8992 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 8993 {
5f5c8ee5
GM
8994 fonts_changed_p = 1;
8995 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
8996 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 8997 }
5f5c8ee5
GM
8998
8999 /* If top line height has changed, arrange for a thorough
9000 immediate redisplay using the correct mode line height. */
045dee35
GM
9001 if (WINDOW_WANTS_HEADER_LINE_P (w)
9002 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
9003 {
9004 fonts_changed_p = 1;
045dee35
GM
9005 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
9006 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9007 }
9008
9009 if (fonts_changed_p)
9010 goto restore_buffers;
5ba50c51 9011 }
5f5c8ee5
GM
9012
9013 if (!line_number_displayed
9014 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
9015 {
9016 w->base_line_pos = Qnil;
9017 w->base_line_number = Qnil;
9018 }
a2889657 9019
5f5c8ee5
GM
9020 finish_menu_bars:
9021
7ce2c095 9022 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 9023 if (update_mode_line
5f5c8ee5
GM
9024 && EQ (FRAME_SELECTED_WINDOW (f), window))
9025 {
9026 int redisplay_menu_p = 0;
9027
9028 if (FRAME_WINDOW_P (f))
9029 {
dc937613 9030#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
5f5c8ee5 9031 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 9032#else
5f5c8ee5 9033 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 9034#endif
5f5c8ee5
GM
9035 }
9036 else
9037 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
9038
9039 if (redisplay_menu_p)
9040 display_menu_bar (w);
9041
9042#ifdef HAVE_WINDOW_SYSTEM
e037b9ec
GM
9043 if (WINDOWP (f->tool_bar_window)
9044 && (FRAME_TOOL_BAR_LINES (f) > 0
9045 || auto_resize_tool_bars_p))
9046 redisplay_tool_bar (f);
5f5c8ee5
GM
9047#endif
9048 }
7ce2c095 9049
88f22aff 9050 finish_scroll_bars:
5f5c8ee5 9051
88f22aff 9052 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 9053 {
b1d1124b 9054 int start, end, whole;
30c566e4 9055
b1d1124b 9056 /* Calculate the start and end positions for the current window.
3505ea70
JB
9057 At some point, it would be nice to choose between scrollbars
9058 which reflect the whole buffer size, with special markers
9059 indicating narrowing, and scrollbars which reflect only the
9060 visible region.
9061
5f5c8ee5 9062 Note that mini-buffers sometimes aren't displaying any text. */
c6e89d6c 9063 if (!MINI_WINDOW_P (w)
5f5c8ee5 9064 || (w == XWINDOW (minibuf_window)
c6e89d6c 9065 && NILP (echo_area_buffer[0])))
b1d1124b 9066 {
8a9311d7 9067 whole = ZV - BEGV;
4d641a15 9068 start = marker_position (w->start) - BEGV;
b1d1124b
JB
9069 /* I don't think this is guaranteed to be right. For the
9070 moment, we'll pretend it is. */
5f5c8ee5 9071 end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
3505ea70 9072
5f5c8ee5
GM
9073 if (end < start)
9074 end = start;
9075 if (whole < (end - start))
9076 whole = end - start;
b1d1124b
JB
9077 }
9078 else
9079 start = end = whole = 0;
30c566e4 9080
88f22aff 9081 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 9082 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 9083
5f5c8ee5
GM
9084 /* Note that we actually used the scroll bar attached to this
9085 window, so it shouldn't be deleted at the end of redisplay. */
88f22aff 9086 (*redeem_scroll_bar_hook) (w);
30c566e4 9087 }
b1d1124b 9088
5f5c8ee5
GM
9089 restore_buffers:
9090
9091 /* Restore current_buffer and value of point in it. */
9092 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
5ba50c51 9093 if (really_switched_buffer)
f72df6ac 9094 set_buffer_internal_1 (old);
e481f960
RS
9095 else
9096 set_buffer_temp (old);
5f5c8ee5 9097 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
9098
9099 unbind_to (count, Qnil);
a2889657 9100}
a2889657 9101
5f5c8ee5
GM
9102
9103/* Build the complete desired matrix of WINDOW with a window start
9104 buffer position POS. Value is non-zero if successful. It is zero
9105 if fonts were loaded during redisplay which makes re-adjusting
9106 glyph matrices necessary. */
9107
9108int
a2889657
JB
9109try_window (window, pos)
9110 Lisp_Object window;
5f5c8ee5
GM
9111 struct text_pos pos;
9112{
9113 struct window *w = XWINDOW (window);
9114 struct it it;
9115 struct glyph_row *last_text_row = NULL;
9cbab4ff 9116
5f5c8ee5
GM
9117 /* Make POS the new window start. */
9118 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 9119
5f5c8ee5
GM
9120 /* Mark cursor position as unknown. No overlay arrow seen. */
9121 w->cursor.vpos = -1;
a2889657 9122 overlay_arrow_seen = 0;
642eefc6 9123
5f5c8ee5
GM
9124 /* Initialize iterator and info to start at POS. */
9125 start_display (&it, w, pos);
a2889657 9126
5f5c8ee5
GM
9127 /* Display all lines of W. */
9128 while (it.current_y < it.last_visible_y)
9129 {
9130 if (display_line (&it))
9131 last_text_row = it.glyph_row - 1;
9132 if (fonts_changed_p)
9133 return 0;
9134 }
a2889657 9135
5f5c8ee5
GM
9136 /* If bottom moved off end of frame, change mode line percentage. */
9137 if (XFASTINT (w->window_end_pos) <= 0
9138 && Z != IT_CHARPOS (it))
a2889657
JB
9139 w->update_mode_line = Qt;
9140
5f5c8ee5
GM
9141 /* Set window_end_pos to the offset of the last character displayed
9142 on the window from the end of current_buffer. Set
9143 window_end_vpos to its row number. */
9144 if (last_text_row)
9145 {
9146 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
9147 w->window_end_bytepos
9148 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9149 XSETFASTINT (w->window_end_pos,
9150 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9151 XSETFASTINT (w->window_end_vpos,
9152 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9153 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
9154 ->displays_text_p);
9155 }
9156 else
9157 {
9158 w->window_end_bytepos = 0;
9159 XSETFASTINT (w->window_end_pos, 0);
9160 XSETFASTINT (w->window_end_vpos, 0);
9161 }
9162
a2889657
JB
9163 /* But that is not valid info until redisplay finishes. */
9164 w->window_end_valid = Qnil;
5f5c8ee5 9165 return 1;
a2889657 9166}
5f5c8ee5
GM
9167
9168
a2889657 9169\f
5f5c8ee5
GM
9170/************************************************************************
9171 Window redisplay reusing current matrix when buffer has not changed
9172 ************************************************************************/
9173
9174/* Try redisplay of window W showing an unchanged buffer with a
9175 different window start than the last time it was displayed by
9176 reusing its current matrix. Value is non-zero if successful.
9177 W->start is the new window start. */
a2889657
JB
9178
9179static int
5f5c8ee5
GM
9180try_window_reusing_current_matrix (w)
9181 struct window *w;
a2889657 9182{
5f5c8ee5
GM
9183 struct frame *f = XFRAME (w->frame);
9184 struct glyph_row *row, *bottom_row;
9185 struct it it;
9186 struct run run;
9187 struct text_pos start, new_start;
9188 int nrows_scrolled, i;
9189 struct glyph_row *last_text_row;
9190 struct glyph_row *last_reused_text_row;
9191 struct glyph_row *start_row;
9192 int start_vpos, min_y, max_y;
9193
9194 /* Right now this function doesn't handle terminal frames. */
9195 if (!FRAME_WINDOW_P (f))
9196 return 0;
a2889657 9197
5f5c8ee5
GM
9198 /* Can't do this if region may have changed. */
9199 if ((!NILP (Vtransient_mark_mode)
9200 && !NILP (current_buffer->mark_active))
8f897821
GM
9201 || !NILP (w->region_showing)
9202 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 9203 return 0;
a2889657 9204
5f5c8ee5 9205 /* If top-line visibility has changed, give up. */
045dee35
GM
9206 if (WINDOW_WANTS_HEADER_LINE_P (w)
9207 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
9208 return 0;
9209
9210 /* Give up if old or new display is scrolled vertically. We could
9211 make this function handle this, but right now it doesn't. */
9212 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9213 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
9214 return 0;
9215
9216 /* The variable new_start now holds the new window start. The old
9217 start `start' can be determined from the current matrix. */
9218 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
9219 start = start_row->start.pos;
9220 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 9221
5f5c8ee5
GM
9222 /* Clear the desired matrix for the display below. */
9223 clear_glyph_matrix (w->desired_matrix);
9224
9225 if (CHARPOS (new_start) <= CHARPOS (start))
9226 {
9227 int first_row_y;
9228
9229 IF_DEBUG (debug_method_add (w, "twu1"));
9230
9231 /* Display up to a row that can be reused. The variable
9232 last_text_row is set to the last row displayed that displays
9233 text. */
9234 start_display (&it, w, new_start);
9235 first_row_y = it.current_y;
9236 w->cursor.vpos = -1;
9237 last_text_row = last_reused_text_row = NULL;
9238 while (it.current_y < it.last_visible_y
9239 && IT_CHARPOS (it) < CHARPOS (start)
9240 && !fonts_changed_p)
9241 if (display_line (&it))
9242 last_text_row = it.glyph_row - 1;
9243
9244 /* A value of current_y < last_visible_y means that we stopped
9245 at the previous window start, which in turn means that we
9246 have at least one reusable row. */
9247 if (it.current_y < it.last_visible_y)
a2889657 9248 {
5f5c8ee5
GM
9249 nrows_scrolled = it.vpos;
9250
9251 /* Find PT if not already found in the lines displayed. */
9252 if (w->cursor.vpos < 0)
a2889657 9253 {
5f5c8ee5
GM
9254 int dy = it.current_y - first_row_y;
9255
9256 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9257 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9258 {
9259 if (PT >= MATRIX_ROW_START_CHARPOS (row)
9260 && PT < MATRIX_ROW_END_CHARPOS (row))
9261 {
9262 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
9263 dy, nrows_scrolled);
9264 break;
9265 }
9266
9267 if (MATRIX_ROW_BOTTOM_Y (row) + dy >= it.last_visible_y)
9268 break;
9269
9270 ++row;
9271 }
9272
9273 /* Give up if point was not found. This shouldn't
9274 happen often; not more often than with try_window
9275 itself. */
9276 if (w->cursor.vpos < 0)
9277 {
9278 clear_glyph_matrix (w->desired_matrix);
9279 return 0;
9280 }
a2889657 9281 }
5f5c8ee5
GM
9282
9283 /* Scroll the display. Do it before the current matrix is
9284 changed. The problem here is that update has not yet
9285 run, i.e. part of the current matrix is not up to date.
9286 scroll_run_hook will clear the cursor, and use the
9287 current matrix to get the height of the row the cursor is
9288 in. */
9289 run.current_y = first_row_y;
9290 run.desired_y = it.current_y;
9291 run.height = it.last_visible_y - it.current_y;
9292 if (run.height > 0)
a2889657 9293 {
5f5c8ee5
GM
9294 update_begin (f);
9295 rif->update_window_begin_hook (w);
9296 rif->scroll_run_hook (w, &run);
9297 rif->update_window_end_hook (w, 0);
9298 update_end (f);
a2889657 9299 }
5f5c8ee5
GM
9300
9301 /* Shift current matrix down by nrows_scrolled lines. */
9302 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9303 rotate_matrix (w->current_matrix,
9304 start_vpos,
9305 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
9306 nrows_scrolled);
9307
9308 /* Disable lines not reused. */
9309 for (i = 0; i < it.vpos; ++i)
9310 MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
9311
9312 /* Re-compute Y positions. */
9313 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix) + nrows_scrolled;
045dee35 9314 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9315 max_y = it.last_visible_y;
9316 while (row < bottom_row)
d2f84654 9317 {
5f5c8ee5
GM
9318 row->y = it.current_y;
9319
9320 if (row->y < min_y)
9321 row->visible_height = row->height - (min_y - row->y);
9322 else if (row->y + row->height > max_y)
9323 row->visible_height
9324 = row->height - (row->y + row->height - max_y);
9325 else
9326 row->visible_height = row->height;
9327
9328 it.current_y += row->height;
9329 ++it.vpos;
9330
9331 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9332 last_reused_text_row = row;
9333 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
9334 break;
9335 ++row;
d2f84654 9336 }
a2889657 9337 }
5f5c8ee5
GM
9338
9339 /* Update window_end_pos etc.; last_reused_text_row is the last
9340 reused row from the current matrix containing text, if any.
9341 The value of last_text_row is the last displayed line
9342 containing text. */
9343 if (last_reused_text_row)
a2889657 9344 {
5f5c8ee5
GM
9345 w->window_end_bytepos
9346 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
9347 XSETFASTINT (w->window_end_pos,
9348 Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
9349 XSETFASTINT (w->window_end_vpos,
9350 MATRIX_ROW_VPOS (last_reused_text_row,
9351 w->current_matrix));
a2889657 9352 }
5f5c8ee5
GM
9353 else if (last_text_row)
9354 {
9355 w->window_end_bytepos
9356 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9357 XSETFASTINT (w->window_end_pos,
9358 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9359 XSETFASTINT (w->window_end_vpos,
9360 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9361 }
9362 else
9363 {
9364 /* This window must be completely empty. */
9365 w->window_end_bytepos = 0;
9366 XSETFASTINT (w->window_end_pos, 0);
9367 XSETFASTINT (w->window_end_vpos, 0);
9368 }
9369 w->window_end_valid = Qnil;
a2889657 9370
5f5c8ee5
GM
9371 /* Update hint: don't try scrolling again in update_window. */
9372 w->desired_matrix->no_scrolling_p = 1;
9373
9374#if GLYPH_DEBUG
9375 debug_method_add (w, "try_window_reusing_current_matrix 1");
9376#endif
9377 return 1;
a2889657 9378 }
5f5c8ee5
GM
9379 else if (CHARPOS (new_start) > CHARPOS (start))
9380 {
9381 struct glyph_row *pt_row, *row;
9382 struct glyph_row *first_reusable_row;
9383 struct glyph_row *first_row_to_display;
9384 int dy;
9385 int yb = window_text_bottom_y (w);
9386
9387 IF_DEBUG (debug_method_add (w, "twu2"));
9388
9389 /* Find the row starting at new_start, if there is one. Don't
9390 reuse a partially visible line at the end. */
9391 first_reusable_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9392 while (first_reusable_row->enabled_p
9393 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
9394 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9395 < CHARPOS (new_start)))
9396 ++first_reusable_row;
9397
9398 /* Give up if there is no row to reuse. */
9399 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
9400 || !first_reusable_row->enabled_p
9401 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9402 != CHARPOS (new_start)))
5f5c8ee5
GM
9403 return 0;
9404
5f5c8ee5
GM
9405 /* We can reuse fully visible rows beginning with
9406 first_reusable_row to the end of the window. Set
9407 first_row_to_display to the first row that cannot be reused.
9408 Set pt_row to the row containing point, if there is any. */
9409 first_row_to_display = first_reusable_row;
9410 pt_row = NULL;
9411 while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb)
9412 {
9413 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
9414 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
9415 pt_row = first_row_to_display;
a2889657 9416
5f5c8ee5
GM
9417 ++first_row_to_display;
9418 }
a2889657 9419
5f5c8ee5
GM
9420 /* Start displaying at the start of first_row_to_display. */
9421 xassert (first_row_to_display->y < yb);
9422 init_to_row_start (&it, w, first_row_to_display);
9423 nrows_scrolled = MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix);
9424 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
9425 - nrows_scrolled);
9426 it.current_y = first_row_to_display->y - first_reusable_row->y;
9427
9428 /* Display lines beginning with first_row_to_display in the
9429 desired matrix. Set last_text_row to the last row displayed
9430 that displays text. */
9431 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
9432 if (pt_row == NULL)
9433 w->cursor.vpos = -1;
9434 last_text_row = NULL;
9435 while (it.current_y < it.last_visible_y && !fonts_changed_p)
9436 if (display_line (&it))
9437 last_text_row = it.glyph_row - 1;
9438
9439 /* Give up If point isn't in a row displayed or reused. */
9440 if (w->cursor.vpos < 0)
9441 {
9442 clear_glyph_matrix (w->desired_matrix);
9443 return 0;
9444 }
12adba34 9445
5f5c8ee5
GM
9446 /* If point is in a reused row, adjust y and vpos of the cursor
9447 position. */
9448 if (pt_row)
9449 {
9450 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
9451 w->current_matrix);
9452 w->cursor.y -= first_reusable_row->y;
a2889657
JB
9453 }
9454
5f5c8ee5
GM
9455 /* Scroll the display. */
9456 run.current_y = first_reusable_row->y;
045dee35 9457 run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9458 run.height = it.last_visible_y - run.current_y;
9459 if (run.height)
9460 {
9461 struct frame *f = XFRAME (WINDOW_FRAME (w));
9462 update_begin (f);
9463 rif->update_window_begin_hook (w);
9464 rif->scroll_run_hook (w, &run);
9465 rif->update_window_end_hook (w, 0);
9466 update_end (f);
9467 }
a2889657 9468
5f5c8ee5
GM
9469 /* Adjust Y positions of reused rows. */
9470 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9471 row = first_reusable_row;
9472 dy = first_reusable_row->y;
045dee35 9473 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9474 max_y = it.last_visible_y;
9475 while (row < first_row_to_display)
9476 {
9477 row->y -= dy;
9478 if (row->y < min_y)
9479 row->visible_height = row->height - (min_y - row->y);
9480 else if (row->y + row->height > max_y)
9481 row->visible_height
9482 = row->height - (row->y + row->height - max_y);
9483 else
9484 row->visible_height = row->height;
9485 ++row;
9486 }
a2889657 9487
5f5c8ee5
GM
9488 /* Disable rows not reused. */
9489 while (row < bottom_row)
9490 {
9491 row->enabled_p = 0;
9492 ++row;
9493 }
9494
9495 /* Scroll the current matrix. */
9496 xassert (nrows_scrolled > 0);
9497 rotate_matrix (w->current_matrix,
9498 start_vpos,
9499 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
9500 -nrows_scrolled);
9501
9502 /* Adjust window end. A null value of last_text_row means that
9503 the window end is in reused rows which in turn means that
9504 only its vpos can have changed. */
9505 if (last_text_row)
9506 {
9507 w->window_end_bytepos
9508 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9509 XSETFASTINT (w->window_end_pos,
9510 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9511 XSETFASTINT (w->window_end_vpos,
9512 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9513 }
9514 else
a2889657 9515 {
e8e536a9 9516 XSETFASTINT (w->window_end_vpos,
5f5c8ee5 9517 XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 9518 }
5f5c8ee5
GM
9519
9520 w->window_end_valid = Qnil;
9521 w->desired_matrix->no_scrolling_p = 1;
9522
9523#if GLYPH_DEBUG
9524 debug_method_add (w, "try_window_reusing_current_matrix 2");
9525#endif
9526 return 1;
a2889657 9527 }
5f5c8ee5
GM
9528
9529 return 0;
9530}
a2889657 9531
a2889657 9532
5f5c8ee5
GM
9533\f
9534/************************************************************************
9535 Window redisplay reusing current matrix when buffer has changed
9536 ************************************************************************/
9537
9538static struct glyph_row *get_last_unchanged_at_beg_row P_ ((struct window *));
9539static struct glyph_row *get_first_unchanged_at_end_row P_ ((struct window *,
9540 int *, int *));
9541static struct glyph_row *
9542find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
9543 struct glyph_row *));
9544
9545
9546/* Return the last row in MATRIX displaying text. If row START is
9547 non-null, start searching with that row. IT gives the dimensions
9548 of the display. Value is null if matrix is empty; otherwise it is
9549 a pointer to the row found. */
9550
9551static struct glyph_row *
9552find_last_row_displaying_text (matrix, it, start)
9553 struct glyph_matrix *matrix;
9554 struct it *it;
9555 struct glyph_row *start;
9556{
9557 struct glyph_row *row, *row_found;
9558
9559 /* Set row_found to the last row in IT->w's current matrix
9560 displaying text. The loop looks funny but think of partially
9561 visible lines. */
9562 row_found = NULL;
9563 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
9564 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9565 {
9566 xassert (row->enabled_p);
9567 row_found = row;
9568 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
9569 break;
9570 ++row;
a2889657 9571 }
5f5c8ee5
GM
9572
9573 return row_found;
9574}
9575
a2889657 9576
5f5c8ee5
GM
9577/* Return the last row in the current matrix of W that is not affected
9578 by changes at the start of current_buffer that occurred since the
9579 last time W was redisplayed. Value is null if no such row exists.
a2889657 9580
5f5c8ee5
GM
9581 The global variable beg_unchanged has to contain the number of
9582 bytes unchanged at the start of current_buffer. BEG +
9583 beg_unchanged is the buffer position of the first changed byte in
9584 current_buffer. Characters at positions < BEG + beg_unchanged are
9585 at the same buffer positions as they were when the current matrix
9586 was built. */
9587
9588static struct glyph_row *
9589get_last_unchanged_at_beg_row (w)
9590 struct window *w;
9591{
9142dd5b 9592 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
9593 struct glyph_row *row;
9594 struct glyph_row *row_found = NULL;
9595 int yb = window_text_bottom_y (w);
9596
9597 /* Find the last row displaying unchanged text. */
9598 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9599 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
9600 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 9601 {
5f5c8ee5
GM
9602 if (/* If row ends before first_changed_pos, it is unchanged,
9603 except in some case. */
9604 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
9605 /* When row ends in ZV and we write at ZV it is not
9606 unchanged. */
9607 && !row->ends_at_zv_p
9608 /* When first_changed_pos is the end of a continued line,
9609 row is not unchanged because it may be no longer
9610 continued. */
9611 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
9612 && row->continued_p))
9613 row_found = row;
9614
9615 /* Stop if last visible row. */
9616 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
9617 break;
9618
9619 ++row;
a2889657
JB
9620 }
9621
5f5c8ee5 9622 return row_found;
a2889657 9623}
5f5c8ee5
GM
9624
9625
9626/* Find the first glyph row in the current matrix of W that is not
9627 affected by changes at the end of current_buffer since the last
9628 time the window was redisplayed. Return in *DELTA the number of
c59c668a
GM
9629 chars by which buffer positions in unchanged text at the end of
9630 current_buffer must be adjusted. Return in *DELTA_BYTES the
9631 corresponding number of bytes. Value is null if no such row
9632 exists, i.e. all rows are affected by changes. */
5f5c8ee5
GM
9633
9634static struct glyph_row *
9635get_first_unchanged_at_end_row (w, delta, delta_bytes)
9636 struct window *w;
9637 int *delta, *delta_bytes;
a2889657 9638{
5f5c8ee5
GM
9639 struct glyph_row *row;
9640 struct glyph_row *row_found = NULL;
c581d710 9641
5f5c8ee5 9642 *delta = *delta_bytes = 0;
b2a76982 9643
5f5c8ee5
GM
9644 /* A value of window_end_pos >= end_unchanged means that the window
9645 end is in the range of changed text. If so, there is no
9646 unchanged row at the end of W's current matrix. */
9647 xassert (!NILP (w->window_end_valid));
9142dd5b 9648 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
9649 return NULL;
9650
9651 /* Set row to the last row in W's current matrix displaying text. */
9652 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
9653
5f5c8ee5
GM
9654 /* If matrix is entirely empty, no unchanged row exists. */
9655 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9656 {
9657 /* The value of row is the last glyph row in the matrix having a
9658 meaningful buffer position in it. The end position of row
9659 corresponds to window_end_pos. This allows us to translate
9660 buffer positions in the current matrix to current buffer
9661 positions for characters not in changed text. */
9662 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
9663 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
9664 int last_unchanged_pos, last_unchanged_pos_old;
9665 struct glyph_row *first_text_row
9666 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9667
9668 *delta = Z - Z_old;
9669 *delta_bytes = Z_BYTE - Z_BYTE_old;
9670
9671 /* Set last_unchanged_pos to the buffer position of the last
9672 character in the buffer that has not been changed. Z is the
9673 index + 1 of the last byte in current_buffer, i.e. by
9674 subtracting end_unchanged we get the index of the last
9675 unchanged character, and we have to add BEG to get its buffer
9676 position. */
9142dd5b 9677 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5
GM
9678 last_unchanged_pos_old = last_unchanged_pos - *delta;
9679
9680 /* Search backward from ROW for a row displaying a line that
9681 starts at a minimum position >= last_unchanged_pos_old. */
9682 while (row >= first_text_row)
9683 {
9684 xassert (row->enabled_p);
9685 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row));
9686
9687 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
9688 row_found = row;
9689 --row;
9690 }
9691 }
9692
9693 xassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
9694 return row_found;
c581d710
RS
9695}
9696
c581d710 9697
5f5c8ee5
GM
9698/* Make sure that glyph rows in the current matrix of window W
9699 reference the same glyph memory as corresponding rows in the
9700 frame's frame matrix. This function is called after scrolling W's
9701 current matrix on a terminal frame in try_window_id and
9702 try_window_reusing_current_matrix. */
9703
9704static void
9705sync_frame_with_window_matrix_rows (w)
9706 struct window *w;
c581d710 9707{
5f5c8ee5
GM
9708 struct frame *f = XFRAME (w->frame);
9709 struct glyph_row *window_row, *window_row_end, *frame_row;
9710
9711 /* Preconditions: W must be a leaf window and full-width. Its frame
9712 must have a frame matrix. */
9713 xassert (NILP (w->hchild) && NILP (w->vchild));
9714 xassert (WINDOW_FULL_WIDTH_P (w));
9715 xassert (!FRAME_WINDOW_P (f));
9716
9717 /* If W is a full-width window, glyph pointers in W's current matrix
9718 have, by definition, to be the same as glyph pointers in the
9719 corresponding frame matrix. */
9720 window_row = w->current_matrix->rows;
9721 window_row_end = window_row + w->current_matrix->nrows;
9722 frame_row = f->current_matrix->rows + XFASTINT (w->top);
9723 while (window_row < window_row_end)
659a218f 9724 {
5f5c8ee5 9725 int area;
f002db93 9726
5f5c8ee5
GM
9727 for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
9728 frame_row->glyphs[area] = window_row->glyphs[area];
f002db93
GM
9729
9730 /* Disable frame rows whose corresponding window rows have
9731 been disabled in try_window_id. */
9732 if (!window_row->enabled_p)
9733 frame_row->enabled_p = 0;
9734
5f5c8ee5 9735 ++window_row, ++frame_row;
659a218f 9736 }
a2889657 9737}
5f5c8ee5
GM
9738
9739
e037b9ec
GM
9740/* Find the glyph row in window W containing CHARPOS. Consider all
9741 rows between START and END (not inclusive). END null means search
9742 all rows to the end of the display area of W. Value is the row
9743 containing CHARPOS or null. */
9744
9745static struct glyph_row *
9746row_containing_pos (w, charpos, start, end)
9747 struct window *w;
9748 int charpos;
9749 struct glyph_row *start, *end;
9750{
9751 struct glyph_row *row = start;
9752 int last_y;
9753
9754 /* If we happen to start on a header-line, skip that. */
9755 if (row->mode_line_p)
9756 ++row;
9757
9758 if ((end && row >= end) || !row->enabled_p)
9759 return NULL;
9760
9761 last_y = window_text_bottom_y (w);
9762
9763 while ((end == NULL || row < end)
9764 && (MATRIX_ROW_END_CHARPOS (row) < charpos
9765 /* The end position of a row equals the start
9766 position of the next row. If CHARPOS is there, we
9767 would rather display it in the next line, except
9768 when this line ends in ZV. */
9769 || (MATRIX_ROW_END_CHARPOS (row) == charpos
9770 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
9771 || !row->ends_at_zv_p)))
9772 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
9773 ++row;
9774
9775 /* Give up if CHARPOS not found. */
9776 if ((end && row >= end)
9777 || charpos < MATRIX_ROW_START_CHARPOS (row)
9778 || charpos > MATRIX_ROW_END_CHARPOS (row))
9779 row = NULL;
9780
9781 return row;
9782}
9783
9784
5f5c8ee5
GM
9785/* Try to redisplay window W by reusing its existing display. W's
9786 current matrix must be up to date when this function is called,
9787 i.e. window_end_valid must not be nil.
9788
9789 Value is
9790
9791 1 if display has been updated
9792 0 if otherwise unsuccessful
9793 -1 if redisplay with same window start is known not to succeed
9794
9795 The following steps are performed:
9796
9797 1. Find the last row in the current matrix of W that is not
9798 affected by changes at the start of current_buffer. If no such row
9799 is found, give up.
9800
9801 2. Find the first row in W's current matrix that is not affected by
9802 changes at the end of current_buffer. Maybe there is no such row.
9803
9804 3. Display lines beginning with the row + 1 found in step 1 to the
9805 row found in step 2 or, if step 2 didn't find a row, to the end of
9806 the window.
9807
9808 4. If cursor is not known to appear on the window, give up.
9809
9810 5. If display stopped at the row found in step 2, scroll the
9811 display and current matrix as needed.
9812
9813 6. Maybe display some lines at the end of W, if we must. This can
9814 happen under various circumstances, like a partially visible line
9815 becoming fully visible, or because newly displayed lines are displayed
9816 in smaller font sizes.
9817
9818 7. Update W's window end information. */
9819
9820 /* Check that window end is what we expect it to be. */
12adba34
RS
9821
9822static int
5f5c8ee5 9823try_window_id (w)
12adba34 9824 struct window *w;
12adba34 9825{
5f5c8ee5
GM
9826 struct frame *f = XFRAME (w->frame);
9827 struct glyph_matrix *current_matrix = w->current_matrix;
9828 struct glyph_matrix *desired_matrix = w->desired_matrix;
9829 struct glyph_row *last_unchanged_at_beg_row;
9830 struct glyph_row *first_unchanged_at_end_row;
9831 struct glyph_row *row;
9832 struct glyph_row *bottom_row;
9833 int bottom_vpos;
9834 struct it it;
9835 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
9836 struct text_pos start_pos;
9837 struct run run;
9838 int first_unchanged_at_end_vpos = 0;
9839 struct glyph_row *last_text_row, *last_text_row_at_end;
9840 struct text_pos start;
9841
9842 SET_TEXT_POS_FROM_MARKER (start, w->start);
9843
9844 /* Check pre-conditions. Window end must be valid, otherwise
9845 the current matrix would not be up to date. */
9846 xassert (!NILP (w->window_end_valid));
9847 xassert (FRAME_WINDOW_P (XFRAME (w->frame))
9848 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)));
9849
9850 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
9851 only if buffer has really changed. The reason is that the gap is
9852 initially at Z for freshly visited files. The code below would
9853 set end_unchanged to 0 in that case. */
9854 if (MODIFF > SAVE_MODIFF)
9855 {
9142dd5b
GM
9856 if (GPT - BEG < BEG_UNCHANGED)
9857 BEG_UNCHANGED = GPT - BEG;
9858 if (Z - GPT < END_UNCHANGED)
9859 END_UNCHANGED = Z - GPT;
5f5c8ee5
GM
9860 }
9861
9862 /* If window starts after a line end, and the last change is in
9863 front of that newline, then changes don't affect the display.
9864 This case happens with stealth-fontification. */
9865 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
9866 if (CHARPOS (start) > BEGV
9142dd5b 9867 && Z - END_UNCHANGED < CHARPOS (start) - 1
5f5c8ee5
GM
9868 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
9869 && PT < MATRIX_ROW_END_CHARPOS (row))
9870 {
9871 /* We have to update window end positions because the buffer's
9872 size has changed. */
9873 w->window_end_pos
9874 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
9875 w->window_end_bytepos
9876 = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
9877 return 1;
9878 }
9879
9880 /* Return quickly if changes are all below what is displayed in the
9881 window, and if PT is in the window. */
9142dd5b 9882 if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row)
5f5c8ee5
GM
9883 && PT < MATRIX_ROW_END_CHARPOS (row))
9884 {
9885 /* We have to update window end positions because the buffer's
9886 size has changed. */
9887 w->window_end_pos
9888 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
9889 w->window_end_bytepos
9890 = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
9891 return 1;
9892 }
9893
9894 /* Check that window start agrees with the start of the first glyph
9895 row in its current matrix. Check this after we know the window
9896 start is not in changed text, otherwise positions would not be
9897 comparable. */
9898 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9899 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
9900 return 0;
9901
5f5c8ee5
GM
9902 /* Compute the position at which we have to start displaying new
9903 lines. Some of the lines at the top of the window might be
9904 reusable because they are not displaying changed text. Find the
9905 last row in W's current matrix not affected by changes at the
9906 start of current_buffer. Value is null if changes start in the
9907 first line of window. */
9908 last_unchanged_at_beg_row = get_last_unchanged_at_beg_row (w);
9909 if (last_unchanged_at_beg_row)
9910 {
9911 init_to_row_end (&it, w, last_unchanged_at_beg_row);
9912 start_pos = it.current.pos;
9913
9914 /* Start displaying new lines in the desired matrix at the same
9915 vpos we would use in the current matrix, i.e. below
9916 last_unchanged_at_beg_row. */
9917 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
9918 current_matrix);
9919 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
9920 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
9921
9922 xassert (it.hpos == 0 && it.current_x == 0);
9923 }
9924 else
9925 {
9926 /* There are no reusable lines at the start of the window.
9927 Start displaying in the first line. */
9928 start_display (&it, w, start);
9929 start_pos = it.current.pos;
9930 }
9931
5f5c8ee5
GM
9932 /* Find the first row that is not affected by changes at the end of
9933 the buffer. Value will be null if there is no unchanged row, in
9934 which case we must redisplay to the end of the window. delta
9935 will be set to the value by which buffer positions beginning with
9936 first_unchanged_at_end_row have to be adjusted due to text
9937 changes. */
9938 first_unchanged_at_end_row
9939 = get_first_unchanged_at_end_row (w, &delta, &delta_bytes);
9940 IF_DEBUG (debug_delta = delta);
9941 IF_DEBUG (debug_delta_bytes = delta_bytes);
9942
9943 /* Set stop_pos to the buffer position up to which we will have to
9944 display new lines. If first_unchanged_at_end_row != NULL, this
9945 is the buffer position of the start of the line displayed in that
9946 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
9947 that we don't stop at a buffer position. */
9948 stop_pos = 0;
9949 if (first_unchanged_at_end_row)
9950 {
9951 xassert (last_unchanged_at_beg_row == NULL
9952 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
9953
9954 /* If this is a continuation line, move forward to the next one
9955 that isn't. Changes in lines above affect this line.
9956 Caution: this may move first_unchanged_at_end_row to a row
9957 not displaying text. */
9958 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
9959 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
9960 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
9961 < it.last_visible_y))
9962 ++first_unchanged_at_end_row;
9963
9964 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
9965 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
9966 >= it.last_visible_y))
9967 first_unchanged_at_end_row = NULL;
9968 else
9969 {
9970 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
9971 + delta);
9972 first_unchanged_at_end_vpos
9973 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 9974 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
9975 }
9976 }
9977 else if (last_unchanged_at_beg_row == NULL)
9978 return 0;
9979
9980
9981#if GLYPH_DEBUG
9982
9983 /* Either there is no unchanged row at the end, or the one we have
9984 now displays text. This is a necessary condition for the window
9985 end pos calculation at the end of this function. */
9986 xassert (first_unchanged_at_end_row == NULL
9987 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
9988
9989 debug_last_unchanged_at_beg_vpos
9990 = (last_unchanged_at_beg_row
9991 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
9992 : -1);
9993 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
9994
9995#endif /* GLYPH_DEBUG != 0 */
9996
9997
9998 /* Display new lines. Set last_text_row to the last new line
9999 displayed which has text on it, i.e. might end up as being the
10000 line where the window_end_vpos is. */
10001 w->cursor.vpos = -1;
10002 last_text_row = NULL;
10003 overlay_arrow_seen = 0;
10004 while (it.current_y < it.last_visible_y
10005 && !fonts_changed_p
10006 && (first_unchanged_at_end_row == NULL
10007 || IT_CHARPOS (it) < stop_pos))
10008 {
10009 if (display_line (&it))
10010 last_text_row = it.glyph_row - 1;
10011 }
10012
10013 if (fonts_changed_p)
10014 return -1;
10015
10016
10017 /* Compute differences in buffer positions, y-positions etc. for
10018 lines reused at the bottom of the window. Compute what we can
10019 scroll. */
ca42b2e8
GM
10020 if (first_unchanged_at_end_row
10021 /* No lines reused because we displayed everything up to the
10022 bottom of the window. */
10023 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
10024 {
10025 dvpos = (it.vpos
10026 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
10027 current_matrix));
10028 dy = it.current_y - first_unchanged_at_end_row->y;
10029 run.current_y = first_unchanged_at_end_row->y;
10030 run.desired_y = run.current_y + dy;
10031 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
10032 }
10033 else
ca42b2e8
GM
10034 {
10035 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
10036 first_unchanged_at_end_row = NULL;
10037 }
5f5c8ee5
GM
10038 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
10039
8f8ba186 10040
5f5c8ee5
GM
10041 /* Find the cursor if not already found. We have to decide whether
10042 PT will appear on this window (it sometimes doesn't, but this is
10043 not a very frequent case.) This decision has to be made before
10044 the current matrix is altered. A value of cursor.vpos < 0 means
10045 that PT is either in one of the lines beginning at
10046 first_unchanged_at_end_row or below the window. Don't care for
10047 lines that might be displayed later at the window end; as
10048 mentioned, this is not a frequent case. */
10049 if (w->cursor.vpos < 0)
10050 {
5f5c8ee5
GM
10051 /* Cursor in unchanged rows at the top? */
10052 if (PT < CHARPOS (start_pos)
10053 && last_unchanged_at_beg_row)
10054 {
e037b9ec
GM
10055 row = row_containing_pos (w, PT,
10056 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
10057 last_unchanged_at_beg_row + 1);
10058 xassert (row && row <= last_unchanged_at_beg_row);
5f5c8ee5
GM
10059 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
10060 }
10061
10062 /* Start from first_unchanged_at_end_row looking for PT. */
10063 else if (first_unchanged_at_end_row)
10064 {
e037b9ec
GM
10065 row = row_containing_pos (w, PT - delta,
10066 first_unchanged_at_end_row, NULL);
10067 if (row)
468155d7
GM
10068 set_cursor_from_row (w, row, w->current_matrix, delta,
10069 delta_bytes, dy, dvpos);
5f5c8ee5
GM
10070 }
10071
10072 /* Give up if cursor was not found. */
10073 if (w->cursor.vpos < 0)
10074 {
10075 clear_glyph_matrix (w->desired_matrix);
10076 return -1;
10077 }
10078 }
10079
10080 /* Don't let the cursor end in the scroll margins. */
10081 {
10082 int this_scroll_margin, cursor_height;
10083
10084 this_scroll_margin = max (0, scroll_margin);
10085 this_scroll_margin = min (this_scroll_margin,
10086 XFASTINT (w->height) / 4);
10087 this_scroll_margin *= CANON_Y_UNIT (it.f);
10088 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
10089
10090 if ((w->cursor.y < this_scroll_margin
10091 && CHARPOS (start) > BEGV)
10092 /* Don't take scroll margin into account at the bottom because
10093 old redisplay didn't do it either. */
10094 || w->cursor.y + cursor_height > it.last_visible_y)
10095 {
10096 w->cursor.vpos = -1;
10097 clear_glyph_matrix (w->desired_matrix);
10098 return -1;
10099 }
10100 }
10101
10102 /* Scroll the display. Do it before changing the current matrix so
10103 that xterm.c doesn't get confused about where the cursor glyph is
10104 found. */
10105 if (dy)
10106 {
10107 update_begin (f);
10108
10109 if (FRAME_WINDOW_P (f))
10110 {
10111 rif->update_window_begin_hook (w);
10112 rif->scroll_run_hook (w, &run);
10113 rif->update_window_end_hook (w, 0);
10114 }
10115 else
10116 {
10117 /* Terminal frame. In this case, dvpos gives the number of
10118 lines to scroll by; dvpos < 0 means scroll up. */
10119 int first_unchanged_at_end_vpos
10120 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
10121 int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
10122 int end = XFASTINT (w->top) + window_internal_height (w);
10123
10124 /* Perform the operation on the screen. */
10125 if (dvpos > 0)
10126 {
10127 /* Scroll last_unchanged_at_beg_row to the end of the
10128 window down dvpos lines. */
10129 set_terminal_window (end);
10130
10131 /* On dumb terminals delete dvpos lines at the end
10132 before inserting dvpos empty lines. */
10133 if (!scroll_region_ok)
10134 ins_del_lines (end - dvpos, -dvpos);
10135
10136 /* Insert dvpos empty lines in front of
10137 last_unchanged_at_beg_row. */
10138 ins_del_lines (from, dvpos);
10139 }
10140 else if (dvpos < 0)
10141 {
10142 /* Scroll up last_unchanged_at_beg_vpos to the end of
10143 the window to last_unchanged_at_beg_vpos - |dvpos|. */
10144 set_terminal_window (end);
10145
10146 /* Delete dvpos lines in front of
10147 last_unchanged_at_beg_vpos. ins_del_lines will set
10148 the cursor to the given vpos and emit |dvpos| delete
10149 line sequences. */
10150 ins_del_lines (from + dvpos, dvpos);
10151
10152 /* On a dumb terminal insert dvpos empty lines at the
10153 end. */
10154 if (!scroll_region_ok)
10155 ins_del_lines (end + dvpos, -dvpos);
10156 }
10157
10158 set_terminal_window (0);
10159 }
10160
10161 update_end (f);
10162 }
10163
ca42b2e8
GM
10164 /* Shift reused rows of the current matrix to the right position.
10165 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
10166 text. */
10167 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
10168 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
10169 if (dvpos < 0)
10170 {
10171 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
10172 bottom_vpos, dvpos);
10173 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
10174 bottom_vpos, 0);
10175 }
10176 else if (dvpos > 0)
10177 {
10178 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
10179 bottom_vpos, dvpos);
10180 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
10181 first_unchanged_at_end_vpos + dvpos, 0);
10182 }
10183
10184 /* For frame-based redisplay, make sure that current frame and window
10185 matrix are in sync with respect to glyph memory. */
10186 if (!FRAME_WINDOW_P (f))
10187 sync_frame_with_window_matrix_rows (w);
10188
10189 /* Adjust buffer positions in reused rows. */
10190 if (delta)
10191 increment_glyph_matrix_buffer_positions (current_matrix,
10192 first_unchanged_at_end_vpos + dvpos,
10193 bottom_vpos, delta, delta_bytes);
10194
10195 /* Adjust Y positions. */
10196 if (dy)
10197 shift_glyph_matrix (w, current_matrix,
10198 first_unchanged_at_end_vpos + dvpos,
10199 bottom_vpos, dy);
10200
10201 if (first_unchanged_at_end_row)
10202 first_unchanged_at_end_row += dvpos;
10203
10204 /* If scrolling up, there may be some lines to display at the end of
10205 the window. */
10206 last_text_row_at_end = NULL;
10207 if (dy < 0)
10208 {
10209 /* Set last_row to the glyph row in the current matrix where the
10210 window end line is found. It has been moved up or down in
10211 the matrix by dvpos. */
10212 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
10213 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
10214
10215 /* If last_row is the window end line, it should display text. */
10216 xassert (last_row->displays_text_p);
10217
10218 /* If window end line was partially visible before, begin
10219 displaying at that line. Otherwise begin displaying with the
10220 line following it. */
10221 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
10222 {
10223 init_to_row_start (&it, w, last_row);
10224 it.vpos = last_vpos;
10225 it.current_y = last_row->y;
10226 }
10227 else
10228 {
10229 init_to_row_end (&it, w, last_row);
10230 it.vpos = 1 + last_vpos;
10231 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
10232 ++last_row;
10233 }
12adba34 10234
5f5c8ee5
GM
10235 /* We may start in a continuation line. If so, we have to get
10236 the right continuation_lines_width and current_x. */
10237 it.continuation_lines_width = last_row->continuation_lines_width;
10238 it.hpos = it.current_x = 0;
10239
10240 /* Display the rest of the lines at the window end. */
10241 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10242 while (it.current_y < it.last_visible_y
10243 && !fonts_changed_p)
10244 {
10245 /* Is it always sure that the display agrees with lines in
10246 the current matrix? I don't think so, so we mark rows
10247 displayed invalid in the current matrix by setting their
10248 enabled_p flag to zero. */
10249 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
10250 if (display_line (&it))
10251 last_text_row_at_end = it.glyph_row - 1;
10252 }
10253 }
12adba34 10254
5f5c8ee5
GM
10255 /* Update window_end_pos and window_end_vpos. */
10256 if (first_unchanged_at_end_row
10257 && first_unchanged_at_end_row->y < it.last_visible_y
10258 && !last_text_row_at_end)
10259 {
10260 /* Window end line if one of the preserved rows from the current
10261 matrix. Set row to the last row displaying text in current
10262 matrix starting at first_unchanged_at_end_row, after
10263 scrolling. */
10264 xassert (first_unchanged_at_end_row->displays_text_p);
10265 row = find_last_row_displaying_text (w->current_matrix, &it,
10266 first_unchanged_at_end_row);
10267 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
10268
10269 XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row));
10270 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
10271 XSETFASTINT (w->window_end_vpos,
10272 MATRIX_ROW_VPOS (row, w->current_matrix));
10273 }
10274 else if (last_text_row_at_end)
10275 {
10276 XSETFASTINT (w->window_end_pos,
10277 Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
10278 w->window_end_bytepos
10279 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
10280 XSETFASTINT (w->window_end_vpos,
10281 MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
10282 }
10283 else if (last_text_row)
10284 {
10285 /* We have displayed either to the end of the window or at the
10286 end of the window, i.e. the last row with text is to be found
10287 in the desired matrix. */
10288 XSETFASTINT (w->window_end_pos,
10289 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10290 w->window_end_bytepos
10291 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
10292 XSETFASTINT (w->window_end_vpos,
10293 MATRIX_ROW_VPOS (last_text_row, desired_matrix));
10294 }
10295 else if (first_unchanged_at_end_row == NULL
10296 && last_text_row == NULL
10297 && last_text_row_at_end == NULL)
10298 {
10299 /* Displayed to end of window, but no line containing text was
10300 displayed. Lines were deleted at the end of the window. */
10301 int vpos;
045dee35 10302 int header_line_p = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
10303
10304 for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
045dee35
GM
10305 if ((w->desired_matrix->rows[vpos + header_line_p].enabled_p
10306 && w->desired_matrix->rows[vpos + header_line_p].displays_text_p)
10307 || (!w->desired_matrix->rows[vpos + header_line_p].enabled_p
10308 && w->current_matrix->rows[vpos + header_line_p].displays_text_p))
5f5c8ee5 10309 break;
12adba34 10310
5f5c8ee5
GM
10311 w->window_end_vpos = make_number (vpos);
10312 }
10313 else
10314 abort ();
10315
10316 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
10317 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 10318
5f5c8ee5
GM
10319 /* Record that display has not been completed. */
10320 w->window_end_valid = Qnil;
10321 w->desired_matrix->no_scrolling_p = 1;
10322 return 1;
12adba34 10323}
0f9c0ff0 10324
a2889657 10325
5f5c8ee5
GM
10326\f
10327/***********************************************************************
10328 More debugging support
10329 ***********************************************************************/
a2889657 10330
5f5c8ee5 10331#if GLYPH_DEBUG
a2889657 10332
5f5c8ee5
GM
10333 void dump_glyph_row P_ ((struct glyph_matrix *, int, int));
10334static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
1c9241f5 10335
31b24551 10336
5f5c8ee5
GM
10337/* Dump the contents of glyph matrix MATRIX on stderr. If
10338 WITH_GLYPHS_P is non-zero, dump glyph contents as well. */
ca26e1c8 10339
5f5c8ee5
GM
10340void
10341dump_glyph_matrix (matrix, with_glyphs_p)
10342 struct glyph_matrix *matrix;
10343 int with_glyphs_p;
10344{
efc63ef0 10345 int i;
5f5c8ee5
GM
10346 for (i = 0; i < matrix->nrows; ++i)
10347 dump_glyph_row (matrix, i, with_glyphs_p);
10348}
31b24551 10349
68a37fa8 10350
5f5c8ee5
GM
10351/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
10352 WITH_GLYPH_SP non-zero means dump glyph contents, too. */
a2889657 10353
5f5c8ee5
GM
10354void
10355dump_glyph_row (matrix, vpos, with_glyphs_p)
10356 struct glyph_matrix *matrix;
10357 int vpos, with_glyphs_p;
10358{
10359 struct glyph_row *row;
10360
10361 if (vpos < 0 || vpos >= matrix->nrows)
10362 return;
10363
10364 row = MATRIX_ROW (matrix, vpos);
10365
10366 fprintf (stderr, "Row Start End Used oEI><O\\CTZF X Y W\n");
10367 fprintf (stderr, "=============================================\n");
10368
10369 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d\n",
10370 row - matrix->rows,
10371 MATRIX_ROW_START_CHARPOS (row),
10372 MATRIX_ROW_END_CHARPOS (row),
10373 row->used[TEXT_AREA],
10374 row->contains_overlapping_glyphs_p,
10375 row->enabled_p,
10376 row->inverse_p,
10377 row->truncated_on_left_p,
10378 row->truncated_on_right_p,
10379 row->overlay_arrow_p,
10380 row->continued_p,
10381 MATRIX_ROW_CONTINUATION_LINE_P (row),
10382 row->displays_text_p,
10383 row->ends_at_zv_p,
10384 row->fill_line_p,
10385 row->x,
10386 row->y,
10387 row->pixel_width);
10388 fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
10389 row->end.overlay_string_index);
10390 fprintf (stderr, "%9d %5d\n",
10391 CHARPOS (row->start.string_pos),
10392 CHARPOS (row->end.string_pos));
10393 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
10394 row->end.dpvec_index);
10395
10396 if (with_glyphs_p)
bd66d1ba 10397 {
5f5c8ee5
GM
10398 struct glyph *glyph, *glyph_end;
10399 int prev_had_glyphs_p;
10400
10401 glyph = row->glyphs[TEXT_AREA];
10402 glyph_end = glyph + row->used[TEXT_AREA];
10403
10404 /* Glyph for a line end in text. */
10405 if (glyph == glyph_end && glyph->charpos > 0)
10406 ++glyph_end;
10407
10408 if (glyph < glyph_end)
bd66d1ba 10409 {
5f5c8ee5
GM
10410 fprintf (stderr, " Glyph Type Pos W Code C Face LR\n");
10411 prev_had_glyphs_p = 1;
bd66d1ba
RS
10412 }
10413 else
5f5c8ee5
GM
10414 prev_had_glyphs_p = 0;
10415
10416 while (glyph < glyph_end)
f7b4b63a 10417 {
5f5c8ee5
GM
10418 if (glyph->type == CHAR_GLYPH)
10419 {
10420 fprintf (stderr,
10421 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10422 glyph - row->glyphs[TEXT_AREA],
10423 'C',
10424 glyph->charpos,
10425 glyph->pixel_width,
10426 glyph->u.ch.code,
10427 (glyph->u.ch.code < 0x80 && glyph->u.ch.code >= ' '
10428 ? glyph->u.ch.code
10429 : '.'),
10430 glyph->u.ch.face_id,
10431 glyph->left_box_line_p,
10432 glyph->right_box_line_p);
10433 }
10434 else if (glyph->type == STRETCH_GLYPH)
10435 {
10436 fprintf (stderr,
10437 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10438 glyph - row->glyphs[TEXT_AREA],
10439 'S',
10440 glyph->charpos,
10441 glyph->pixel_width,
10442 0,
10443 '.',
10444 glyph->u.stretch.face_id,
10445 glyph->left_box_line_p,
10446 glyph->right_box_line_p);
10447 }
10448 else if (glyph->type == IMAGE_GLYPH)
10449 {
10450 fprintf (stderr,
10451 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10452 glyph - row->glyphs[TEXT_AREA],
10453 'I',
10454 glyph->charpos,
10455 glyph->pixel_width,
10456 glyph->u.img.id,
10457 '.',
10458 glyph->u.img.face_id,
10459 glyph->left_box_line_p,
10460 glyph->right_box_line_p);
10461 }
10462 ++glyph;
f7b4b63a 10463 }
f4faa47c 10464 }
5f5c8ee5 10465}
f4faa47c 10466
a2889657 10467
5f5c8ee5
GM
10468DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
10469 Sdump_glyph_matrix, 0, 1, "p",
10470 "Dump the current matrix of the selected window to stderr.\n\
10471Shows contents of glyph row structures. With non-nil optional\n\
10472parameter WITH-GLYPHS-P, dump glyphs as well.")
10473 (with_glyphs_p)
10474{
10475 struct window *w = XWINDOW (selected_window);
10476 struct buffer *buffer = XBUFFER (w->buffer);
10477
10478 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
10479 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
10480 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
10481 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
10482 fprintf (stderr, "=============================================\n");
10483 dump_glyph_matrix (w->current_matrix, !NILP (with_glyphs_p));
10484 return Qnil;
10485}
1c2250c2 10486
1fca3fae 10487
5f5c8ee5
GM
10488DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "",
10489 "Dump glyph row ROW to stderr.")
10490 (row)
10491 Lisp_Object row;
10492{
10493 CHECK_NUMBER (row, 0);
10494 dump_glyph_row (XWINDOW (selected_window)->current_matrix, XINT (row), 1);
10495 return Qnil;
10496}
1fca3fae 10497
67481ae5 10498
e037b9ec 10499DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row,
5f5c8ee5
GM
10500 0, 0, "", "")
10501 ()
10502{
886bd6f2
GM
10503 struct frame *sf = SELECTED_FRAME ();
10504 struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)
5f5c8ee5
GM
10505 ->current_matrix);
10506 dump_glyph_row (m, 0, 1);
10507 return Qnil;
10508}
ca26e1c8 10509
0f9c0ff0 10510
5f5c8ee5
GM
10511DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
10512 Strace_redisplay_toggle, 0, 0, "",
10513 "Toggle tracing of redisplay.")
10514 ()
10515{
10516 trace_redisplay_p = !trace_redisplay_p;
10517 return Qnil;
10518}
10519
10520
10521#endif /* GLYPH_DEBUG */
ca26e1c8 10522
ca26e1c8 10523
5f5c8ee5
GM
10524\f
10525/***********************************************************************
10526 Building Desired Matrix Rows
10527 ***********************************************************************/
a2889657 10528
5f5c8ee5
GM
10529/* Return a temporary glyph row holding the glyphs of an overlay
10530 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 10531
5f5c8ee5
GM
10532static struct glyph_row *
10533get_overlay_arrow_glyph_row (w)
10534 struct window *w;
10535{
10536 struct frame *f = XFRAME (WINDOW_FRAME (w));
10537 struct buffer *buffer = XBUFFER (w->buffer);
10538 struct buffer *old = current_buffer;
10539 unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data;
10540 int arrow_len = XSTRING (Voverlay_arrow_string)->size;
10541 unsigned char *arrow_end = arrow_string + arrow_len;
10542 unsigned char *p;
10543 struct it it;
10544 int multibyte_p;
10545 int n_glyphs_before;
10546
10547 set_buffer_temp (buffer);
10548 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
10549 it.glyph_row->used[TEXT_AREA] = 0;
10550 SET_TEXT_POS (it.position, 0, 0);
10551
10552 multibyte_p = !NILP (buffer->enable_multibyte_characters);
10553 p = arrow_string;
10554 while (p < arrow_end)
10555 {
10556 Lisp_Object face, ilisp;
10557
10558 /* Get the next character. */
10559 if (multibyte_p)
4fdb80f2 10560 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
10561 else
10562 it.c = *p, it.len = 1;
10563 p += it.len;
10564
10565 /* Get its face. */
10566 XSETFASTINT (ilisp, p - arrow_string);
10567 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
10568 it.face_id = compute_char_face (f, it.c, face);
10569
10570 /* Compute its width, get its glyphs. */
10571 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 10572 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
10573 PRODUCE_GLYPHS (&it);
10574
10575 /* If this character doesn't fit any more in the line, we have
10576 to remove some glyphs. */
10577 if (it.current_x > it.last_visible_x)
10578 {
10579 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
10580 break;
10581 }
10582 }
10583
10584 set_buffer_temp (old);
10585 return it.glyph_row;
10586}
ca26e1c8 10587
b0a0fbda 10588
5f5c8ee5
GM
10589/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
10590 glyphs are only inserted for terminal frames since we can't really
10591 win with truncation glyphs when partially visible glyphs are
10592 involved. Which glyphs to insert is determined by
10593 produce_special_glyphs. */
67481ae5 10594
5f5c8ee5
GM
10595static void
10596insert_left_trunc_glyphs (it)
10597 struct it *it;
10598{
10599 struct it truncate_it;
10600 struct glyph *from, *end, *to, *toend;
10601
10602 xassert (!FRAME_WINDOW_P (it->f));
10603
10604 /* Get the truncation glyphs. */
10605 truncate_it = *it;
10606 truncate_it.charset = -1;
10607 truncate_it.current_x = 0;
10608 truncate_it.face_id = DEFAULT_FACE_ID;
10609 truncate_it.glyph_row = &scratch_glyph_row;
10610 truncate_it.glyph_row->used[TEXT_AREA] = 0;
10611 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
10612 truncate_it.object = 0;
10613 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
10614
10615 /* Overwrite glyphs from IT with truncation glyphs. */
10616 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
10617 end = from + truncate_it.glyph_row->used[TEXT_AREA];
10618 to = it->glyph_row->glyphs[TEXT_AREA];
10619 toend = to + it->glyph_row->used[TEXT_AREA];
10620
10621 while (from < end)
10622 *to++ = *from++;
10623
10624 /* There may be padding glyphs left over. Remove them. */
10625 from = to;
10626 while (from < toend && CHAR_GLYPH_PADDING_P (*from))
10627 ++from;
10628 while (from < toend)
10629 *to++ = *from++;
10630
10631 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
10632}
e0bfbde6 10633
e0bfbde6 10634
5f5c8ee5 10635/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 10636
5f5c8ee5
GM
10637 Most of the time, ascent and height of a display line will be equal
10638 to the max_ascent and max_height values of the display iterator
10639 structure. This is not the case if
67481ae5 10640
5f5c8ee5
GM
10641 1. We hit ZV without displaying anything. In this case, max_ascent
10642 and max_height will be zero.
1c9241f5 10643
5f5c8ee5
GM
10644 2. We have some glyphs that don't contribute to the line height.
10645 (The glyph row flag contributes_to_line_height_p is for future
10646 pixmap extensions).
f6fd109b 10647
5f5c8ee5
GM
10648 The first case is easily covered by using default values because in
10649 these cases, the line height does not really matter, except that it
10650 must not be zero. */
67481ae5 10651
5f5c8ee5
GM
10652static void
10653compute_line_metrics (it)
10654 struct it *it;
10655{
10656 struct glyph_row *row = it->glyph_row;
10657 int area, i;
1c2250c2 10658
5f5c8ee5
GM
10659 if (FRAME_WINDOW_P (it->f))
10660 {
045dee35 10661 int i, header_line_height;
1c2250c2 10662
5f5c8ee5
GM
10663 /* The line may consist of one space only, that was added to
10664 place the cursor on it. If so, the row's height hasn't been
10665 computed yet. */
10666 if (row->height == 0)
10667 {
10668 if (it->max_ascent + it->max_descent == 0)
312246d1 10669 it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
5f5c8ee5
GM
10670 row->ascent = it->max_ascent;
10671 row->height = it->max_ascent + it->max_descent;
312246d1
GM
10672 row->phys_ascent = it->max_phys_ascent;
10673 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
10674 }
10675
10676 /* Compute the width of this line. */
10677 row->pixel_width = row->x;
10678 for (i = 0; i < row->used[TEXT_AREA]; ++i)
10679 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
10680
10681 xassert (row->pixel_width >= 0);
10682 xassert (row->ascent >= 0 && row->height > 0);
10683
312246d1
GM
10684 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
10685 || MATRIX_ROW_OVERLAPS_PRED_P (row));
10686
10687 /* If first line's physical ascent is larger than its logical
10688 ascent, use the physical ascent, and make the row taller.
10689 This makes accented characters fully visible. */
10690 if (row == it->w->desired_matrix->rows
10691 && row->phys_ascent > row->ascent)
10692 {
10693 row->height += row->phys_ascent - row->ascent;
10694 row->ascent = row->phys_ascent;
10695 }
10696
5f5c8ee5
GM
10697 /* Compute how much of the line is visible. */
10698 row->visible_height = row->height;
10699
045dee35
GM
10700 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
10701 if (row->y < header_line_height)
10702 row->visible_height -= header_line_height - row->y;
5f5c8ee5
GM
10703 else
10704 {
10705 int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
10706 if (row->y + row->height > max_y)
10707 row->visible_height -= row->y + row->height - max_y;
10708 }
10709 }
10710 else
10711 {
10712 row->pixel_width = row->used[TEXT_AREA];
312246d1
GM
10713 row->ascent = row->phys_ascent = 0;
10714 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 10715 }
67481ae5 10716
5f5c8ee5
GM
10717 /* Compute a hash code for this row. */
10718 row->hash = 0;
10719 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
10720 for (i = 0; i < row->used[area]; ++i)
10721 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
10722 + row->glyphs[area][i].u.val
10723 + (row->glyphs[area][i].type << 2));
a2889657 10724
5f5c8ee5 10725 it->max_ascent = it->max_descent = 0;
312246d1 10726 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 10727}
12adba34 10728
ca26e1c8 10729
5f5c8ee5
GM
10730/* Append one space to the glyph row of iterator IT if doing a
10731 window-based redisplay. DEFAULT_FACE_P non-zero means let the
10732 space have the default face, otherwise let it have the same face as
c6e89d6c
GM
10733 IT->face_id.
10734
10735 This function is called to make sure that there is always one glyph
10736 at the end of a glyph row that the cursor can be set on under
10737 window-systems. (If there weren't such a glyph we would not know
10738 how wide and tall a box cursor should be displayed).
10739
10740 At the same time this space let's a nicely handle clearing to the
10741 end of the line if the row ends in italic text. */
ca26e1c8 10742
5f5c8ee5
GM
10743static void
10744append_space (it, default_face_p)
10745 struct it *it;
10746 int default_face_p;
10747{
10748 if (FRAME_WINDOW_P (it->f))
10749 {
10750 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 10751
5f5c8ee5
GM
10752 if (it->glyph_row->glyphs[TEXT_AREA] + n
10753 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 10754 {
5f5c8ee5
GM
10755 /* Save some values that must not be changed. */
10756 int saved_x = it->current_x;
10757 struct text_pos saved_pos;
10758 int saved_what = it->what;
10759 int saved_face_id = it->face_id;
10760 int saved_charset = it->charset;
10761 Lisp_Object saved_object;
10762
10763 saved_object = it->object;
10764 saved_pos = it->position;
10765
10766 it->what = IT_CHARACTER;
10767 bzero (&it->position, sizeof it->position);
10768 it->object = 0;
10769 it->c = ' ';
10770 it->len = 1;
10771 it->charset = CHARSET_ASCII;
10772
10773 if (default_face_p)
10774 it->face_id = DEFAULT_FACE_ID;
10775 if (it->multibyte_p)
10776 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, CHARSET_ASCII);
10777 else
10778 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, -1);
1842fc1a 10779
5f5c8ee5
GM
10780 PRODUCE_GLYPHS (it);
10781
10782 it->current_x = saved_x;
10783 it->object = saved_object;
10784 it->position = saved_pos;
10785 it->what = saved_what;
10786 it->face_id = saved_face_id;
10787 it->charset = saved_charset;
10788 }
10789 }
10790}
12adba34 10791
1842fc1a 10792
5f5c8ee5
GM
10793/* Extend the face of the last glyph in the text area of IT->glyph_row
10794 to the end of the display line. Called from display_line.
10795 If the glyph row is empty, add a space glyph to it so that we
10796 know the face to draw. Set the glyph row flag fill_line_p. */
10797
10798static void
10799extend_face_to_end_of_line (it)
10800 struct it *it;
10801{
10802 struct face *face;
10803 struct frame *f = it->f;
1842fc1a 10804
5f5c8ee5
GM
10805 /* If line is already filled, do nothing. */
10806 if (it->current_x >= it->last_visible_x)
10807 return;
10808
10809 /* Face extension extends the background and box of IT->face_id
10810 to the end of the line. If the background equals the background
10811 of the frame, we haven't to do anything. */
10812 face = FACE_FROM_ID (f, it->face_id);
10813 if (FRAME_WINDOW_P (f)
10814 && face->box == FACE_NO_BOX
10815 && face->background == FRAME_BACKGROUND_PIXEL (f)
10816 && !face->stipple)
10817 return;
1842fc1a 10818
5f5c8ee5
GM
10819 /* Set the glyph row flag indicating that the face of the last glyph
10820 in the text area has to be drawn to the end of the text area. */
10821 it->glyph_row->fill_line_p = 1;
545e04f6 10822
5f5c8ee5
GM
10823 /* If current charset of IT is not ASCII, make sure we have the
10824 ASCII face. This will be automatically undone the next time
10825 get_next_display_element returns a character from a different
10826 charset. Note that the charset will always be ASCII in unibyte
10827 text. */
10828 if (it->charset != CHARSET_ASCII)
10829 {
10830 it->charset = CHARSET_ASCII;
10831 it->face_id = FACE_FOR_CHARSET (f, it->face_id, CHARSET_ASCII);
10832 }
545e04f6 10833
5f5c8ee5
GM
10834 if (FRAME_WINDOW_P (f))
10835 {
10836 /* If the row is empty, add a space with the current face of IT,
10837 so that we know which face to draw. */
10838 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 10839 {
5f5c8ee5
GM
10840 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
10841 it->glyph_row->glyphs[TEXT_AREA][0].u.ch.face_id = it->face_id;
10842 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 10843 }
5f5c8ee5
GM
10844 }
10845 else
10846 {
10847 /* Save some values that must not be changed. */
10848 int saved_x = it->current_x;
10849 struct text_pos saved_pos;
10850 Lisp_Object saved_object;
10851 int saved_what = it->what;
10852
10853 saved_object = it->object;
10854 saved_pos = it->position;
10855
10856 it->what = IT_CHARACTER;
10857 bzero (&it->position, sizeof it->position);
10858 it->object = 0;
10859 it->c = ' ';
10860 it->len = 1;
10861
10862 PRODUCE_GLYPHS (it);
10863
10864 while (it->current_x <= it->last_visible_x)
10865 PRODUCE_GLYPHS (it);
10866
10867 /* Don't count these blanks really. It would let us insert a left
10868 truncation glyph below and make us set the cursor on them, maybe. */
10869 it->current_x = saved_x;
10870 it->object = saved_object;
10871 it->position = saved_pos;
10872 it->what = saved_what;
10873 }
10874}
12adba34 10875
545e04f6 10876
5f5c8ee5
GM
10877/* Value is non-zero if text starting at CHARPOS in current_buffer is
10878 trailing whitespace. */
1c9241f5 10879
5f5c8ee5
GM
10880static int
10881trailing_whitespace_p (charpos)
10882 int charpos;
10883{
10884 int bytepos = CHAR_TO_BYTE (charpos);
10885 int c = 0;
7bbe686f 10886
5f5c8ee5
GM
10887 while (bytepos < ZV_BYTE
10888 && (c = FETCH_CHAR (bytepos),
10889 c == ' ' || c == '\t'))
10890 ++bytepos;
0d09d1e6 10891
8f897821
GM
10892 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
10893 {
10894 if (bytepos != PT_BYTE)
10895 return 1;
10896 }
10897 return 0;
5f5c8ee5 10898}
31b24551 10899
545e04f6 10900
5f5c8ee5 10901/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 10902
5f5c8ee5
GM
10903void
10904highlight_trailing_whitespace (f, row)
10905 struct frame *f;
10906 struct glyph_row *row;
10907{
10908 int used = row->used[TEXT_AREA];
10909
10910 if (used)
10911 {
10912 struct glyph *start = row->glyphs[TEXT_AREA];
10913 struct glyph *glyph = start + used - 1;
10914
10915 /* Skip over the space glyph inserted to display the
10916 cursor at the end of a line. */
10917 if (glyph->type == CHAR_GLYPH
10918 && glyph->u.ch.code == ' '
10919 && glyph->object == 0)
10920 --glyph;
10921
10922 /* If last glyph is a space or stretch, and it's trailing
10923 whitespace, set the face of all trailing whitespace glyphs in
10924 IT->glyph_row to `trailing-whitespace'. */
10925 if (glyph >= start
10926 && BUFFERP (glyph->object)
10927 && (glyph->type == STRETCH_GLYPH
10928 || (glyph->type == CHAR_GLYPH
10929 && glyph->u.ch.code == ' '))
10930 && trailing_whitespace_p (glyph->charpos))
545e04f6 10931 {
5f5c8ee5
GM
10932 int face_id = lookup_named_face (f, Qtrailing_whitespace,
10933 CHARSET_ASCII);
10934
10935 while (glyph >= start
10936 && BUFFERP (glyph->object)
10937 && (glyph->type == STRETCH_GLYPH
10938 || (glyph->type == CHAR_GLYPH
10939 && glyph->u.ch.code == ' ')))
545e04f6 10940 {
5f5c8ee5
GM
10941 if (glyph->type == STRETCH_GLYPH)
10942 glyph->u.stretch.face_id = face_id;
10943 else
10944 glyph->u.ch.face_id = face_id;
10945 --glyph;
545e04f6
KH
10946 }
10947 }
a2889657 10948 }
5f5c8ee5 10949}
a2889657 10950
5fcbb24d 10951
5f5c8ee5
GM
10952/* Construct the glyph row IT->glyph_row in the desired matrix of
10953 IT->w from text at the current position of IT. See dispextern.h
10954 for an overview of struct it. Value is non-zero if
10955 IT->glyph_row displays text, as opposed to a line displaying ZV
10956 only. */
10957
10958static int
10959display_line (it)
10960 struct it *it;
10961{
10962 struct glyph_row *row = it->glyph_row;
10963
10964 /* We always start displaying at hpos zero even if hscrolled. */
10965 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 10966
5f5c8ee5
GM
10967 /* We must not display in a row that's not a text row. */
10968 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
10969 < it->w->desired_matrix->nrows);
12adba34 10970
5f5c8ee5
GM
10971 /* Is IT->w showing the region? */
10972 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 10973
5f5c8ee5
GM
10974 /* Clear the result glyph row and enable it. */
10975 prepare_desired_row (row);
12adba34 10976
5f5c8ee5
GM
10977 row->y = it->current_y;
10978 row->start = it->current;
10979 row->continuation_lines_width = it->continuation_lines_width;
10980 row->displays_text_p = 1;
10981
10982 /* Arrange the overlays nicely for our purposes. Usually, we call
10983 display_line on only one line at a time, in which case this
10984 can't really hurt too much, or we call it on lines which appear
10985 one after another in the buffer, in which case all calls to
10986 recenter_overlay_lists but the first will be pretty cheap. */
10987 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
10988
5f5c8ee5
GM
10989 /* Move over display elements that are not visible because we are
10990 hscrolled. This may stop at an x-position < IT->first_visible_x
10991 if the first glyph is partially visible or if we hit a line end. */
10992 if (it->current_x < it->first_visible_x)
10993 move_it_in_display_line_to (it, ZV, it->first_visible_x,
10994 MOVE_TO_POS | MOVE_TO_X);
10995
10996 /* Get the initial row height. This is either the height of the
10997 text hscrolled, if there is any, or zero. */
10998 row->ascent = it->max_ascent;
10999 row->height = it->max_ascent + it->max_descent;
312246d1
GM
11000 row->phys_ascent = it->max_phys_ascent;
11001 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
11002
11003 /* Loop generating characters. The loop is left with IT on the next
11004 character to display. */
11005 while (1)
11006 {
11007 int n_glyphs_before, hpos_before, x_before;
11008 int x, i, nglyphs;
11009
11010 /* Retrieve the next thing to display. Value is zero if end of
11011 buffer reached. */
11012 if (!get_next_display_element (it))
11013 {
11014 /* Maybe add a space at the end of this line that is used to
11015 display the cursor there under X. */
11016 append_space (it, 1);
11017
11018 /* The position -1 below indicates a blank line not
11019 corresponding to any text, as opposed to an empty line
11020 corresponding to a line end. */
11021 if (row->used[TEXT_AREA] <= 1)
a2889657 11022 {
5f5c8ee5
GM
11023 row->glyphs[TEXT_AREA]->charpos = -1;
11024 row->displays_text_p = 0;
11025
11026 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines))
11027 row->indicate_empty_line_p = 1;
a2889657 11028 }
5f5c8ee5
GM
11029
11030 it->continuation_lines_width = 0;
11031 row->ends_at_zv_p = 1;
11032 break;
a2889657 11033 }
a2889657 11034
5f5c8ee5
GM
11035 /* Now, get the metrics of what we want to display. This also
11036 generates glyphs in `row' (which is IT->glyph_row). */
11037 n_glyphs_before = row->used[TEXT_AREA];
11038 x = it->current_x;
11039 PRODUCE_GLYPHS (it);
a2889657 11040
5f5c8ee5
GM
11041 /* If this display element was in marginal areas, continue with
11042 the next one. */
11043 if (it->area != TEXT_AREA)
a2889657 11044 {
5f5c8ee5
GM
11045 row->ascent = max (row->ascent, it->max_ascent);
11046 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11047 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11048 row->phys_height = max (row->phys_height,
11049 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11050 set_iterator_to_next (it);
11051 continue;
11052 }
5936754e 11053
5f5c8ee5
GM
11054 /* Does the display element fit on the line? If we truncate
11055 lines, we should draw past the right edge of the window. If
11056 we don't truncate, we want to stop so that we can display the
11057 continuation glyph before the right margin. If lines are
11058 continued, there are two possible strategies for characters
11059 resulting in more than 1 glyph (e.g. tabs): Display as many
11060 glyphs as possible in this line and leave the rest for the
11061 continuation line, or display the whole element in the next
11062 line. Original redisplay did the former, so we do it also. */
11063 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
11064 hpos_before = it->hpos;
11065 x_before = x;
11066
11067 if (nglyphs == 1
11068 && it->current_x < it->last_visible_x)
11069 {
11070 ++it->hpos;
11071 row->ascent = max (row->ascent, it->max_ascent);
11072 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11073 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11074 row->phys_height = max (row->phys_height,
11075 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11076 if (it->current_x - it->pixel_width < it->first_visible_x)
11077 row->x = x - it->first_visible_x;
11078 }
11079 else
11080 {
11081 int new_x;
11082 struct glyph *glyph;
11083
11084 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 11085 {
5f5c8ee5
GM
11086 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
11087 new_x = x + glyph->pixel_width;
11088
11089 if (/* Lines are continued. */
11090 !it->truncate_lines_p
11091 && (/* Glyph doesn't fit on the line. */
11092 new_x > it->last_visible_x
11093 /* Or it fits exactly on a window system frame. */
11094 || (new_x == it->last_visible_x
11095 && FRAME_WINDOW_P (it->f))))
a2889657 11096 {
5f5c8ee5
GM
11097 /* End of a continued line. */
11098
11099 if (it->hpos == 0
11100 || (new_x == it->last_visible_x
11101 && FRAME_WINDOW_P (it->f)))
11102 {
11103 /* Current glyph fits exactly on the line. We
11104 must continue the line because we can't draw
11105 the cursor after the glyph. */
11106 row->continued_p = 1;
11107 it->current_x = new_x;
11108 it->continuation_lines_width += new_x;
11109 ++it->hpos;
11110 if (i == nglyphs - 1)
11111 set_iterator_to_next (it);
11112 }
11113 else
5936754e 11114 {
5f5c8ee5
GM
11115 /* Display element draws past the right edge of
11116 the window. Restore positions to values
11117 before the element. The next line starts
11118 with current_x before the glyph that could
11119 not be displayed, so that TAB works right. */
11120 row->used[TEXT_AREA] = n_glyphs_before + i;
11121
11122 /* Display continuation glyphs. */
11123 if (!FRAME_WINDOW_P (it->f))
11124 produce_special_glyphs (it, IT_CONTINUATION);
11125 row->continued_p = 1;
11126
11127 it->current_x = x;
11128 it->continuation_lines_width += x;
5936754e 11129 }
5f5c8ee5
GM
11130 break;
11131 }
11132 else if (new_x > it->first_visible_x)
11133 {
11134 /* Increment number of glyphs actually displayed. */
11135 ++it->hpos;
11136
11137 if (x < it->first_visible_x)
11138 /* Glyph is partially visible, i.e. row starts at
11139 negative X position. */
11140 row->x = x - it->first_visible_x;
11141 }
11142 else
11143 {
11144 /* Glyph is completely off the left margin of the
11145 window. This should not happen because of the
11146 move_it_in_display_line at the start of
11147 this function. */
11148 abort ();
a2889657 11149 }
a2889657 11150 }
5f5c8ee5
GM
11151
11152 row->ascent = max (row->ascent, it->max_ascent);
11153 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11154 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11155 row->phys_height = max (row->phys_height,
11156 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11157
11158 /* End of this display line if row is continued. */
11159 if (row->continued_p)
11160 break;
a2889657 11161 }
a2889657 11162
5f5c8ee5
GM
11163 /* Is this a line end? If yes, we're also done, after making
11164 sure that a non-default face is extended up to the right
11165 margin of the window. */
11166 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 11167 {
5f5c8ee5
GM
11168 int used_before = row->used[TEXT_AREA];
11169
11170 /* Add a space at the end of the line that is used to
11171 display the cursor there. */
11172 append_space (it, 0);
11173
11174 /* Extend the face to the end of the line. */
11175 extend_face_to_end_of_line (it);
11176
11177 /* Make sure we have the position. */
11178 if (used_before == 0)
11179 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
11180
11181 /* Consume the line end. This skips over invisible lines. */
11182 set_iterator_to_next (it);
11183 it->continuation_lines_width = 0;
11184 break;
1c9241f5 11185 }
a2889657 11186
5f5c8ee5
GM
11187 /* Proceed with next display element. Note that this skips
11188 over lines invisible because of selective display. */
11189 set_iterator_to_next (it);
b1d1124b 11190
5f5c8ee5
GM
11191 /* If we truncate lines, we are done when the last displayed
11192 glyphs reach past the right margin of the window. */
11193 if (it->truncate_lines_p
11194 && (FRAME_WINDOW_P (it->f)
11195 ? (it->current_x >= it->last_visible_x)
11196 : (it->current_x > it->last_visible_x)))
75d13c64 11197 {
5f5c8ee5
GM
11198 /* Maybe add truncation glyphs. */
11199 if (!FRAME_WINDOW_P (it->f))
11200 {
11201 --it->glyph_row->used[TEXT_AREA];
11202 produce_special_glyphs (it, IT_TRUNCATION);
11203 }
11204
11205 row->truncated_on_right_p = 1;
11206 it->continuation_lines_width = 0;
312246d1 11207 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
11208 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
11209 it->hpos = hpos_before;
11210 it->current_x = x_before;
11211 break;
75d13c64 11212 }
a2889657 11213 }
a2889657 11214
5f5c8ee5
GM
11215 /* If line is not empty and hscrolled, maybe insert truncation glyphs
11216 at the left window margin. */
11217 if (it->first_visible_x
11218 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
11219 {
11220 if (!FRAME_WINDOW_P (it->f))
11221 insert_left_trunc_glyphs (it);
11222 row->truncated_on_left_p = 1;
11223 }
a2889657 11224
5f5c8ee5
GM
11225 /* If the start of this line is the overlay arrow-position, then
11226 mark this glyph row as the one containing the overlay arrow.
11227 This is clearly a mess with variable size fonts. It would be
11228 better to let it be displayed like cursors under X. */
e24c997d 11229 if (MARKERP (Voverlay_arrow_position)
a2889657 11230 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
11231 && (MATRIX_ROW_START_CHARPOS (row)
11232 == marker_position (Voverlay_arrow_position))
e24c997d 11233 && STRINGP (Voverlay_arrow_string)
a2889657
JB
11234 && ! overlay_arrow_seen)
11235 {
5f5c8ee5
GM
11236 /* Overlay arrow in window redisplay is a bitmap. */
11237 if (!FRAME_WINDOW_P (it->f))
c4628384 11238 {
5f5c8ee5
GM
11239 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
11240 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
11241 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
11242 struct glyph *p = row->glyphs[TEXT_AREA];
11243 struct glyph *p2, *end;
11244
11245 /* Copy the arrow glyphs. */
11246 while (glyph < arrow_end)
11247 *p++ = *glyph++;
11248
11249 /* Throw away padding glyphs. */
11250 p2 = p;
11251 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
11252 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
11253 ++p2;
11254 if (p2 > p)
212e4f87 11255 {
5f5c8ee5
GM
11256 while (p2 < end)
11257 *p++ = *p2++;
11258 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 11259 }
c4628384 11260 }
5f5c8ee5 11261
a2889657 11262 overlay_arrow_seen = 1;
5f5c8ee5 11263 row->overlay_arrow_p = 1;
a2889657
JB
11264 }
11265
5f5c8ee5
GM
11266 /* Compute pixel dimensions of this line. */
11267 compute_line_metrics (it);
11268
11269 /* Remember the position at which this line ends. */
11270 row->end = it->current;
11271
11272 /* Maybe set the cursor. If you change this, it's probably a good
11273 idea to also change the code in redisplay_window for cursor
11274 movement in an unchanged window. */
11275 if (it->w->cursor.vpos < 0
11276 && PT >= MATRIX_ROW_START_CHARPOS (row)
11277 && MATRIX_ROW_END_CHARPOS (row) >= PT
11278 && !(MATRIX_ROW_END_CHARPOS (row) == PT
11279 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
11280 || !row->ends_at_zv_p)))
11281 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
11282
11283 /* Highlight trailing whitespace. */
8f897821 11284 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
11285 highlight_trailing_whitespace (it->f, it->glyph_row);
11286
11287 /* Prepare for the next line. This line starts horizontally at (X
11288 HPOS) = (0 0). Vertical positions are incremented. As a
11289 convenience for the caller, IT->glyph_row is set to the next
11290 row to be used. */
11291 it->current_x = it->hpos = 0;
11292 it->current_y += row->height;
11293 ++it->vpos;
11294 ++it->glyph_row;
11295 return row->displays_text_p;
a2889657 11296}
5f5c8ee5
GM
11297
11298
a2889657 11299\f
5f5c8ee5
GM
11300/***********************************************************************
11301 Menu Bar
11302 ***********************************************************************/
11303
11304/* Redisplay the menu bar in the frame for window W.
11305
11306 The menu bar of X frames that don't have X toolkit support is
11307 displayed in a special window W->frame->menu_bar_window.
11308
11309 The menu bar of terminal frames is treated specially as far as
11310 glyph matrices are concerned. Menu bar lines are not part of
11311 windows, so the update is done directly on the frame matrix rows
11312 for the menu bar. */
7ce2c095
RS
11313
11314static void
11315display_menu_bar (w)
11316 struct window *w;
11317{
5f5c8ee5
GM
11318 struct frame *f = XFRAME (WINDOW_FRAME (w));
11319 struct it it;
11320 Lisp_Object items;
8351baf2 11321 int i;
7ce2c095 11322
5f5c8ee5 11323 /* Don't do all this for graphical frames. */
dc937613 11324#ifdef HAVE_NTGUI
d129c4c2
KH
11325 if (!NILP (Vwindow_system))
11326 return;
dc937613 11327#endif
dc937613 11328#ifdef USE_X_TOOLKIT
d3413a53 11329 if (FRAME_X_P (f))
7ce2c095 11330 return;
5f5c8ee5
GM
11331#endif
11332
11333#ifdef USE_X_TOOLKIT
11334 xassert (!FRAME_WINDOW_P (f));
52377a47 11335 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5
GM
11336 it.first_visible_x = 0;
11337 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11338#else /* not USE_X_TOOLKIT */
11339 if (FRAME_WINDOW_P (f))
11340 {
11341 /* Menu bar lines are displayed in the desired matrix of the
11342 dummy window menu_bar_window. */
11343 struct window *menu_w;
11344 xassert (WINDOWP (f->menu_bar_window));
11345 menu_w = XWINDOW (f->menu_bar_window);
11346 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 11347 MENU_FACE_ID);
5f5c8ee5
GM
11348 it.first_visible_x = 0;
11349 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11350 }
11351 else
11352 {
11353 /* This is a TTY frame, i.e. character hpos/vpos are used as
11354 pixel x/y. */
11355 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 11356 MENU_FACE_ID);
5f5c8ee5
GM
11357 it.first_visible_x = 0;
11358 it.last_visible_x = FRAME_WIDTH (f);
11359 }
11360#endif /* not USE_X_TOOLKIT */
11361
11362 /* Clear all rows of the menu bar. */
11363 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
11364 {
11365 struct glyph_row *row = it.glyph_row + i;
11366 clear_glyph_row (row);
11367 row->enabled_p = 1;
11368 row->full_width_p = 1;
11369 }
7ce2c095 11370
5f5c8ee5
GM
11371 /* Make the first line of the menu bar appear in reverse video. */
11372 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
7ce2c095 11373
5f5c8ee5
GM
11374 /* Display all items of the menu bar. */
11375 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 11376 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 11377 {
5f5c8ee5
GM
11378 Lisp_Object string;
11379
11380 /* Stop at nil string. */
8351baf2
RS
11381 string = XVECTOR (items)->contents[i + 1];
11382 if (NILP (string))
11383 break;
2d66ad19 11384
5f5c8ee5
GM
11385 /* Remember where item was displayed. */
11386 XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos);
7ce2c095 11387
5f5c8ee5
GM
11388 /* Display the item, pad with one space. */
11389 if (it.current_x < it.last_visible_x)
11390 display_string (NULL, string, Qnil, 0, 0, &it,
11391 XSTRING (string)->size + 1, 0, 0, -1);
7ce2c095
RS
11392 }
11393
2d66ad19 11394 /* Fill out the line with spaces. */
5f5c8ee5
GM
11395 if (it.current_x < it.last_visible_x)
11396 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 11397
5f5c8ee5
GM
11398 /* Compute the total height of the lines. */
11399 compute_line_metrics (&it);
7ce2c095 11400}
5f5c8ee5
GM
11401
11402
7ce2c095 11403\f
5f5c8ee5
GM
11404/***********************************************************************
11405 Mode Line
11406 ***********************************************************************/
11407
11408/* Display the mode and/or top line of window W. */
a2889657
JB
11409
11410static void
5f5c8ee5 11411display_mode_lines (w)
a2889657
JB
11412 struct window *w;
11413{
5f5c8ee5 11414 /* These will be set while the mode line specs are processed. */
aa6d10fa 11415 line_number_displayed = 0;
155ef550 11416 w->column_number_displayed = Qnil;
aa6d10fa 11417
5f5c8ee5 11418 if (WINDOW_WANTS_MODELINE_P (w))
045dee35
GM
11419 display_mode_line (w, MODE_LINE_FACE_ID,
11420 current_buffer->mode_line_format);
5f5c8ee5 11421
045dee35
GM
11422 if (WINDOW_WANTS_HEADER_LINE_P (w))
11423 display_mode_line (w, HEADER_LINE_FACE_ID,
11424 current_buffer->header_line_format);
5f5c8ee5 11425}
03b294dc 11426
03b294dc 11427
5f5c8ee5 11428/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 11429 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
5f5c8ee5 11430 FORMAT is the mode line format to display. */
03b294dc 11431
5f5c8ee5
GM
11432static void
11433display_mode_line (w, face_id, format)
11434 struct window *w;
11435 enum face_id face_id;
11436 Lisp_Object format;
11437{
11438 struct it it;
11439 struct face *face;
03b294dc 11440
5f5c8ee5
GM
11441 init_iterator (&it, w, -1, -1, NULL, face_id);
11442 prepare_desired_row (it.glyph_row);
11443
11444 /* Temporarily make frame's keyboard the current kboard so that
11445 kboard-local variables in the mode_line_format will get the right
11446 values. */
11447 push_frame_kboard (it.f);
11448 display_mode_element (&it, 0, 0, 0, format);
11449 pop_frame_kboard ();
a2889657 11450
5f5c8ee5
GM
11451 /* Fill up with spaces. */
11452 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
11453
11454 compute_line_metrics (&it);
11455 it.glyph_row->full_width_p = 1;
11456 it.glyph_row->mode_line_p = 1;
11457 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
11458 it.glyph_row->continued_p = 0;
11459 it.glyph_row->truncated_on_left_p = 0;
11460 it.glyph_row->truncated_on_right_p = 0;
11461
11462 /* Make a 3D mode-line have a shadow at its right end. */
11463 face = FACE_FROM_ID (it.f, face_id);
11464 extend_face_to_end_of_line (&it);
11465 if (face->box != FACE_NO_BOX)
d7eb09a0 11466 {
5f5c8ee5
GM
11467 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
11468 + it.glyph_row->used[TEXT_AREA] - 1);
11469 last->right_box_line_p = 1;
d7eb09a0 11470 }
a2889657
JB
11471}
11472
a2889657 11473
5f5c8ee5
GM
11474/* Contribute ELT to the mode line for window IT->w. How it
11475 translates into text depends on its data type.
a2889657 11476
5f5c8ee5 11477 IT describes the display environment in which we display, as usual.
a2889657
JB
11478
11479 DEPTH is the depth in recursion. It is used to prevent
11480 infinite recursion here.
11481
5f5c8ee5
GM
11482 FIELD_WIDTH is the number of characters the display of ELT should
11483 occupy in the mode line, and PRECISION is the maximum number of
11484 characters to display from ELT's representation. See
11485 display_string for details. *
a2889657 11486
5f5c8ee5 11487 Returns the hpos of the end of the text generated by ELT. */
a2889657
JB
11488
11489static int
5f5c8ee5
GM
11490display_mode_element (it, depth, field_width, precision, elt)
11491 struct it *it;
a2889657 11492 int depth;
5f5c8ee5
GM
11493 int field_width, precision;
11494 Lisp_Object elt;
a2889657 11495{
5f5c8ee5
GM
11496 int n = 0, field, prec;
11497
a2889657
JB
11498 tail_recurse:
11499 if (depth > 10)
11500 goto invalid;
11501
11502 depth++;
11503
0220c518 11504 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
11505 {
11506 case Lisp_String:
11507 {
11508 /* A string: output it and check for %-constructs within it. */
5f5c8ee5
GM
11509 unsigned char c;
11510 unsigned char *this = XSTRING (elt)->data;
11511 unsigned char *lisp_string = this;
11512
11513 while ((precision <= 0 || n < precision)
11514 && *this
11515 && (frame_title_ptr
11516 || it->current_x < it->last_visible_x))
a2889657
JB
11517 {
11518 unsigned char *last = this;
5f5c8ee5
GM
11519
11520 /* Advance to end of string or next format specifier. */
a2889657
JB
11521 while ((c = *this++) != '\0' && c != '%')
11522 ;
5f5c8ee5 11523
a2889657
JB
11524 if (this - 1 != last)
11525 {
5f5c8ee5
GM
11526 /* Output to end of string or up to '%'. Field width
11527 is length of string. Don't output more than
11528 PRECISION allows us. */
11529 prec = --this - last;
11530 if (precision > 0 && prec > precision - n)
11531 prec = precision - n;
11532
d39b6696 11533 if (frame_title_ptr)
5f5c8ee5 11534 n += store_frame_title (last, prec, prec);
d39b6696 11535 else
5f5c8ee5
GM
11536 n += display_string (NULL, elt, Qnil, 0, last - lisp_string,
11537 it, 0, prec, 0, -1);
a2889657
JB
11538 }
11539 else /* c == '%' */
11540 {
5f5c8ee5
GM
11541 unsigned char *percent_position = this;
11542
11543 /* Get the specified minimum width. Zero means
11544 don't pad. */
11545 field = 0;
a2889657 11546 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 11547 field = field * 10 + c - '0';
a2889657 11548
5f5c8ee5
GM
11549 /* Don't pad beyond the total padding allowed. */
11550 if (field_width - n > 0 && field > field_width - n)
11551 field = field_width - n;
a2889657 11552
5f5c8ee5
GM
11553 /* Note that either PRECISION <= 0 or N < PRECISION. */
11554 prec = precision - n;
11555
a2889657 11556 if (c == 'M')
5f5c8ee5
GM
11557 n += display_mode_element (it, depth, field, prec,
11558 Vglobal_mode_string);
a2889657 11559 else if (c != 0)
d39b6696 11560 {
5f5c8ee5
GM
11561 unsigned char *spec
11562 = decode_mode_spec (it->w, c, field, prec);
11563
d39b6696 11564 if (frame_title_ptr)
5f5c8ee5 11565 n += store_frame_title (spec, field, prec);
d39b6696 11566 else
5f5c8ee5
GM
11567 {
11568 int nglyphs_before
11569 = it->glyph_row->used[TEXT_AREA];
11570 int charpos
11571 = percent_position - XSTRING (elt)->data;
11572 int nwritten
11573 = display_string (spec, Qnil, elt, charpos, 0, it,
11574 field, prec, 0, -1);
11575
11576 /* Assign to the glyphs written above the
11577 string where the `%x' came from, position
11578 of the `%'. */
11579 if (nwritten > 0)
11580 {
11581 struct glyph *glyph
11582 = (it->glyph_row->glyphs[TEXT_AREA]
11583 + nglyphs_before);
11584 int i;
11585
11586 for (i = 0; i < nwritten; ++i)
11587 {
11588 glyph[i].object = elt;
11589 glyph[i].charpos = charpos;
11590 }
11591
11592 n += nwritten;
11593 }
11594 }
d39b6696 11595 }
a2889657
JB
11596 }
11597 }
11598 }
11599 break;
11600
11601 case Lisp_Symbol:
11602 /* A symbol: process the value of the symbol recursively
11603 as if it appeared here directly. Avoid error if symbol void.
11604 Special case: if value of symbol is a string, output the string
11605 literally. */
11606 {
11607 register Lisp_Object tem;
11608 tem = Fboundp (elt);
265a9e55 11609 if (!NILP (tem))
a2889657
JB
11610 {
11611 tem = Fsymbol_value (elt);
11612 /* If value is a string, output that string literally:
11613 don't check for % within it. */
e24c997d 11614 if (STRINGP (tem))
d39b6696 11615 {
5f5c8ee5
GM
11616 prec = XSTRING (tem)->size;
11617 if (precision > 0 && prec > precision - n)
11618 prec = precision - n;
d39b6696 11619 if (frame_title_ptr)
5f5c8ee5 11620 n += store_frame_title (XSTRING (tem)->data, -1, prec);
d39b6696 11621 else
5f5c8ee5
GM
11622 n += display_string (NULL, tem, Qnil, 0, 0, it,
11623 0, prec, 0, -1);
d39b6696 11624 }
a2889657 11625 else if (!EQ (tem, elt))
5f5c8ee5
GM
11626 {
11627 /* Give up right away for nil or t. */
11628 elt = tem;
11629 goto tail_recurse;
11630 }
a2889657
JB
11631 }
11632 }
11633 break;
11634
11635 case Lisp_Cons:
11636 {
11637 register Lisp_Object car, tem;
11638
11639 /* A cons cell: three distinct cases.
11640 If first element is a string or a cons, process all the elements
11641 and effectively concatenate them.
11642 If first element is a negative number, truncate displaying cdr to
11643 at most that many characters. If positive, pad (with spaces)
11644 to at least that many characters.
11645 If first element is a symbol, process the cadr or caddr recursively
11646 according to whether the symbol's value is non-nil or nil. */
9472f927 11647 car = XCAR (elt);
5f5c8ee5
GM
11648 if (EQ (car, QCeval) && CONSP (XCDR (elt)))
11649 {
11650 /* An element of the form (:eval FORM) means evaluate FORM
11651 and use the result as mode line elements. */
11652 struct gcpro gcpro1;
11653 Lisp_Object spec;
11654
11655 spec = eval_form (XCAR (XCDR (elt)));
11656 GCPRO1 (spec);
11657 n += display_mode_element (it, depth, field_width - n,
11658 precision - n, spec);
11659 UNGCPRO;
11660 }
11661 else if (SYMBOLP (car))
a2889657
JB
11662 {
11663 tem = Fboundp (car);
9472f927 11664 elt = XCDR (elt);
e24c997d 11665 if (!CONSP (elt))
a2889657
JB
11666 goto invalid;
11667 /* elt is now the cdr, and we know it is a cons cell.
11668 Use its car if CAR has a non-nil value. */
265a9e55 11669 if (!NILP (tem))
a2889657
JB
11670 {
11671 tem = Fsymbol_value (car);
265a9e55 11672 if (!NILP (tem))
9472f927
GM
11673 {
11674 elt = XCAR (elt);
11675 goto tail_recurse;
11676 }
a2889657
JB
11677 }
11678 /* Symbol's value is nil (or symbol is unbound)
11679 Get the cddr of the original list
11680 and if possible find the caddr and use that. */
9472f927 11681 elt = XCDR (elt);
265a9e55 11682 if (NILP (elt))
a2889657 11683 break;
e24c997d 11684 else if (!CONSP (elt))
a2889657 11685 goto invalid;
9472f927 11686 elt = XCAR (elt);
a2889657
JB
11687 goto tail_recurse;
11688 }
e24c997d 11689 else if (INTEGERP (car))
a2889657
JB
11690 {
11691 register int lim = XINT (car);
9472f927 11692 elt = XCDR (elt);
a2889657 11693 if (lim < 0)
5f5c8ee5
GM
11694 {
11695 /* Negative int means reduce maximum width. */
11696 if (precision <= 0)
11697 precision = -lim;
11698 else
11699 precision = min (precision, -lim);
11700 }
a2889657
JB
11701 else if (lim > 0)
11702 {
11703 /* Padding specified. Don't let it be more than
11704 current maximum. */
5f5c8ee5
GM
11705 if (precision > 0)
11706 lim = min (precision, lim);
11707
a2889657
JB
11708 /* If that's more padding than already wanted, queue it.
11709 But don't reduce padding already specified even if
11710 that is beyond the current truncation point. */
5f5c8ee5 11711 field_width = max (lim, field_width);
a2889657
JB
11712 }
11713 goto tail_recurse;
11714 }
e24c997d 11715 else if (STRINGP (car) || CONSP (car))
a2889657
JB
11716 {
11717 register int limit = 50;
5f5c8ee5
GM
11718 /* Limit is to protect against circular lists. */
11719 while (CONSP (elt)
11720 && --limit > 0
11721 && (precision <= 0 || n < precision))
a2889657 11722 {
5f5c8ee5 11723 n += display_mode_element (it, depth, field_width - n,
9472f927
GM
11724 precision - n, XCAR (elt));
11725 elt = XCDR (elt);
a2889657
JB
11726 }
11727 }
11728 }
11729 break;
11730
11731 default:
11732 invalid:
d39b6696 11733 if (frame_title_ptr)
5f5c8ee5 11734 n += store_frame_title ("*invalid*", 0, precision - n);
d39b6696 11735 else
5f5c8ee5
GM
11736 n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
11737 precision - n, 0, 0);
11738 return n;
a2889657
JB
11739 }
11740
5f5c8ee5
GM
11741 /* Pad to FIELD_WIDTH. */
11742 if (field_width > 0 && n < field_width)
11743 {
11744 if (frame_title_ptr)
11745 n += store_frame_title ("", field_width - n, 0);
11746 else
11747 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
11748 0, 0, 0);
11749 }
11750
11751 return n;
a2889657 11752}
5f5c8ee5
GM
11753
11754
766525bc
RS
11755/* Write a null-terminated, right justified decimal representation of
11756 the positive integer D to BUF using a minimal field width WIDTH. */
11757
11758static void
11759pint2str (buf, width, d)
11760 register char *buf;
11761 register int width;
11762 register int d;
11763{
11764 register char *p = buf;
11765
11766 if (d <= 0)
5f5c8ee5 11767 *p++ = '0';
766525bc 11768 else
5f5c8ee5 11769 {
766525bc 11770 while (d > 0)
5f5c8ee5 11771 {
766525bc
RS
11772 *p++ = d % 10 + '0';
11773 d /= 10;
5f5c8ee5
GM
11774 }
11775 }
11776
11777 for (width -= (int) (p - buf); width > 0; --width)
11778 *p++ = ' ';
766525bc
RS
11779 *p-- = '\0';
11780 while (p > buf)
5f5c8ee5 11781 {
766525bc
RS
11782 d = *buf;
11783 *buf++ = *p;
11784 *p-- = d;
5f5c8ee5 11785 }
766525bc
RS
11786}
11787
5f5c8ee5 11788/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
11789 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
11790 type of CODING_SYSTEM. Return updated pointer into BUF. */
11791
6693a99a 11792static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 11793
1c9241f5
KH
11794static char *
11795decode_mode_spec_coding (coding_system, buf, eol_flag)
11796 Lisp_Object coding_system;
11797 register char *buf;
11798 int eol_flag;
11799{
1e1078d6 11800 Lisp_Object val;
916848d8 11801 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
302f2b38
EZ
11802 unsigned char *eol_str;
11803 int eol_str_len;
11804 /* The EOL conversion we are using. */
11805 Lisp_Object eoltype;
1e1078d6
RS
11806
11807 val = coding_system;
1c9241f5
KH
11808
11809 if (NILP (val)) /* Not yet decided. */
11810 {
916848d8
RS
11811 if (multibyte)
11812 *buf++ = '-';
21e989e3 11813 if (eol_flag)
302f2b38 11814 eoltype = eol_mnemonic_undecided;
1e1078d6 11815 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
11816 }
11817 else
11818 {
1e1078d6
RS
11819 Lisp_Object eolvalue;
11820
11821 eolvalue = Fget (coding_system, Qeol_type);
11822
1c9241f5 11823 while (!NILP (val) && SYMBOLP (val))
1e1078d6
RS
11824 {
11825 val = Fget (val, Qcoding_system);
11826 if (NILP (eolvalue))
b070c1d7 11827 eolvalue = Fget (val, Qeol_type);
1e1078d6
RS
11828 }
11829
916848d8
RS
11830 if (multibyte)
11831 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
11832
1c9241f5
KH
11833 if (eol_flag)
11834 {
1e1078d6
RS
11835 /* The EOL conversion that is normal on this system. */
11836
11837 if (NILP (eolvalue)) /* Not yet decided. */
11838 eoltype = eol_mnemonic_undecided;
11839 else if (VECTORP (eolvalue)) /* Not yet decided. */
11840 eoltype = eol_mnemonic_undecided;
11841 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
11842 eoltype = (XFASTINT (eolvalue) == 0
11843 ? eol_mnemonic_unix
11844 : (XFASTINT (eolvalue) == 1
11845 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
11846 }
11847 }
5f5c8ee5 11848
302f2b38
EZ
11849 if (eol_flag)
11850 {
11851 /* Mention the EOL conversion if it is not the usual one. */
11852 if (STRINGP (eoltype))
11853 {
11854 eol_str = XSTRING (eoltype)->data;
11855 eol_str_len = XSTRING (eoltype)->size;
11856 }
f30b3499
KH
11857 else if (INTEGERP (eoltype)
11858 && CHAR_VALID_P (XINT (eoltype), 0))
11859 {
f30b3499
KH
11860 unsigned char work[4];
11861
11862 eol_str_len = CHAR_STRING (XINT (eoltype), work, eol_str);
11863 }
302f2b38
EZ
11864 else
11865 {
11866 eol_str = invalid_eol_type;
11867 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 11868 }
f30b3499 11869 bcopy (eol_str, buf, eol_str_len);
302f2b38 11870 buf += eol_str_len;
1c9241f5 11871 }
302f2b38 11872
1c9241f5
KH
11873 return buf;
11874}
11875
a2889657 11876/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
11877 generated by character C. PRECISION >= 0 means don't return a
11878 string longer than that value. FIELD_WIDTH > 0 means pad the
11879 string returned with spaces to that value. */
a2889657 11880
11e82b76
JB
11881static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
11882
a2889657 11883static char *
5f5c8ee5 11884decode_mode_spec (w, c, field_width, precision)
a2889657
JB
11885 struct window *w;
11886 register char c;
5f5c8ee5 11887 int field_width, precision;
a2889657 11888{
0b67772d 11889 Lisp_Object obj;
5f5c8ee5
GM
11890 struct frame *f = XFRAME (WINDOW_FRAME (w));
11891 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 11892 struct buffer *b = XBUFFER (w->buffer);
a2889657 11893
0b67772d 11894 obj = Qnil;
a2889657
JB
11895
11896 switch (c)
11897 {
1af9f229
RS
11898 case '*':
11899 if (!NILP (b->read_only))
11900 return "%";
11901 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
11902 return "*";
11903 return "-";
11904
11905 case '+':
11906 /* This differs from %* only for a modified read-only buffer. */
11907 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
11908 return "*";
11909 if (!NILP (b->read_only))
11910 return "%";
11911 return "-";
11912
11913 case '&':
11914 /* This differs from %* in ignoring read-only-ness. */
11915 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
11916 return "*";
11917 return "-";
11918
11919 case '%':
11920 return "%";
11921
11922 case '[':
11923 {
11924 int i;
11925 char *p;
11926
11927 if (command_loop_level > 5)
11928 return "[[[... ";
11929 p = decode_mode_spec_buf;
11930 for (i = 0; i < command_loop_level; i++)
11931 *p++ = '[';
11932 *p = 0;
11933 return decode_mode_spec_buf;
11934 }
11935
11936 case ']':
11937 {
11938 int i;
11939 char *p;
11940
11941 if (command_loop_level > 5)
11942 return " ...]]]";
11943 p = decode_mode_spec_buf;
11944 for (i = 0; i < command_loop_level; i++)
11945 *p++ = ']';
11946 *p = 0;
11947 return decode_mode_spec_buf;
11948 }
11949
11950 case '-':
11951 {
1af9f229 11952 register int i;
5f5c8ee5
GM
11953
11954 /* Let lots_of_dashes be a string of infinite length. */
11955 if (field_width <= 0
11956 || field_width > sizeof (lots_of_dashes))
1af9f229 11957 {
5f5c8ee5
GM
11958 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
11959 decode_mode_spec_buf[i] = '-';
11960 decode_mode_spec_buf[i] = '\0';
11961 return decode_mode_spec_buf;
1af9f229 11962 }
5f5c8ee5
GM
11963 else
11964 return lots_of_dashes;
1af9f229
RS
11965 }
11966
a2889657 11967 case 'b':
d39b6696 11968 obj = b->name;
a2889657
JB
11969 break;
11970
1af9f229
RS
11971 case 'c':
11972 {
11973 int col = current_column ();
11974 XSETFASTINT (w->column_number_displayed, col);
5f5c8ee5 11975 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
11976 return decode_mode_spec_buf;
11977 }
11978
11979 case 'F':
11980 /* %F displays the frame name. */
5f5c8ee5 11981 if (!NILP (f->title))
95184b48 11982 return (char *) XSTRING (f->title)->data;
fd8ff63d 11983 if (f->explicit_name || ! FRAME_WINDOW_P (f))
95184b48 11984 return (char *) XSTRING (f->name)->data;
9c6da96f 11985 return "Emacs";
1af9f229 11986
a2889657 11987 case 'f':
d39b6696 11988 obj = b->filename;
a2889657
JB
11989 break;
11990
aa6d10fa
RS
11991 case 'l':
11992 {
12adba34
RS
11993 int startpos = XMARKER (w->start)->charpos;
11994 int startpos_byte = marker_byte_position (w->start);
11995 int line, linepos, linepos_byte, topline;
aa6d10fa 11996 int nlines, junk;
aa6d10fa
RS
11997 int height = XFASTINT (w->height);
11998
11999 /* If we decided that this buffer isn't suitable for line numbers,
12000 don't forget that too fast. */
12001 if (EQ (w->base_line_pos, w->buffer))
766525bc 12002 goto no_value;
5300fd39
RS
12003 /* But do forget it, if the window shows a different buffer now. */
12004 else if (BUFFERP (w->base_line_pos))
12005 w->base_line_pos = Qnil;
aa6d10fa
RS
12006
12007 /* If the buffer is very big, don't waste time. */
d39b6696 12008 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
aa6d10fa
RS
12009 {
12010 w->base_line_pos = Qnil;
12011 w->base_line_number = Qnil;
766525bc 12012 goto no_value;
aa6d10fa
RS
12013 }
12014
12015 if (!NILP (w->base_line_number)
12016 && !NILP (w->base_line_pos)
12adba34 12017 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
12018 {
12019 line = XFASTINT (w->base_line_number);
12020 linepos = XFASTINT (w->base_line_pos);
12adba34 12021 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
12022 }
12023 else
12024 {
12025 line = 1;
d39b6696 12026 linepos = BUF_BEGV (b);
12adba34 12027 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
12028 }
12029
12030 /* Count lines from base line to window start position. */
12adba34
RS
12031 nlines = display_count_lines (linepos, linepos_byte,
12032 startpos_byte,
12033 startpos, &junk);
aa6d10fa
RS
12034
12035 topline = nlines + line;
12036
12037 /* Determine a new base line, if the old one is too close
12038 or too far away, or if we did not have one.
12039 "Too close" means it's plausible a scroll-down would
12040 go back past it. */
d39b6696 12041 if (startpos == BUF_BEGV (b))
aa6d10fa 12042 {
c2213350
KH
12043 XSETFASTINT (w->base_line_number, topline);
12044 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
12045 }
12046 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 12047 || linepos == BUF_BEGV (b))
aa6d10fa 12048 {
d39b6696 12049 int limit = BUF_BEGV (b);
12adba34 12050 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 12051 int position;
5d121aec 12052 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
12053
12054 if (startpos - distance > limit)
12adba34
RS
12055 {
12056 limit = startpos - distance;
12057 limit_byte = CHAR_TO_BYTE (limit);
12058 }
aa6d10fa 12059
12adba34
RS
12060 nlines = display_count_lines (startpos, startpos_byte,
12061 limit_byte,
12062 - (height * 2 + 30),
aa6d10fa
RS
12063 &position);
12064 /* If we couldn't find the lines we wanted within
5d121aec 12065 line_number_display_limit_width chars per line,
aa6d10fa 12066 give up on line numbers for this window. */
12adba34 12067 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
12068 {
12069 w->base_line_pos = w->buffer;
12070 w->base_line_number = Qnil;
766525bc 12071 goto no_value;
aa6d10fa
RS
12072 }
12073
c2213350 12074 XSETFASTINT (w->base_line_number, topline - nlines);
12adba34 12075 XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
aa6d10fa
RS
12076 }
12077
12078 /* Now count lines from the start pos to point. */
12adba34
RS
12079 nlines = display_count_lines (startpos, startpos_byte,
12080 PT_BYTE, PT, &junk);
aa6d10fa
RS
12081
12082 /* Record that we did display the line number. */
12083 line_number_displayed = 1;
12084
12085 /* Make the string to show. */
5f5c8ee5 12086 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 12087 return decode_mode_spec_buf;
766525bc
RS
12088 no_value:
12089 {
12090 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
12091 int pad = field_width - 2;
12092 while (pad-- > 0)
12093 *p++ = ' ';
12094 *p++ = '?';
12095 *p = '?';
766525bc
RS
12096 return decode_mode_spec_buf;
12097 }
aa6d10fa
RS
12098 }
12099 break;
12100
a2889657 12101 case 'm':
d39b6696 12102 obj = b->mode_name;
a2889657
JB
12103 break;
12104
12105 case 'n':
d39b6696 12106 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
12107 return " Narrow";
12108 break;
12109
a2889657
JB
12110 case 'p':
12111 {
12112 int pos = marker_position (w->start);
d39b6696 12113 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 12114
d39b6696 12115 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 12116 {
d39b6696 12117 if (pos <= BUF_BEGV (b))
a2889657
JB
12118 return "All";
12119 else
12120 return "Bottom";
12121 }
d39b6696 12122 else if (pos <= BUF_BEGV (b))
a2889657
JB
12123 return "Top";
12124 else
12125 {
3c7d31b9
RS
12126 if (total > 1000000)
12127 /* Do it differently for a large value, to avoid overflow. */
12128 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12129 else
12130 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
12131 /* We can't normally display a 3-digit number,
12132 so get us a 2-digit number that is close. */
12133 if (total == 100)
12134 total = 99;
12135 sprintf (decode_mode_spec_buf, "%2d%%", total);
12136 return decode_mode_spec_buf;
12137 }
12138 }
12139
8ffcb79f
RS
12140 /* Display percentage of size above the bottom of the screen. */
12141 case 'P':
12142 {
12143 int toppos = marker_position (w->start);
d39b6696
KH
12144 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
12145 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 12146
d39b6696 12147 if (botpos >= BUF_ZV (b))
8ffcb79f 12148 {
d39b6696 12149 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12150 return "All";
12151 else
12152 return "Bottom";
12153 }
12154 else
12155 {
3c7d31b9
RS
12156 if (total > 1000000)
12157 /* Do it differently for a large value, to avoid overflow. */
12158 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12159 else
12160 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
12161 /* We can't normally display a 3-digit number,
12162 so get us a 2-digit number that is close. */
12163 if (total == 100)
12164 total = 99;
d39b6696 12165 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12166 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
12167 else
12168 sprintf (decode_mode_spec_buf, "%2d%%", total);
12169 return decode_mode_spec_buf;
12170 }
12171 }
12172
1af9f229
RS
12173 case 's':
12174 /* status of process */
12175 obj = Fget_buffer_process (w->buffer);
12176 if (NILP (obj))
12177 return "no process";
12178#ifdef subprocesses
12179 obj = Fsymbol_name (Fprocess_status (obj));
12180#endif
12181 break;
d39b6696 12182
1af9f229
RS
12183 case 't': /* indicate TEXT or BINARY */
12184#ifdef MODE_LINE_BINARY_TEXT
12185 return MODE_LINE_BINARY_TEXT (b);
12186#else
12187 return "T";
12188#endif
1c9241f5
KH
12189
12190 case 'z':
12191 /* coding-system (not including end-of-line format) */
12192 case 'Z':
12193 /* coding-system (including end-of-line type) */
12194 {
12195 int eol_flag = (c == 'Z');
539b4d41 12196 char *p = decode_mode_spec_buf;
1c9241f5 12197
d30e754b 12198 if (! FRAME_WINDOW_P (f))
1c9241f5 12199 {
11c52c4f
RS
12200 /* No need to mention EOL here--the terminal never needs
12201 to do EOL conversion. */
12202 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
12203 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 12204 }
f13c925f 12205 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 12206 p, eol_flag);
f13c925f 12207
11c52c4f 12208#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
12209#ifdef subprocesses
12210 obj = Fget_buffer_process (Fcurrent_buffer ());
12211 if (PROCESSP (obj))
12212 {
12213 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
12214 p, eol_flag);
12215 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
12216 p, eol_flag);
12217 }
12218#endif /* subprocesses */
11c52c4f 12219#endif /* 0 */
1c9241f5
KH
12220 *p = 0;
12221 return decode_mode_spec_buf;
12222 }
a2889657 12223 }
d39b6696 12224
e24c997d 12225 if (STRINGP (obj))
a2889657
JB
12226 return (char *) XSTRING (obj)->data;
12227 else
12228 return "";
12229}
5f5c8ee5
GM
12230
12231
12adba34
RS
12232/* Count up to COUNT lines starting from START / START_BYTE.
12233 But don't go beyond LIMIT_BYTE.
12234 Return the number of lines thus found (always nonnegative).
59b49f63 12235
12adba34 12236 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
12237
12238static int
12adba34
RS
12239display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
12240 int start, start_byte, limit_byte, count;
12241 int *byte_pos_ptr;
59b49f63 12242{
59b49f63
RS
12243 register unsigned char *cursor;
12244 unsigned char *base;
12245
12246 register int ceiling;
12247 register unsigned char *ceiling_addr;
12adba34 12248 int orig_count = count;
59b49f63
RS
12249
12250 /* If we are not in selective display mode,
12251 check only for newlines. */
12adba34
RS
12252 int selective_display = (!NILP (current_buffer->selective_display)
12253 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
12254
12255 if (count > 0)
12adba34
RS
12256 {
12257 while (start_byte < limit_byte)
12258 {
12259 ceiling = BUFFER_CEILING_OF (start_byte);
12260 ceiling = min (limit_byte - 1, ceiling);
12261 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
12262 base = (cursor = BYTE_POS_ADDR (start_byte));
12263 while (1)
12264 {
12265 if (selective_display)
12266 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
12267 ;
12268 else
12269 while (*cursor != '\n' && ++cursor != ceiling_addr)
12270 ;
12271
12272 if (cursor != ceiling_addr)
12273 {
12274 if (--count == 0)
12275 {
12276 start_byte += cursor - base + 1;
12277 *byte_pos_ptr = start_byte;
12278 return orig_count;
12279 }
12280 else
12281 if (++cursor == ceiling_addr)
12282 break;
12283 }
12284 else
12285 break;
12286 }
12287 start_byte += cursor - base;
12288 }
12289 }
59b49f63
RS
12290 else
12291 {
12adba34
RS
12292 while (start_byte > limit_byte)
12293 {
12294 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
12295 ceiling = max (limit_byte, ceiling);
12296 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
12297 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
12298 while (1)
12299 {
12adba34
RS
12300 if (selective_display)
12301 while (--cursor != ceiling_addr
12302 && *cursor != '\n' && *cursor != 015)
12303 ;
12304 else
12305 while (--cursor != ceiling_addr && *cursor != '\n')
12306 ;
12307
59b49f63
RS
12308 if (cursor != ceiling_addr)
12309 {
12310 if (++count == 0)
12311 {
12adba34
RS
12312 start_byte += cursor - base + 1;
12313 *byte_pos_ptr = start_byte;
12314 /* When scanning backwards, we should
12315 not count the newline posterior to which we stop. */
12316 return - orig_count - 1;
59b49f63
RS
12317 }
12318 }
12319 else
12320 break;
12321 }
12adba34
RS
12322 /* Here we add 1 to compensate for the last decrement
12323 of CURSOR, which took it past the valid range. */
12324 start_byte += cursor - base + 1;
59b49f63
RS
12325 }
12326 }
12327
12adba34 12328 *byte_pos_ptr = limit_byte;
aa6d10fa 12329
12adba34
RS
12330 if (count < 0)
12331 return - orig_count + count;
12332 return orig_count - count;
aa6d10fa 12333
12adba34 12334}
a2889657 12335
a2889657 12336
5f5c8ee5
GM
12337\f
12338/***********************************************************************
12339 Displaying strings
12340 ***********************************************************************/
278feba9 12341
5f5c8ee5 12342/* Display a NUL-terminated string, starting with index START.
a3788d53 12343
5f5c8ee5
GM
12344 If STRING is non-null, display that C string. Otherwise, the Lisp
12345 string LISP_STRING is displayed.
a2889657 12346
5f5c8ee5
GM
12347 If FACE_STRING is not nil, FACE_STRING_POS is a position in
12348 FACE_STRING. Display STRING or LISP_STRING with the face at
12349 FACE_STRING_POS in FACE_STRING:
a2889657 12350
5f5c8ee5
GM
12351 Display the string in the environment given by IT, but use the
12352 standard display table, temporarily.
a3788d53 12353
5f5c8ee5
GM
12354 FIELD_WIDTH is the minimum number of output glyphs to produce.
12355 If STRING has fewer characters than FIELD_WIDTH, pad to the right
12356 with spaces. If STRING has more characters, more than FIELD_WIDTH
12357 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
12358
12359 PRECISION is the maximum number of characters to output from
12360 STRING. PRECISION < 0 means don't truncate the string.
a2889657 12361
5f5c8ee5 12362 This is roughly equivalent to printf format specifiers:
a2889657 12363
5f5c8ee5
GM
12364 FIELD_WIDTH PRECISION PRINTF
12365 ----------------------------------------
12366 -1 -1 %s
12367 -1 10 %.10s
12368 10 -1 %10s
12369 20 10 %20.10s
a2889657 12370
5f5c8ee5
GM
12371 MULTIBYTE zero means do not display multibyte chars, > 0 means do
12372 display them, and < 0 means obey the current buffer's value of
12373 enable_multibyte_characters.
278feba9 12374
5f5c8ee5 12375 Value is the number of glyphs produced. */
b1d1124b 12376
5f5c8ee5
GM
12377static int
12378display_string (string, lisp_string, face_string, face_string_pos,
12379 start, it, field_width, precision, max_x, multibyte)
12380 unsigned char *string;
12381 Lisp_Object lisp_string;
12382 int start;
12383 struct it *it;
12384 int field_width, precision, max_x;
12385 int multibyte;
12386{
12387 int hpos_at_start = it->hpos;
12388 int saved_face_id = it->face_id;
12389 struct glyph_row *row = it->glyph_row;
12390
12391 /* Initialize the iterator IT for iteration over STRING beginning
12392 with index START. We assume that IT may be modified here (which
12393 means that display_line has to do something when displaying a
12394 mini-buffer prompt, which it does). */
12395 reseat_to_string (it, string, lisp_string, start,
12396 precision, field_width, multibyte);
12397
12398 /* If displaying STRING, set up the face of the iterator
12399 from LISP_STRING, if that's given. */
12400 if (STRINGP (face_string))
12401 {
12402 int endptr;
12403 struct face *face;
12404
12405 it->face_id
12406 = face_at_string_position (it->w, face_string, face_string_pos,
12407 0, it->region_beg_charpos,
12408 it->region_end_charpos,
12409 &endptr, it->base_face_id);
12410 face = FACE_FROM_ID (it->f, it->face_id);
12411 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 12412 }
a2889657 12413
5f5c8ee5
GM
12414 /* Set max_x to the maximum allowed X position. Don't let it go
12415 beyond the right edge of the window. */
12416 if (max_x <= 0)
12417 max_x = it->last_visible_x;
12418 else
12419 max_x = min (max_x, it->last_visible_x);
efc63ef0 12420
5f5c8ee5
GM
12421 /* Skip over display elements that are not visible. because IT->w is
12422 hscrolled. */
12423 if (it->current_x < it->first_visible_x)
12424 move_it_in_display_line_to (it, 100000, it->first_visible_x,
12425 MOVE_TO_POS | MOVE_TO_X);
a2889657 12426
5f5c8ee5
GM
12427 row->ascent = it->max_ascent;
12428 row->height = it->max_ascent + it->max_descent;
312246d1
GM
12429 row->phys_ascent = it->max_phys_ascent;
12430 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 12431
5f5c8ee5
GM
12432 /* This condition is for the case that we are called with current_x
12433 past last_visible_x. */
12434 while (it->current_x < max_x)
a2889657 12435 {
5f5c8ee5 12436 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 12437
5f5c8ee5
GM
12438 /* Get the next display element. */
12439 if (!get_next_display_element (it))
90adcf20 12440 break;
1c9241f5 12441
5f5c8ee5
GM
12442 /* Produce glyphs. */
12443 x_before = it->current_x;
12444 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
12445 PRODUCE_GLYPHS (it);
90adcf20 12446
5f5c8ee5
GM
12447 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
12448 i = 0;
12449 x = x_before;
12450 while (i < nglyphs)
a2889657 12451 {
5f5c8ee5
GM
12452 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
12453
12454 if (!it->truncate_lines_p
12455 && x + glyph->pixel_width > max_x)
12456 {
12457 /* End of continued line or max_x reached. */
12458 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
12459 it->current_x = x;
12460 break;
12461 }
12462 else if (x + glyph->pixel_width > it->first_visible_x)
12463 {
12464 /* Glyph is at least partially visible. */
12465 ++it->hpos;
12466 if (x < it->first_visible_x)
12467 it->glyph_row->x = x - it->first_visible_x;
12468 }
12469 else
a2889657 12470 {
5f5c8ee5
GM
12471 /* Glyph is off the left margin of the display area.
12472 Should not happen. */
12473 abort ();
a2889657 12474 }
5f5c8ee5
GM
12475
12476 row->ascent = max (row->ascent, it->max_ascent);
12477 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
12478 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
12479 row->phys_height = max (row->phys_height,
12480 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
12481 x += glyph->pixel_width;
12482 ++i;
a2889657 12483 }
5f5c8ee5
GM
12484
12485 /* Stop if max_x reached. */
12486 if (i < nglyphs)
12487 break;
12488
12489 /* Stop at line ends. */
12490 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 12491 {
5f5c8ee5
GM
12492 it->continuation_lines_width = 0;
12493 break;
a2889657 12494 }
1c9241f5 12495
5f5c8ee5 12496 set_iterator_to_next (it);
a688bb24 12497
5f5c8ee5
GM
12498 /* Stop if truncating at the right edge. */
12499 if (it->truncate_lines_p
12500 && it->current_x >= it->last_visible_x)
12501 {
12502 /* Add truncation mark, but don't do it if the line is
12503 truncated at a padding space. */
12504 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 12505 {
5f5c8ee5
GM
12506 if (!FRAME_WINDOW_P (it->f))
12507 produce_special_glyphs (it, IT_TRUNCATION);
12508 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 12509 }
5f5c8ee5 12510 break;
1c9241f5 12511 }
a2889657
JB
12512 }
12513
5f5c8ee5
GM
12514 /* Maybe insert a truncation at the left. */
12515 if (it->first_visible_x
12516 && IT_CHARPOS (*it) > 0)
a2889657 12517 {
5f5c8ee5
GM
12518 if (!FRAME_WINDOW_P (it->f))
12519 insert_left_trunc_glyphs (it);
12520 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
12521 }
12522
5f5c8ee5
GM
12523 it->face_id = saved_face_id;
12524
12525 /* Value is number of columns displayed. */
12526 return it->hpos - hpos_at_start;
12527}
a2889657 12528
a2889657 12529
a2889657 12530\f
5f5c8ee5
GM
12531/* This is like a combination of memq and assq. Return 1 if PROPVAL
12532 appears as an element of LIST or as the car of an element of LIST.
12533 If PROPVAL is a list, compare each element against LIST in that
12534 way, and return 1 if any element of PROPVAL is found in LIST.
12535 Otherwise return 0. This function cannot quit. */
642eefc6
RS
12536
12537int
12538invisible_p (propval, list)
12539 register Lisp_Object propval;
12540 Lisp_Object list;
12541{
af460d46 12542 register Lisp_Object tail, proptail;
9472f927 12543 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
12544 {
12545 register Lisp_Object tem;
9472f927 12546 tem = XCAR (tail);
642eefc6
RS
12547 if (EQ (propval, tem))
12548 return 1;
9472f927 12549 if (CONSP (tem) && EQ (propval, XCAR (tem)))
642eefc6
RS
12550 return 1;
12551 }
af460d46
RS
12552 if (CONSP (propval))
12553 for (proptail = propval; CONSP (proptail);
9472f927 12554 proptail = XCDR (proptail))
af460d46
RS
12555 {
12556 Lisp_Object propelt;
9472f927
GM
12557 propelt = XCAR (proptail);
12558 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
12559 {
12560 register Lisp_Object tem;
9472f927 12561 tem = XCAR (tail);
af460d46
RS
12562 if (EQ (propelt, tem))
12563 return 1;
9472f927 12564 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
af460d46
RS
12565 return 1;
12566 }
12567 }
642eefc6
RS
12568 return 0;
12569}
12570
5f5c8ee5
GM
12571
12572/* Return 1 if PROPVAL appears as the car of an element of LIST and
12573 the cdr of that element is non-nil. If PROPVAL is a list, check
12574 each element of PROPVAL in that way, and the first time some
12575 element is found, return 1 if the cdr of that element is non-nil.
12576 Otherwise return 0. This function cannot quit. */
642eefc6
RS
12577
12578int
12579invisible_ellipsis_p (propval, list)
12580 register Lisp_Object propval;
12581 Lisp_Object list;
12582{
af460d46 12583 register Lisp_Object tail, proptail;
9472f927
GM
12584
12585 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
12586 {
12587 register Lisp_Object tem;
9472f927
GM
12588 tem = XCAR (tail);
12589 if (CONSP (tem) && EQ (propval, XCAR (tem)))
12590 return ! NILP (XCDR (tem));
642eefc6 12591 }
9472f927 12592
af460d46 12593 if (CONSP (propval))
9472f927 12594 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
af460d46
RS
12595 {
12596 Lisp_Object propelt;
9472f927
GM
12597 propelt = XCAR (proptail);
12598 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
12599 {
12600 register Lisp_Object tem;
9472f927
GM
12601 tem = XCAR (tail);
12602 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
12603 return ! NILP (XCDR (tem));
af460d46
RS
12604 }
12605 }
9472f927 12606
642eefc6
RS
12607 return 0;
12608}
5f5c8ee5
GM
12609
12610
642eefc6 12611\f
5f5c8ee5
GM
12612/***********************************************************************
12613 Initialization
12614 ***********************************************************************/
12615
a2889657
JB
12616void
12617syms_of_xdisp ()
12618{
c6e89d6c
GM
12619 Vwith_echo_area_save_vector = Qnil;
12620 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 12621
c6e89d6c
GM
12622 Vmessage_stack = Qnil;
12623 staticpro (&Vmessage_stack);
12624
735c094c 12625 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 12626 staticpro (&Qinhibit_redisplay);
735c094c 12627
5f5c8ee5
GM
12628#if GLYPH_DEBUG
12629 defsubr (&Sdump_glyph_matrix);
12630 defsubr (&Sdump_glyph_row);
e037b9ec 12631 defsubr (&Sdump_tool_bar_row);
5f5c8ee5
GM
12632 defsubr (&Strace_redisplay_toggle);
12633#endif
12634
cf074754
RS
12635 staticpro (&Qmenu_bar_update_hook);
12636 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
12637
d46fb96a 12638 staticpro (&Qoverriding_terminal_local_map);
7079aefa 12639 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 12640
399164b4
KH
12641 staticpro (&Qoverriding_local_map);
12642 Qoverriding_local_map = intern ("overriding-local-map");
12643
75c43375
RS
12644 staticpro (&Qwindow_scroll_functions);
12645 Qwindow_scroll_functions = intern ("window-scroll-functions");
12646
e0bfbde6
RS
12647 staticpro (&Qredisplay_end_trigger_functions);
12648 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
5f5c8ee5 12649
2e54982e
RS
12650 staticpro (&Qinhibit_point_motion_hooks);
12651 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
12652
5f5c8ee5 12653 Qdisplay = intern ("display");
f3751a65 12654 staticpro (&Qdisplay);
5f5c8ee5
GM
12655 Qspace_width = intern ("space-width");
12656 staticpro (&Qspace_width);
12657 Qheight = intern ("height");
12658 staticpro (&Qheight);
12659 Qraise = intern ("raise");
12660 staticpro (&Qraise);
12661 Qspace = intern ("space");
12662 staticpro (&Qspace);
f3751a65
GM
12663 Qmargin = intern ("margin");
12664 staticpro (&Qmargin);
5f5c8ee5 12665 Qleft_margin = intern ("left-margin");
f3751a65 12666 staticpro (&Qleft_margin);
5f5c8ee5 12667 Qright_margin = intern ("right-margin");
f3751a65 12668 staticpro (&Qright_margin);
5f5c8ee5
GM
12669 Qalign_to = intern ("align-to");
12670 staticpro (&Qalign_to);
12671 QCalign_to = intern (":align-to");
12672 staticpro (&QCalign_to);
12673 Qwidth = intern ("width");
12674 staticpro (&Qwidth);
12675 Qrelative_width = intern ("relative-width");
12676 staticpro (&Qrelative_width);
12677 QCrelative_width = intern (":relative-width");
12678 staticpro (&QCrelative_width);
12679 QCrelative_height = intern (":relative-height");
12680 staticpro (&QCrelative_height);
12681 QCeval = intern (":eval");
12682 staticpro (&QCeval);
d3acf96b 12683 Qwhen = intern ("when");
f3751a65 12684 staticpro (&Qwhen);
886bd6f2
GM
12685 QCfile = intern (":file");
12686 staticpro (&QCfile);
5f5c8ee5
GM
12687 Qfontified = intern ("fontified");
12688 staticpro (&Qfontified);
12689 Qfontification_functions = intern ("fontification-functions");
12690 staticpro (&Qfontification_functions);
5f5c8ee5
GM
12691 Qtrailing_whitespace = intern ("trailing-whitespace");
12692 staticpro (&Qtrailing_whitespace);
12693 Qimage = intern ("image");
12694 staticpro (&Qimage);
12695
a2889657
JB
12696 last_arrow_position = Qnil;
12697 last_arrow_string = Qnil;
f3751a65
GM
12698 staticpro (&last_arrow_position);
12699 staticpro (&last_arrow_string);
c6e89d6c
GM
12700
12701 echo_buffer[0] = echo_buffer[1] = Qnil;
12702 staticpro (&echo_buffer[0]);
12703 staticpro (&echo_buffer[1]);
12704
12705 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
12706 staticpro (&echo_area_buffer[0]);
12707 staticpro (&echo_area_buffer[1]);
a2889657 12708
8f897821
GM
12709 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
12710 "Non-nil means highlight trailing whitespace.\n\
12711The face used for trailing whitespace is `trailing-whitespace'.");
12712 Vshow_trailing_whitespace = Qnil;
12713
735c094c
KH
12714 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
12715 "Non-nil means don't actually do any redisplay.\n\
12716This is used for internal purposes.");
12717 Vinhibit_redisplay = Qnil;
12718
a2889657 12719 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 12720 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
12721 Vglobal_mode_string = Qnil;
12722
12723 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
12724 "Marker for where to display an arrow on top of the buffer text.\n\
12725This must be the beginning of a line in order to work.\n\
12726See also `overlay-arrow-string'.");
12727 Voverlay_arrow_position = Qnil;
12728
12729 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
12730 "String to display as an arrow. See also `overlay-arrow-position'.");
12731 Voverlay_arrow_string = Qnil;
12732
12733 DEFVAR_INT ("scroll-step", &scroll_step,
12734 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
12735If that fails to bring point back on frame, point is centered instead.\n\
12736If this is zero, point is always centered after it moves off frame.");
a2889657 12737
0789adb2
RS
12738 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
12739 "*Scroll up to this many lines, to bring point back on screen.");
12740 scroll_conservatively = 0;
12741
9afd2168
RS
12742 DEFVAR_INT ("scroll-margin", &scroll_margin,
12743 "*Number of lines of margin at the top and bottom of a window.\n\
12744Recenter the window whenever point gets within this many lines\n\
12745of the top or bottom of the window.");
12746 scroll_margin = 0;
12747
5f5c8ee5 12748#if GLYPH_DEBUG
a2889657 12749 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
5f5c8ee5 12750#endif
a2889657
JB
12751
12752 DEFVAR_BOOL ("truncate-partial-width-windows",
12753 &truncate_partial_width_windows,
44fa5b1e 12754 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
12755 truncate_partial_width_windows = 1;
12756
12757 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
12758 "*Non-nil means use inverse video for the mode line.");
12759 mode_line_inverse_video = 1;
aa6d10fa
RS
12760
12761 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
5f5c8ee5 12762 "*Maximum buffer size for which line number should be displayed.\n\
db4f2bfa 12763If the buffer is bigger than this, the line number does not appear\n\
9f027393 12764in the mode line.");
aa6d10fa 12765 line_number_display_limit = 1000000;
fba9ce76 12766
5d121aec
KH
12767 DEFVAR_INT ("line-number-display-limit-width", &line_number_display_limit_width,
12768 "*Maximum line width (in characters) for line number display.\n\
12769If the average length of the lines near point is bigger than this, then the\n\
12770line number may be omitted from the mode line.");
12771 line_number_display_limit_width = 200;
12772
fba9ce76
RS
12773 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
12774 "*Non-nil means highlight region even in nonselected windows.");
293a54ce 12775 highlight_nonselected_windows = 0;
d39b6696
KH
12776
12777 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
12778 "Non-nil if more than one frame is visible on this display.\n\
12779Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
12780This variable is not guaranteed to be accurate except while processing\n\
12781`frame-title-format' and `icon-title-format'.");
d39b6696
KH
12782
12783 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
5f5c8ee5 12784 "Template for displaying the title bar of visible frames.\n\
d39b6696
KH
12785\(Assuming the window manager supports this feature.)\n\
12786This variable has the same structure as `mode-line-format' (which see),\n\
12787and is used only on frames for which no explicit name has been set\n\
12788\(see `modify-frame-parameters').");
12789 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
5f5c8ee5 12790 "Template for displaying the title bar of an iconified frame.\n\
d39b6696
KH
12791\(Assuming the window manager supports this feature.)\n\
12792This variable has the same structure as `mode-line-format' (which see),\n\
12793and is used only on frames for which no explicit name has been set\n\
12794\(see `modify-frame-parameters').");
12795 Vicon_title_format
12796 = Vframe_title_format
12797 = Fcons (intern ("multiple-frames"),
12798 Fcons (build_string ("%b"),
12799 Fcons (Fcons (build_string (""),
12800 Fcons (intern ("invocation-name"),
12801 Fcons (build_string ("@"),
12802 Fcons (intern ("system-name"),
12803 Qnil)))),
12804 Qnil)));
5992c4f7
KH
12805
12806 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
12807 "Maximum number of lines to keep in the message log buffer.\n\
12808If nil, disable message logging. If t, log messages but don't truncate\n\
12809the buffer when it becomes large.");
12810 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
12811
12812 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
12813 "Functions called before redisplay, if window sizes have changed.\n\
12814The value should be a list of functions that take one argument.\n\
12815Just before redisplay, for each frame, if any of its windows have changed\n\
12816size since the last redisplay, or have been split or deleted,\n\
12817all the functions in the list are called, with the frame as argument.");
12818 Vwindow_size_change_functions = Qnil;
75c43375
RS
12819
12820 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
5f5c8ee5 12821 "List of Functions to call before redisplaying a window with scrolling.\n\
75c43375 12822Each function is called with two arguments, the window\n\
8d9583b0
RS
12823and its new display-start position. Note that the value of `window-end'\n\
12824is not valid when these functions are called.");
75c43375 12825 Vwindow_scroll_functions = Qnil;
5f5c8ee5 12826
e037b9ec
GM
12827 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
12828 "*Non-nil means automatically resize tool-bars.\n\
12829This increases a tool-bar's height if not all tool-bar items are visible.\n\
12830It decreases a tool-bar's height when it would display blank lines\n\
5f5c8ee5 12831otherwise.");
e037b9ec 12832 auto_resize_tool_bars_p = 1;
5f5c8ee5 12833
e037b9ec
GM
12834 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
12835 "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
12836 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 12837
e037b9ec
GM
12838 DEFVAR_INT ("tool-bar-button-margin", &tool_bar_button_margin,
12839 "*Margin around tool-bar buttons in pixels.");
12840 tool_bar_button_margin = 1;
5f5c8ee5 12841
e037b9ec
GM
12842 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
12843 "Relief thickness of tool-bar buttons.");
12844 tool_bar_button_relief = 3;
5f5c8ee5
GM
12845
12846 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
12847 "List of functions to call to fontify regions of text.\n\
12848Each function is called with one argument POS. Functions must\n\
12849fontify a region starting at POS in the current buffer, and give\n\
12850fontified regions the property `fontified'.\n\
12851This variable automatically becomes buffer-local when set.");
12852 Vfontification_functions = Qnil;
12853 Fmake_local_variable (Qfontification_functions);
7bbe686f
AI
12854
12855 DEFVAR_BOOL ("unibyte-display-via-language-environment",
5f5c8ee5
GM
12856 &unibyte_display_via_language_environment,
12857 "*Non-nil means display unibyte text according to language environment.\n\
7bbe686f
AI
12858Specifically this means that unibyte non-ASCII characters\n\
12859are displayed by converting them to the equivalent multibyte characters\n\
12860according to the current language environment. As a result, they are\n\
12861displayed according to the current fontset.");
12862 unibyte_display_via_language_environment = 0;
c6e89d6c
GM
12863
12864 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
12865 "*Maximum height for resizing mini-windows.\n\
12866If a float, it specifies a fraction of the mini-window frame's height.\n\
97cafc0f
GM
12867If an integer, it specifies a number of lines.\n\
12868If nil, don't resize.");
c6e89d6c 12869 Vmax_mini_window_height = make_float (0.25);
a2889657
JB
12870}
12871
5f5c8ee5
GM
12872
12873/* Initialize this module when Emacs starts. */
12874
dfcf069d 12875void
a2889657
JB
12876init_xdisp ()
12877{
12878 Lisp_Object root_window;
5f5c8ee5 12879 struct window *mini_w;
a2889657 12880
5f5c8ee5 12881 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
12882
12883 mini_w = XWINDOW (minibuf_window);
11e82b76 12884 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 12885
a2889657
JB
12886 if (!noninteractive)
12887 {
5f5c8ee5
GM
12888 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
12889 int i;
12890
12891 XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f));
12c226c5 12892 set_window_height (root_window,
5f5c8ee5 12893 FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 12894 0);
c2213350 12895 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
12896 set_window_height (minibuf_window, 1, 0);
12897
c2213350
KH
12898 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
12899 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
5f5c8ee5
GM
12900
12901 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
12902 scratch_glyph_row.glyphs[TEXT_AREA + 1]
12903 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
12904
12905 /* The default ellipsis glyphs `...'. */
12906 for (i = 0; i < 3; ++i)
12907 XSETFASTINT (default_invis_vector[i], '.');
a2889657 12908 }
5f5c8ee5
GM
12909
12910#ifdef HAVE_WINDOW_SYSTEM
12911 {
12912 /* Allocate the buffer for frame titles. */
12913 int size = 100;
12914 frame_title_buf = (char *) xmalloc (size);
12915 frame_title_buf_end = frame_title_buf + size;
12916 frame_title_ptr = NULL;
12917 }
12918#endif /* HAVE_WINDOW_SYSTEM */
a2889657 12919}
5f5c8ee5
GM
12920
12921