Support print-circle and related features.
[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;
261
8f897821 262/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 263
8f897821 264Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5
GM
265
266/* Name of the face used to highlight trailing whitespace. */
267
268Lisp_Object Qtrailing_whitespace;
269
270/* The symbol `image' which is the car of the lists used to represent
271 images in Lisp. */
272
273Lisp_Object Qimage;
274
275/* Non-zero means print newline to stdout before next mini-buffer
276 message. */
a2889657
JB
277
278int noninteractive_need_newline;
279
5f5c8ee5 280/* Non-zero means print newline to message log before next message. */
f88eb0b6 281
3c6595e0 282static int message_log_need_newline;
f88eb0b6 283
5f5c8ee5
GM
284\f
285/* The buffer position of the first character appearing entirely or
286 partially on the line of the selected window which contains the
287 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
288 redisplay optimization in redisplay_internal. */
a2889657 289
5f5c8ee5 290static struct text_pos this_line_start_pos;
a2889657 291
5f5c8ee5
GM
292/* Number of characters past the end of the line above, including the
293 terminating newline. */
294
295static struct text_pos this_line_end_pos;
296
297/* The vertical positions and the height of this line. */
a2889657 298
a2889657 299static int this_line_vpos;
5f5c8ee5
GM
300static int this_line_y;
301static int this_line_pixel_height;
302
303/* X position at which this display line starts. Usually zero;
304 negative if first character is partially visible. */
305
306static int this_line_start_x;
a2889657 307
5f5c8ee5 308/* Buffer that this_line_.* variables are referring to. */
a2889657 309
a2889657
JB
310static struct buffer *this_line_buffer;
311
5f5c8ee5
GM
312/* Nonzero means truncate lines in all windows less wide than the
313 frame. */
a2889657 314
a2889657
JB
315int truncate_partial_width_windows;
316
7bbe686f 317/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 318
7bbe686f 319int unibyte_display_via_language_environment;
5f5c8ee5
GM
320
321/* Nonzero means we have more than one non-mini-buffer-only frame.
322 Not guaranteed to be accurate except while parsing
323 frame-title-format. */
7bbe686f 324
d39b6696
KH
325int multiple_frames;
326
a2889657
JB
327Lisp_Object Vglobal_mode_string;
328
329/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 330
a2889657
JB
331Lisp_Object Voverlay_arrow_position;
332
5f5c8ee5
GM
333/* String to display for the arrow. Only used on terminal frames. */
334
a2889657
JB
335Lisp_Object Voverlay_arrow_string;
336
5f5c8ee5
GM
337/* Values of those variables at last redisplay. However, if
338 Voverlay_arrow_position is a marker, last_arrow_position is its
339 numerical position. */
340
d45de95b
RS
341static Lisp_Object last_arrow_position, last_arrow_string;
342
5f5c8ee5
GM
343/* Like mode-line-format, but for the title bar on a visible frame. */
344
d39b6696
KH
345Lisp_Object Vframe_title_format;
346
5f5c8ee5
GM
347/* Like mode-line-format, but for the title bar on an iconified frame. */
348
d39b6696
KH
349Lisp_Object Vicon_title_format;
350
08b610e4
RS
351/* List of functions to call when a window's size changes. These
352 functions get one arg, a frame on which one or more windows' sizes
353 have changed. */
5f5c8ee5 354
08b610e4
RS
355static Lisp_Object Vwindow_size_change_functions;
356
cf074754
RS
357Lisp_Object Qmenu_bar_update_hook;
358
a2889657 359/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 360
5f5c8ee5 361static int overlay_arrow_seen;
ca26e1c8 362
fba9ce76 363/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 364
5f5c8ee5
GM
365int highlight_nonselected_windows;
366
367/* If cursor motion alone moves point off frame, try scrolling this
368 many lines up or down if that will bring it back. */
369
14510fee 370static int scroll_step;
a2889657 371
5f5c8ee5
GM
372/* Non-0 means scroll just far enough to bring point back on the
373 screen, when appropriate. */
374
0789adb2
RS
375static int scroll_conservatively;
376
5f5c8ee5
GM
377/* Recenter the window whenever point gets within this many lines of
378 the top or bottom of the window. This value is translated into a
379 pixel value by multiplying it with CANON_Y_UNIT, which means that
380 there is really a fixed pixel height scroll margin. */
381
9afd2168
RS
382int scroll_margin;
383
5f5c8ee5
GM
384/* Number of windows showing the buffer of the selected window (or
385 another buffer with the same base buffer). keyboard.c refers to
386 this. */
a2889657 387
a2889657
JB
388int buffer_shared;
389
5f5c8ee5 390/* Vector containing glyphs for an ellipsis `...'. */
a2889657 391
5f5c8ee5 392static Lisp_Object default_invis_vector[3];
a2889657 393
5f5c8ee5 394/* Nonzero means display mode line highlighted. */
a2889657 395
a2889657
JB
396int mode_line_inverse_video;
397
5f5c8ee5
GM
398/* Prompt to display in front of the mini-buffer contents. */
399
8c5b6a0a 400Lisp_Object minibuf_prompt;
a2889657 401
5f5c8ee5
GM
402/* Width of current mini-buffer prompt. Only set after display_line
403 of the line that contains the prompt. */
404
a2889657 405int minibuf_prompt_width;
5f5c8ee5
GM
406int minibuf_prompt_pixel_width;
407
5f5c8ee5
GM
408/* This is the window where the echo area message was displayed. It
409 is always a mini-buffer window, but it may not be the same window
410 currently active as a mini-buffer. */
411
73af359d
RS
412Lisp_Object echo_area_window;
413
c6e89d6c
GM
414/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
415 pushes the current message and the value of
416 message_enable_multibyte on the stack, the function restore_message
417 pops the stack and displays MESSAGE again. */
418
419Lisp_Object Vmessage_stack;
420
a3788d53
RS
421/* Nonzero means multibyte characters were enabled when the echo area
422 message was specified. */
5f5c8ee5 423
a3788d53
RS
424int message_enable_multibyte;
425
5f5c8ee5
GM
426/* True if we should redraw the mode lines on the next redisplay. */
427
a2889657
JB
428int update_mode_lines;
429
5f5c8ee5
GM
430/* Nonzero if window sizes or contents have changed since last
431 redisplay that finished */
432
a2889657
JB
433int windows_or_buffers_changed;
434
5f5c8ee5
GM
435/* Nonzero after display_mode_line if %l was used and it displayed a
436 line number. */
437
aa6d10fa
RS
438int line_number_displayed;
439
440/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 441
14510fee 442static int line_number_display_limit;
5992c4f7 443
5d121aec
KH
444/* line width to consider when repostioning for line number display */
445
446static int line_number_display_limit_width;
447
5f5c8ee5
GM
448/* Number of lines to keep in the message log buffer. t means
449 infinite. nil means don't log at all. */
450
5992c4f7 451Lisp_Object Vmessage_log_max;
d45de95b 452
c6e89d6c
GM
453/* Current, index 0, and last displayed echo area message. Either
454 buffers from echo_buffers, or nil to indicate no message. */
455
456Lisp_Object echo_area_buffer[2];
457
458/* The buffers referenced from echo_area_buffer. */
459
460static Lisp_Object echo_buffer[2];
461
462/* A vector saved used in with_area_buffer to reduce consing. */
463
464static Lisp_Object Vwith_echo_area_save_vector;
465
466/* Non-zero means display_echo_area should display the last echo area
467 message again. Set by redisplay_preserve_echo_area. */
468
469static int display_last_displayed_message_p;
470
471/* Nonzero if echo area is being used by print; zero if being used by
472 message. */
473
474int message_buf_print;
475
9142dd5b
GM
476/* Maximum height for resizing mini-windows. Either a float
477 specifying a fraction of the available height, or an integer
478 specifying a number of lines. */
c6e89d6c
GM
479
480static Lisp_Object Vmax_mini_window_height;
481
5f5c8ee5
GM
482/* A scratch glyph row with contents used for generating truncation
483 glyphs. Also used in direct_output_for_insert. */
12adba34 484
5f5c8ee5
GM
485#define MAX_SCRATCH_GLYPHS 100
486struct glyph_row scratch_glyph_row;
487static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 488
5f5c8ee5
GM
489/* Ascent and height of the last line processed by move_it_to. */
490
491static int last_max_ascent, last_height;
492
493/* The maximum distance to look ahead for text properties. Values
494 that are too small let us call compute_char_face and similar
495 functions too often which is expensive. Values that are too large
496 let us call compute_char_face and alike too often because we
497 might not be interested in text properties that far away. */
498
499#define TEXT_PROP_DISTANCE_LIMIT 100
500
501/* Non-zero means print traces of redisplay if compiled with
502 GLYPH_DEBUG != 0. */
503
504#if GLYPH_DEBUG
505int trace_redisplay_p;
506#endif
507
508/* Value returned from text property handlers (see below). */
509
510enum prop_handled
3c6595e0 511{
5f5c8ee5
GM
512 HANDLED_NORMALLY,
513 HANDLED_RECOMPUTE_PROPS,
514 HANDLED_OVERLAY_STRING_CONSUMED,
515 HANDLED_RETURN
516};
3c6595e0 517
5f5c8ee5
GM
518/* A description of text properties that redisplay is interested
519 in. */
3c6595e0 520
5f5c8ee5
GM
521struct props
522{
523 /* The name of the property. */
524 Lisp_Object *name;
90adcf20 525
5f5c8ee5
GM
526 /* A unique index for the property. */
527 enum prop_idx idx;
528
529 /* A handler function called to set up iterator IT from the property
530 at IT's current position. Value is used to steer handle_stop. */
531 enum prop_handled (*handler) P_ ((struct it *it));
532};
533
534static enum prop_handled handle_face_prop P_ ((struct it *));
535static enum prop_handled handle_invisible_prop P_ ((struct it *));
536static enum prop_handled handle_display_prop P_ ((struct it *));
537static enum prop_handled handle_overlay_change P_ ((struct it *));
538static enum prop_handled handle_fontified_prop P_ ((struct it *));
539
540/* Properties handled by iterators. */
541
542static struct props it_props[] =
5992c4f7 543{
5f5c8ee5
GM
544 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
545 /* Handle `face' before `display' because some sub-properties of
546 `display' need to know the face. */
547 {&Qface, FACE_PROP_IDX, handle_face_prop},
548 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
549 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
550 {NULL, 0, NULL}
551};
5992c4f7 552
5f5c8ee5
GM
553/* Value is the position described by X. If X is a marker, value is
554 the marker_position of X. Otherwise, value is X. */
12adba34 555
5f5c8ee5 556#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 557
5f5c8ee5 558/* Enumeration returned by some move_it_.* functions internally. */
12adba34 559
5f5c8ee5
GM
560enum move_it_result
561{
562 /* Not used. Undefined value. */
563 MOVE_UNDEFINED,
bab29e15 564
5f5c8ee5
GM
565 /* Move ended at the requested buffer position or ZV. */
566 MOVE_POS_MATCH_OR_ZV,
bab29e15 567
5f5c8ee5
GM
568 /* Move ended at the requested X pixel position. */
569 MOVE_X_REACHED,
12adba34 570
5f5c8ee5
GM
571 /* Move within a line ended at the end of a line that must be
572 continued. */
573 MOVE_LINE_CONTINUED,
574
575 /* Move within a line ended at the end of a line that would
576 be displayed truncated. */
577 MOVE_LINE_TRUNCATED,
ff6c30e5 578
5f5c8ee5
GM
579 /* Move within a line ended at a line end. */
580 MOVE_NEWLINE_OR_CR
581};
12adba34 582
ff6c30e5 583
5f5c8ee5
GM
584\f
585/* Function prototypes. */
586
e037b9ec
GM
587static struct glyph_row *row_containing_pos P_ ((struct window *, int,
588 struct glyph_row *,
589 struct glyph_row *));
c6e89d6c
GM
590static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
591static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
c6e89d6c
GM
592static void clear_garbaged_frames P_ ((void));
593static int current_message_1 P_ ((Lisp_Object *));
594static int truncate_message_1 P_ ((int));
595static int set_message_1 P_ ((char *s, Lisp_Object, int, int));
596static int display_echo_area P_ ((struct window *));
597static int display_echo_area_1 P_ ((struct window *));
28514cd9 598static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
4fdb80f2 599static int string_char_and_length P_ ((unsigned char *, int, int *));
5f5c8ee5
GM
600static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
601 struct text_pos));
602static int compute_window_start_on_continuation_line P_ ((struct window *));
603static Lisp_Object eval_handler P_ ((Lisp_Object));
604static Lisp_Object eval_form P_ ((Lisp_Object));
605static void insert_left_trunc_glyphs P_ ((struct it *));
606static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
607static void extend_face_to_end_of_line P_ ((struct it *));
608static void append_space P_ ((struct it *, int));
609static void make_cursor_line_fully_visible P_ ((struct window *));
610static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
611static int trailing_whitespace_p P_ ((int));
612static int message_log_check_duplicate P_ ((int, int, int, int));
613int invisible_p P_ ((Lisp_Object, Lisp_Object));
614int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
615static void push_it P_ ((struct it *));
616static void pop_it P_ ((struct it *));
617static void sync_frame_with_window_matrix_rows P_ ((struct window *));
618static void redisplay_internal P_ ((int));
c6e89d6c 619static int echo_area_display P_ ((int));
5f5c8ee5
GM
620static void redisplay_windows P_ ((Lisp_Object));
621static void redisplay_window P_ ((Lisp_Object, int));
622static void update_menu_bar P_ ((struct frame *, int));
623static int try_window_reusing_current_matrix P_ ((struct window *));
624static int try_window_id P_ ((struct window *));
625static int display_line P_ ((struct it *));
626static void display_mode_lines P_ ((struct window *));
627static void display_mode_line P_ ((struct window *, enum face_id,
628 Lisp_Object));
629static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
630static char *decode_mode_spec P_ ((struct window *, char, int, int));
631static void display_menu_bar P_ ((struct window *));
632static int display_count_lines P_ ((int, int, int, int, int *));
633static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
634 int, int, struct it *, int, int, int, int));
635static void compute_line_metrics P_ ((struct it *));
636static void run_redisplay_end_trigger_hook P_ ((struct it *));
637static int get_overlay_strings P_ ((struct it *));
638static void next_overlay_string P_ ((struct it *));
639void set_iterator_to_next P_ ((struct it *));
640static void reseat P_ ((struct it *, struct text_pos, int));
641static void reseat_1 P_ ((struct it *, struct text_pos, int));
642static void back_to_previous_visible_line_start P_ ((struct it *));
643static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 644static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
645static int next_element_from_display_vector P_ ((struct it *));
646static int next_element_from_string P_ ((struct it *));
647static int next_element_from_c_string P_ ((struct it *));
648static int next_element_from_buffer P_ ((struct it *));
649static int next_element_from_image P_ ((struct it *));
650static int next_element_from_stretch P_ ((struct it *));
651static void load_overlay_strings P_ ((struct it *));
652static void init_from_display_pos P_ ((struct it *, struct window *,
653 struct display_pos *));
654static void reseat_to_string P_ ((struct it *, unsigned char *,
655 Lisp_Object, int, int, int, int));
656static int charset_at_position P_ ((struct text_pos));
657static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
658 int, int, int));
659void move_it_vertically_backward P_ ((struct it *, int));
660static void init_to_row_start P_ ((struct it *, struct window *,
661 struct glyph_row *));
662static void init_to_row_end P_ ((struct it *, struct window *,
663 struct glyph_row *));
664static void back_to_previous_line_start P_ ((struct it *));
665static void forward_to_next_line_start P_ ((struct it *));
666static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
667 Lisp_Object, int));
668static struct text_pos string_pos P_ ((int, Lisp_Object));
669static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
670static int number_of_chars P_ ((unsigned char *, int));
671static void compute_stop_pos P_ ((struct it *));
672static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
673 Lisp_Object));
674static int face_before_or_after_it_pos P_ ((struct it *, int));
675static int next_overlay_change P_ ((int));
676static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
677 Lisp_Object, struct text_pos *));
678
679#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
680#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 681
5f5c8ee5 682#ifdef HAVE_WINDOW_SYSTEM
12adba34 683
e037b9ec
GM
684static void update_tool_bar P_ ((struct frame *, int));
685static void build_desired_tool_bar_string P_ ((struct frame *f));
686static int redisplay_tool_bar P_ ((struct frame *));
687static void display_tool_bar_line P_ ((struct it *));
12adba34 688
5f5c8ee5 689#endif /* HAVE_WINDOW_SYSTEM */
12adba34 690
5f5c8ee5
GM
691\f
692/***********************************************************************
693 Window display dimensions
694 ***********************************************************************/
12adba34 695
5f5c8ee5
GM
696/* Return the window-relative maximum y + 1 for glyph rows displaying
697 text in window W. This is the height of W minus the height of a
698 mode line, if any. */
699
700INLINE int
701window_text_bottom_y (w)
702 struct window *w;
703{
704 struct frame *f = XFRAME (w->frame);
705 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
706
707 if (WINDOW_WANTS_MODELINE_P (w))
708 height -= CURRENT_MODE_LINE_HEIGHT (w);
709 return height;
f88eb0b6
KH
710}
711
f82aff7c 712
5f5c8ee5
GM
713/* Return the pixel width of display area AREA of window W. AREA < 0
714 means return the total width of W, not including bitmap areas to
715 the left and right of the window. */
ff6c30e5 716
5f5c8ee5
GM
717INLINE int
718window_box_width (w, area)
719 struct window *w;
720 int area;
721{
722 struct frame *f = XFRAME (w->frame);
723 int width = XFASTINT (w->width);
724
725 if (!w->pseudo_window_p)
ff6c30e5 726 {
050d82d7 727 width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FLAGS_AREA_COLS (f);
5f5c8ee5
GM
728
729 if (area == TEXT_AREA)
730 {
731 if (INTEGERP (w->left_margin_width))
732 width -= XFASTINT (w->left_margin_width);
733 if (INTEGERP (w->right_margin_width))
734 width -= XFASTINT (w->right_margin_width);
735 }
736 else if (area == LEFT_MARGIN_AREA)
737 width = (INTEGERP (w->left_margin_width)
738 ? XFASTINT (w->left_margin_width) : 0);
739 else if (area == RIGHT_MARGIN_AREA)
740 width = (INTEGERP (w->right_margin_width)
741 ? XFASTINT (w->right_margin_width) : 0);
ff6c30e5 742 }
5f5c8ee5
GM
743
744 return width * CANON_X_UNIT (f);
ff6c30e5 745}
1adc55de 746
1adc55de 747
5f5c8ee5
GM
748/* Return the pixel height of the display area of window W, not
749 including mode lines of W, if any.. */
f88eb0b6 750
5f5c8ee5
GM
751INLINE int
752window_box_height (w)
753 struct window *w;
f88eb0b6 754{
5f5c8ee5
GM
755 struct frame *f = XFRAME (w->frame);
756 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
757
758 if (WINDOW_WANTS_MODELINE_P (w))
759 height -= CURRENT_MODE_LINE_HEIGHT (w);
760
045dee35
GM
761 if (WINDOW_WANTS_HEADER_LINE_P (w))
762 height -= CURRENT_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
763
764 return height;
5992c4f7
KH
765}
766
767
5f5c8ee5
GM
768/* Return the frame-relative coordinate of the left edge of display
769 area AREA of window W. AREA < 0 means return the left edge of the
770 whole window, to the right of any bitmap area at the left side of
771 W. */
5992c4f7 772
5f5c8ee5
GM
773INLINE int
774window_box_left (w, area)
775 struct window *w;
776 int area;
90adcf20 777{
5f5c8ee5
GM
778 struct frame *f = XFRAME (w->frame);
779 int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
a3788d53 780
5f5c8ee5 781 if (!w->pseudo_window_p)
90adcf20 782 {
5f5c8ee5 783 x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
050d82d7 784 + FRAME_LEFT_FLAGS_AREA_WIDTH (f));
5f5c8ee5
GM
785
786 if (area == TEXT_AREA)
787 x += window_box_width (w, LEFT_MARGIN_AREA);
788 else if (area == RIGHT_MARGIN_AREA)
789 x += (window_box_width (w, LEFT_MARGIN_AREA)
790 + window_box_width (w, TEXT_AREA));
90adcf20 791 }
73af359d 792
5f5c8ee5
GM
793 return x;
794}
90adcf20 795
b6436d4e 796
5f5c8ee5
GM
797/* Return the frame-relative coordinate of the right edge of display
798 area AREA of window W. AREA < 0 means return the left edge of the
799 whole window, to the left of any bitmap area at the right side of
800 W. */
ded34426 801
5f5c8ee5
GM
802INLINE int
803window_box_right (w, area)
804 struct window *w;
805 int area;
806{
807 return window_box_left (w, area) + window_box_width (w, area);
808}
809
810
811/* Get the bounding box of the display area AREA of window W, without
812 mode lines, in frame-relative coordinates. AREA < 0 means the
813 whole window, not including bitmap areas to the left and right of
814 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
815 coordinates of the upper-left corner of the box. Return in
816 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
817
818INLINE void
819window_box (w, area, box_x, box_y, box_width, box_height)
820 struct window *w;
821 int area;
822 int *box_x, *box_y, *box_width, *box_height;
823{
824 struct frame *f = XFRAME (w->frame);
825
826 *box_width = window_box_width (w, area);
827 *box_height = window_box_height (w);
828 *box_x = window_box_left (w, area);
829 *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
830 + XFASTINT (w->top) * CANON_Y_UNIT (f));
045dee35
GM
831 if (WINDOW_WANTS_HEADER_LINE_P (w))
832 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
ded34426 833}
1adc55de 834
1adc55de 835
5f5c8ee5
GM
836/* Get the bounding box of the display area AREA of window W, without
837 mode lines. AREA < 0 means the whole window, not including bitmap
838 areas to the left and right of the window. Return in *TOP_LEFT_X
839 and TOP_LEFT_Y the frame-relative pixel coordinates of the
840 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
841 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
842 box. */
ded34426 843
5f5c8ee5
GM
844INLINE void
845window_box_edges (w, area, top_left_x, top_left_y,
846 bottom_right_x, bottom_right_y)
847 struct window *w;
848 int area;
849 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 850{
5f5c8ee5
GM
851 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
852 bottom_right_y);
853 *bottom_right_x += *top_left_x;
854 *bottom_right_y += *top_left_y;
48ae5f0a
KH
855}
856
5f5c8ee5
GM
857
858\f
859/***********************************************************************
860 Utilities
861 ***********************************************************************/
862
4fdb80f2
GM
863/* Return the next character from STR which is MAXLEN bytes long.
864 Return in *LEN the length of the character. This is like
865 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
866 we find one, we return a `?', but with the length of the illegal
867 character. */
868
869static INLINE int
7a5b8a93 870string_char_and_length (str, maxlen, len)
4fdb80f2 871 unsigned char *str;
7a5b8a93 872 int maxlen, *len;
4fdb80f2
GM
873{
874 int c;
875
876 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
877 if (!CHAR_VALID_P (c, 1))
878 /* We may not change the length here because other places in Emacs
879 don't use this function, i.e. they silently accept illegal
880 characters. */
881 c = '?';
882
883 return c;
884}
885
886
887
5f5c8ee5
GM
888/* Given a position POS containing a valid character and byte position
889 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
890
891static struct text_pos
892string_pos_nchars_ahead (pos, string, nchars)
893 struct text_pos pos;
894 Lisp_Object string;
895 int nchars;
0b1005ef 896{
5f5c8ee5
GM
897 xassert (STRINGP (string) && nchars >= 0);
898
899 if (STRING_MULTIBYTE (string))
900 {
901 int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos);
902 unsigned char *p = XSTRING (string)->data + BYTEPOS (pos);
903 int len;
904
905 while (nchars--)
906 {
4fdb80f2 907 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
908 p += len, rest -= len;
909 xassert (rest >= 0);
910 CHARPOS (pos) += 1;
911 BYTEPOS (pos) += len;
912 }
913 }
914 else
915 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
916
917 return pos;
0a9dc68b
RS
918}
919
0a9dc68b 920
5f5c8ee5
GM
921/* Value is the text position, i.e. character and byte position,
922 for character position CHARPOS in STRING. */
923
924static INLINE struct text_pos
925string_pos (charpos, string)
926 int charpos;
0a9dc68b 927 Lisp_Object string;
0a9dc68b 928{
5f5c8ee5
GM
929 struct text_pos pos;
930 xassert (STRINGP (string));
931 xassert (charpos >= 0);
932 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
933 return pos;
934}
935
936
937/* Value is a text position, i.e. character and byte position, for
938 character position CHARPOS in C string S. MULTIBYTE_P non-zero
939 means recognize multibyte characters. */
940
941static struct text_pos
942c_string_pos (charpos, s, multibyte_p)
943 int charpos;
944 unsigned char *s;
945 int multibyte_p;
946{
947 struct text_pos pos;
948
949 xassert (s != NULL);
950 xassert (charpos >= 0);
951
952 if (multibyte_p)
0a9dc68b 953 {
5f5c8ee5
GM
954 int rest = strlen (s), len;
955
956 SET_TEXT_POS (pos, 0, 0);
957 while (charpos--)
0a9dc68b 958 {
4fdb80f2 959 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
960 s += len, rest -= len;
961 xassert (rest >= 0);
962 CHARPOS (pos) += 1;
963 BYTEPOS (pos) += len;
0a9dc68b
RS
964 }
965 }
5f5c8ee5
GM
966 else
967 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 968
5f5c8ee5
GM
969 return pos;
970}
0a9dc68b 971
0a9dc68b 972
5f5c8ee5
GM
973/* Value is the number of characters in C string S. MULTIBYTE_P
974 non-zero means recognize multibyte characters. */
0a9dc68b 975
5f5c8ee5
GM
976static int
977number_of_chars (s, multibyte_p)
978 unsigned char *s;
979 int multibyte_p;
980{
981 int nchars;
982
983 if (multibyte_p)
984 {
985 int rest = strlen (s), len;
986 unsigned char *p = (unsigned char *) s;
0a9dc68b 987
5f5c8ee5
GM
988 for (nchars = 0; rest > 0; ++nchars)
989 {
4fdb80f2 990 string_char_and_length (p, rest, &len);
5f5c8ee5 991 rest -= len, p += len;
0a9dc68b
RS
992 }
993 }
5f5c8ee5
GM
994 else
995 nchars = strlen (s);
996
997 return nchars;
0b1005ef
KH
998}
999
5f5c8ee5
GM
1000
1001/* Compute byte position NEWPOS->bytepos corresponding to
1002 NEWPOS->charpos. POS is a known position in string STRING.
1003 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1004
5f5c8ee5
GM
1005static void
1006compute_string_pos (newpos, pos, string)
1007 struct text_pos *newpos, pos;
1008 Lisp_Object string;
76412d64 1009{
5f5c8ee5
GM
1010 xassert (STRINGP (string));
1011 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
1012
1013 if (STRING_MULTIBYTE (string))
1014 *newpos = string_pos_nchars_ahead (pos, CHARPOS (*newpos) - CHARPOS (pos),
1015 string);
1016 else
1017 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1018}
1019
9c74a0dd 1020
5f5c8ee5
GM
1021/* Return the charset of the character at position POS in
1022 current_buffer. */
1adc55de 1023
5f5c8ee5
GM
1024static int
1025charset_at_position (pos)
1026 struct text_pos pos;
a2889657 1027{
5f5c8ee5
GM
1028 int c, multibyte_p;
1029 unsigned char *p = BYTE_POS_ADDR (BYTEPOS (pos));
1030
1031 multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1032 if (multibyte_p)
a2889657 1033 {
5f5c8ee5
GM
1034 int maxlen = ((BYTEPOS (pos) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
1035 - BYTEPOS (pos));
1036 int len;
4fdb80f2 1037 c = string_char_and_length (p, maxlen, &len);
a2889657 1038 }
5f5c8ee5
GM
1039 else
1040 c = *p;
1041
1042 return CHAR_CHARSET (c);
1043}
1044
1045
1046\f
1047/***********************************************************************
1048 Lisp form evaluation
1049 ***********************************************************************/
1050
1051/* Error handler for eval_form. */
1052
1053static Lisp_Object
1054eval_handler (arg)
1055 Lisp_Object arg;
1056{
1057 return Qnil;
1058}
1059
1060
1061/* Evaluate SEXPR and return the result, or nil if something went
1062 wrong. */
1063
1064static Lisp_Object
1065eval_form (sexpr)
1066 Lisp_Object sexpr;
1067{
1068 int count = specpdl_ptr - specpdl;
1069 Lisp_Object val;
1070 specbind (Qinhibit_redisplay, Qt);
1071 val = internal_condition_case_1 (Feval, sexpr, Qerror, eval_handler);
1072 return unbind_to (count, val);
1073}
1074
1075
1076\f
1077/***********************************************************************
1078 Debugging
1079 ***********************************************************************/
1080
1081#if 0
1082
1083/* Define CHECK_IT to perform sanity checks on iterators.
1084 This is for debugging. It is too slow to do unconditionally. */
1085
1086static void
1087check_it (it)
1088 struct it *it;
1089{
1090 if (it->method == next_element_from_string)
a2889657 1091 {
5f5c8ee5
GM
1092 xassert (STRINGP (it->string));
1093 xassert (IT_STRING_CHARPOS (*it) >= 0);
1094 }
1095 else if (it->method == next_element_from_buffer)
1096 {
1097 /* Check that character and byte positions agree. */
1098 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1099 }
73af359d 1100
5f5c8ee5
GM
1101 if (it->dpvec)
1102 xassert (it->current.dpvec_index >= 0);
1103 else
1104 xassert (it->current.dpvec_index < 0);
1105}
1f40cad2 1106
5f5c8ee5
GM
1107#define CHECK_IT(IT) check_it ((IT))
1108
1109#else /* not 0 */
1110
1111#define CHECK_IT(IT) (void) 0
1112
1113#endif /* not 0 */
1114
1115
1116#if GLYPH_DEBUG
1117
1118/* Check that the window end of window W is what we expect it
1119 to be---the last row in the current matrix displaying text. */
1120
1121static void
1122check_window_end (w)
1123 struct window *w;
1124{
1125 if (!MINI_WINDOW_P (w)
1126 && !NILP (w->window_end_valid))
1127 {
1128 struct glyph_row *row;
1129 xassert ((row = MATRIX_ROW (w->current_matrix,
1130 XFASTINT (w->window_end_vpos)),
1131 !row->enabled_p
1132 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1133 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1134 }
1135}
1136
1137#define CHECK_WINDOW_END(W) check_window_end ((W))
1138
1139#else /* not GLYPH_DEBUG */
1140
1141#define CHECK_WINDOW_END(W) (void) 0
1142
1143#endif /* not GLYPH_DEBUG */
1144
1145
1146\f
1147/***********************************************************************
1148 Iterator initialization
1149 ***********************************************************************/
1150
1151/* Initialize IT for displaying current_buffer in window W, starting
1152 at character position CHARPOS. CHARPOS < 0 means that no buffer
1153 position is specified which is useful when the iterator is assigned
1154 a position later. BYTEPOS is the byte position corresponding to
1155 CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS.
1156
1157 If ROW is not null, calls to produce_glyphs with IT as parameter
1158 will produce glyphs in that row.
1159
1160 BASE_FACE_ID is the id of a base face to use. It must be one of
1161 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or
045dee35 1162 HEADER_LINE_FACE_ID for displaying mode lines, or TOOL_BAR_FACE_ID for
e037b9ec 1163 displaying the tool-bar.
5f5c8ee5
GM
1164
1165 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or
045dee35 1166 HEADER_LINE_FACE_ID, the iterator will be initialized to use the
5f5c8ee5
GM
1167 corresponding mode line glyph row of the desired matrix of W. */
1168
1169void
1170init_iterator (it, w, charpos, bytepos, row, base_face_id)
1171 struct it *it;
1172 struct window *w;
1173 int charpos, bytepos;
1174 struct glyph_row *row;
1175 enum face_id base_face_id;
1176{
1177 int highlight_region_p;
5f5c8ee5
GM
1178
1179 /* Some precondition checks. */
1180 xassert (w != NULL && it != NULL);
5f5c8ee5
GM
1181 xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
1182
1183 /* If face attributes have been changed since the last redisplay,
1184 free realized faces now because they depend on face definitions
1185 that might have changed. */
1186 if (face_change_count)
1187 {
1188 face_change_count = 0;
1189 free_all_realized_faces (Qnil);
1190 }
1191
1192 /* Use one of the mode line rows of W's desired matrix if
1193 appropriate. */
1194 if (row == NULL)
1195 {
1196 if (base_face_id == MODE_LINE_FACE_ID)
1197 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
1198 else if (base_face_id == HEADER_LINE_FACE_ID)
1199 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5
GM
1200 }
1201
1202 /* Clear IT. */
1203 bzero (it, sizeof *it);
1204 it->current.overlay_string_index = -1;
1205 it->current.dpvec_index = -1;
1206 it->charset = CHARSET_ASCII;
1207 it->base_face_id = base_face_id;
1208
1209 /* The window in which we iterate over current_buffer: */
1210 XSETWINDOW (it->window, w);
1211 it->w = w;
1212 it->f = XFRAME (w->frame);
1213
1214 /* If realized faces have been removed, e.g. because of face
1215 attribute changes of named faces, recompute them. */
1216 if (FRAME_FACE_CACHE (it->f)->used == 0)
1217 recompute_basic_faces (it->f);
1218
5f5c8ee5
GM
1219 /* Current value of the `space-width', and 'height' properties. */
1220 it->space_width = Qnil;
1221 it->font_height = Qnil;
1222
1223 /* Are control characters displayed as `^C'? */
1224 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
1225
1226 /* -1 means everything between a CR and the following line end
1227 is invisible. >0 means lines indented more than this value are
1228 invisible. */
1229 it->selective = (INTEGERP (current_buffer->selective_display)
1230 ? XFASTINT (current_buffer->selective_display)
1231 : (!NILP (current_buffer->selective_display)
1232 ? -1 : 0));
1233 it->selective_display_ellipsis_p
1234 = !NILP (current_buffer->selective_display_ellipses);
1235
1236 /* Display table to use. */
1237 it->dp = window_display_table (w);
1238
1239 /* Are multibyte characters enabled in current_buffer? */
1240 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1241
1242 /* Non-zero if we should highlight the region. */
1243 highlight_region_p
1244 = (!NILP (Vtransient_mark_mode)
1245 && !NILP (current_buffer->mark_active)
1246 && XMARKER (current_buffer->mark)->buffer != 0);
1247
1248 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
1249 start and end of a visible region in window IT->w. Set both to
1250 -1 to indicate no region. */
1251 if (highlight_region_p
1252 /* Maybe highlight only in selected window. */
1253 && (/* Either show region everywhere. */
1254 highlight_nonselected_windows
1255 /* Or show region in the selected window. */
1256 || w == XWINDOW (selected_window)
1257 /* Or show the region if we are in the mini-buffer and W is
1258 the window the mini-buffer refers to. */
1259 || (MINI_WINDOW_P (XWINDOW (selected_window))
1260 && w == XWINDOW (Vminibuf_scroll_window))))
1261 {
1262 int charpos = marker_position (current_buffer->mark);
1263 it->region_beg_charpos = min (PT, charpos);
1264 it->region_end_charpos = max (PT, charpos);
1265 }
1266 else
1267 it->region_beg_charpos = it->region_end_charpos = -1;
1268
1269 /* Get the position at which the redisplay_end_trigger hook should
1270 be run, if it is to be run at all. */
1271 if (MARKERP (w->redisplay_end_trigger)
1272 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
1273 it->redisplay_end_trigger_charpos
1274 = marker_position (w->redisplay_end_trigger);
1275 else if (INTEGERP (w->redisplay_end_trigger))
1276 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
1277
1278 /* Correct bogus values of tab_width. */
1279 it->tab_width = XINT (current_buffer->tab_width);
1280 if (it->tab_width <= 0 || it->tab_width > 1000)
1281 it->tab_width = 8;
1282
1283 /* Are lines in the display truncated? */
1284 it->truncate_lines_p
1285 = (base_face_id != DEFAULT_FACE_ID
1286 || XINT (it->w->hscroll)
1287 || (truncate_partial_width_windows
1288 && !WINDOW_FULL_WIDTH_P (it->w))
1289 || !NILP (current_buffer->truncate_lines));
1290
1291 /* Get dimensions of truncation and continuation glyphs. These are
1292 displayed as bitmaps under X, so we don't need them for such
1293 frames. */
1294 if (!FRAME_WINDOW_P (it->f))
1295 {
1296 if (it->truncate_lines_p)
1297 {
1298 /* We will need the truncation glyph. */
1299 xassert (it->glyph_row == NULL);
1300 produce_special_glyphs (it, IT_TRUNCATION);
1301 it->truncation_pixel_width = it->pixel_width;
1302 }
1303 else
1304 {
1305 /* We will need the continuation glyph. */
1306 xassert (it->glyph_row == NULL);
1307 produce_special_glyphs (it, IT_CONTINUATION);
1308 it->continuation_pixel_width = it->pixel_width;
1309 }
1310
1311 /* Reset these values to zero becaue the produce_special_glyphs
1312 above has changed them. */
1313 it->pixel_width = it->ascent = it->descent = 0;
312246d1 1314 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
1315 }
1316
1317 /* Set this after getting the dimensions of truncation and
1318 continuation glyphs, so that we don't produce glyphs when calling
1319 produce_special_glyphs, above. */
1320 it->glyph_row = row;
1321 it->area = TEXT_AREA;
1322
1323 /* Get the dimensions of the display area. The display area
1324 consists of the visible window area plus a horizontally scrolled
1325 part to the left of the window. All x-values are relative to the
1326 start of this total display area. */
1327 if (base_face_id != DEFAULT_FACE_ID)
1328 {
1329 /* Mode lines, menu bar in terminal frames. */
1330 it->first_visible_x = 0;
1331 it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
1332 }
1333 else
1334 {
1335 it->first_visible_x
1336 = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
1337 it->last_visible_x = (it->first_visible_x
1338 + window_box_width (w, TEXT_AREA));
1339
1340 /* If we truncate lines, leave room for the truncator glyph(s) at
1341 the right margin. Otherwise, leave room for the continuation
1342 glyph(s). Truncation and continuation glyphs are not inserted
1343 for window-based redisplay. */
1344 if (!FRAME_WINDOW_P (it->f))
1345 {
1346 if (it->truncate_lines_p)
1347 it->last_visible_x -= it->truncation_pixel_width;
1348 else
1349 it->last_visible_x -= it->continuation_pixel_width;
1350 }
1351
045dee35
GM
1352 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
1353 it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
1354 }
1355
1356 /* Leave room for a border glyph. */
1357 if (!FRAME_WINDOW_P (it->f)
1358 && !WINDOW_RIGHTMOST_P (it->w))
1359 it->last_visible_x -= 1;
1360
1361 it->last_visible_y = window_text_bottom_y (w);
1362
1363 /* For mode lines and alike, arrange for the first glyph having a
1364 left box line if the face specifies a box. */
1365 if (base_face_id != DEFAULT_FACE_ID)
1366 {
1367 struct face *face;
1368
1369 it->face_id = base_face_id;
1370
1371 /* If we have a boxed mode line, make the first character appear
1372 with a left box line. */
1373 face = FACE_FROM_ID (it->f, base_face_id);
1374 if (face->box != FACE_NO_BOX)
1375 it->start_of_box_run_p = 1;
1376 }
1377
1378 /* If a buffer position was specified, set the iterator there,
1379 getting overlays and face properties from that position. */
1380 if (charpos > 0)
1381 {
1382 it->end_charpos = ZV;
1383 it->face_id = -1;
1384 IT_CHARPOS (*it) = charpos;
1385
1386 /* Compute byte position if not specified. */
1387 if (bytepos <= 0)
1388 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
1389 else
1390 IT_BYTEPOS (*it) = bytepos;
1391
1392 /* Compute faces etc. */
1393 reseat (it, it->current.pos, 1);
1394 }
1395
1396 CHECK_IT (it);
1397}
1398
1399
1400/* Initialize IT for the display of window W with window start POS. */
1401
1402void
1403start_display (it, w, pos)
1404 struct it *it;
1405 struct window *w;
1406 struct text_pos pos;
1407{
1408 int start_at_line_beg_p;
1409 struct glyph_row *row;
045dee35 1410 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
1411 int first_y;
1412
1413 row = w->desired_matrix->rows + first_vpos;
1414 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
1415 first_y = it->current_y;
1416
1417 /* If window start is not at a line start, move back to the line
1418 start. This makes sure that we take continuation lines into
1419 account. */
1420 start_at_line_beg_p = (CHARPOS (pos) == BEGV
1421 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
1422 if (!start_at_line_beg_p)
1423 reseat_at_previous_visible_line_start (it);
1424
5f5c8ee5
GM
1425 /* If window start is not at a line start, skip forward to POS to
1426 get the correct continuation_lines_width and current_x. */
1427 if (!start_at_line_beg_p)
1428 {
1429 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
1430
1431 /* If lines are continued, this line may end in the middle of a
1432 multi-glyph character (e.g. a control character displayed as
1433 \003, or in the middle of an overlay string). In this case
1434 move_it_to above will not have taken us to the start of
1435 the continuation line but to the end of the continued line. */
1436 if (!it->truncate_lines_p && it->current_x > 0)
1437 {
1438 if (it->current.dpvec_index >= 0
1439 || it->current.overlay_string_index >= 0)
1440 {
1441 set_iterator_to_next (it);
1442 move_it_in_display_line_to (it, -1, -1, 0);
1443 }
1444 it->continuation_lines_width += it->current_x;
1445 }
1446
1447 it->current_y = first_y;
1448 it->vpos = 0;
1449 it->current_x = it->hpos = 0;
1450 }
1451
1452#if 0 /* Don't assert the following because start_display is sometimes
1453 called intentionally with a window start that is not at a
1454 line start. Please leave this code in as a comment. */
1455
1456 /* Window start should be on a line start, now. */
1457 xassert (it->continuation_lines_width
1458 || IT_CHARPOS (it) == BEGV
1459 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
1460#endif /* 0 */
1461}
1462
1463
1464/* Initialize IT for stepping through current_buffer in window W,
1465 starting at position POS that includes overlay string and display
1466 vector/ control character translation position information. */
1467
1468static void
1469init_from_display_pos (it, w, pos)
1470 struct it *it;
1471 struct window *w;
1472 struct display_pos *pos;
1473{
1474 /* Keep in mind: the call to reseat in init_iterator skips invisible
1475 text, so we might end up at a position different from POS. This
1476 is only a problem when POS is a row start after a newline and an
1477 overlay starts there with an after-string, and the overlay has an
1478 invisible property. Since we don't skip invisible text in
1479 display_line and elsewhere immediately after consuming the
1480 newline before the row start, such a POS will not be in a string,
1481 but the call to init_iterator below will move us to the
1482 after-string. */
1483 init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos),
1484 NULL, DEFAULT_FACE_ID);
1485
1486 /* If position is within an overlay string, set up IT to
1487 the right overlay string. */
1488 if (pos->overlay_string_index >= 0)
1489 {
1490 int relative_index;
1491
1492 /* We already have the first chunk of overlay strings in
1493 IT->overlay_strings. Load more until the one for
1494 pos->overlay_string_index is in IT->overlay_strings. */
1495 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
1496 {
1497 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
1498 it->current.overlay_string_index = 0;
1499 while (n--)
1500 {
1501 load_overlay_strings (it);
1502 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
1503 }
1504 }
1505
1506 it->current.overlay_string_index = pos->overlay_string_index;
1507 relative_index = (it->current.overlay_string_index
1508 % OVERLAY_STRING_CHUNK_SIZE);
1509 it->string = it->overlay_strings[relative_index];
1510 it->current.string_pos = pos->string_pos;
1511 it->method = next_element_from_string;
1512 }
1513 else if (CHARPOS (pos->string_pos) >= 0)
1514 {
1515 /* Recorded position is not in an overlay string, but in another
1516 string. This can only be a string from a `display' property.
1517 IT should already be filled with that string. */
1518 it->current.string_pos = pos->string_pos;
1519 xassert (STRINGP (it->string));
1520 }
1521
1522 /* Restore position in display vector translations or control
1523 character translations. */
1524 if (pos->dpvec_index >= 0)
1525 {
1526 /* This fills IT->dpvec. */
1527 get_next_display_element (it);
1528 xassert (it->dpvec && it->current.dpvec_index == 0);
1529 it->current.dpvec_index = pos->dpvec_index;
1530 }
1531
1532 CHECK_IT (it);
1533}
1534
1535
1536/* Initialize IT for stepping through current_buffer in window W
1537 starting at ROW->start. */
1538
1539static void
1540init_to_row_start (it, w, row)
1541 struct it *it;
1542 struct window *w;
1543 struct glyph_row *row;
1544{
1545 init_from_display_pos (it, w, &row->start);
1546 it->continuation_lines_width = row->continuation_lines_width;
1547 CHECK_IT (it);
1548}
1549
1550
1551/* Initialize IT for stepping through current_buffer in window W
1552 starting in the line following ROW, i.e. starting at ROW->end. */
1553
1554static void
1555init_to_row_end (it, w, row)
1556 struct it *it;
1557 struct window *w;
1558 struct glyph_row *row;
1559{
1560 init_from_display_pos (it, w, &row->end);
1561
1562 if (row->continued_p)
1563 it->continuation_lines_width = (row->continuation_lines_width
1564 + row->pixel_width);
1565 CHECK_IT (it);
1566}
1567
1568
1569
1570\f
1571/***********************************************************************
1572 Text properties
1573 ***********************************************************************/
1574
1575/* Called when IT reaches IT->stop_charpos. Handle text property and
1576 overlay changes. Set IT->stop_charpos to the next position where
1577 to stop. */
1578
1579static void
1580handle_stop (it)
1581 struct it *it;
1582{
1583 enum prop_handled handled;
1584 int handle_overlay_change_p = 1;
1585 struct props *p;
1586
1587 it->dpvec = NULL;
1588 it->current.dpvec_index = -1;
1589
1590 do
1591 {
1592 handled = HANDLED_NORMALLY;
1593
1594 /* Call text property handlers. */
1595 for (p = it_props; p->handler; ++p)
1596 {
1597 handled = p->handler (it);
1598
1599 if (handled == HANDLED_RECOMPUTE_PROPS)
1600 break;
1601 else if (handled == HANDLED_RETURN)
1602 return;
1603 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
1604 handle_overlay_change_p = 0;
1605 }
1606
1607 if (handled != HANDLED_RECOMPUTE_PROPS)
1608 {
1609 /* Don't check for overlay strings below when set to deliver
1610 characters from a display vector. */
1611 if (it->method == next_element_from_display_vector)
1612 handle_overlay_change_p = 0;
1613
1614 /* Handle overlay changes. */
1615 if (handle_overlay_change_p)
1616 handled = handle_overlay_change (it);
1617
1618 /* Determine where to stop next. */
1619 if (handled == HANDLED_NORMALLY)
1620 compute_stop_pos (it);
1621 }
1622 }
1623 while (handled == HANDLED_RECOMPUTE_PROPS);
1624}
1625
1626
1627/* Compute IT->stop_charpos from text property and overlay change
1628 information for IT's current position. */
1629
1630static void
1631compute_stop_pos (it)
1632 struct it *it;
1633{
1634 register INTERVAL iv, next_iv;
1635 Lisp_Object object, limit, position;
1636
1637 /* If nowhere else, stop at the end. */
1638 it->stop_charpos = it->end_charpos;
1639
1640 if (STRINGP (it->string))
1641 {
1642 /* Strings are usually short, so don't limit the search for
1643 properties. */
1644 object = it->string;
1645 limit = Qnil;
1646 XSETFASTINT (position, IT_STRING_CHARPOS (*it));
1647 }
1648 else
1649 {
1650 int charpos;
1651
1652 /* If next overlay change is in front of the current stop pos
1653 (which is IT->end_charpos), stop there. Note: value of
1654 next_overlay_change is point-max if no overlay change
1655 follows. */
1656 charpos = next_overlay_change (IT_CHARPOS (*it));
1657 if (charpos < it->stop_charpos)
1658 it->stop_charpos = charpos;
1659
1660 /* If showing the region, we have to stop at the region
1661 start or end because the face might change there. */
1662 if (it->region_beg_charpos > 0)
1663 {
1664 if (IT_CHARPOS (*it) < it->region_beg_charpos)
1665 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
1666 else if (IT_CHARPOS (*it) < it->region_end_charpos)
1667 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
1668 }
1669
1670 /* Set up variables for computing the stop position from text
1671 property changes. */
1672 XSETBUFFER (object, current_buffer);
1673 XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
1674 XSETFASTINT (position, IT_CHARPOS (*it));
1675
1676 }
1677
1678 /* Get the interval containing IT's position. Value is a null
1679 interval if there isn't such an interval. */
1680 iv = validate_interval_range (object, &position, &position, 0);
1681 if (!NULL_INTERVAL_P (iv))
1682 {
1683 Lisp_Object values_here[LAST_PROP_IDX];
1684 struct props *p;
1685
1686 /* Get properties here. */
1687 for (p = it_props; p->handler; ++p)
1688 values_here[p->idx] = textget (iv->plist, *p->name);
1689
1690 /* Look for an interval following iv that has different
1691 properties. */
1692 for (next_iv = next_interval (iv);
1693 (!NULL_INTERVAL_P (next_iv)
1694 && (NILP (limit)
1695 || XFASTINT (limit) > next_iv->position));
1696 next_iv = next_interval (next_iv))
1697 {
1698 for (p = it_props; p->handler; ++p)
1699 {
1700 Lisp_Object new_value;
1701
1702 new_value = textget (next_iv->plist, *p->name);
1703 if (!EQ (values_here[p->idx], new_value))
1704 break;
1705 }
1706
1707 if (p->handler)
1708 break;
1709 }
1710
1711 if (!NULL_INTERVAL_P (next_iv))
1712 {
1713 if (INTEGERP (limit)
1714 && next_iv->position >= XFASTINT (limit))
1715 /* No text property change up to limit. */
1716 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
1717 else
1718 /* Text properties change in next_iv. */
1719 it->stop_charpos = min (it->stop_charpos, next_iv->position);
1720 }
1721 }
1722
1723 xassert (STRINGP (it->string)
1724 || (it->stop_charpos >= BEGV
1725 && it->stop_charpos >= IT_CHARPOS (*it)));
1726}
1727
1728
1729/* Return the position of the next overlay change after POS in
1730 current_buffer. Value is point-max if no overlay change
1731 follows. This is like `next-overlay-change' but doesn't use
1732 xmalloc. */
1733
1734static int
1735next_overlay_change (pos)
1736 int pos;
1737{
1738 int noverlays;
1739 int endpos;
1740 Lisp_Object *overlays;
1741 int len;
1742 int i;
1743
1744 /* Get all overlays at the given position. */
1745 len = 10;
1746 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
1747 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
1748 if (noverlays > len)
1749 {
1750 len = noverlays;
1751 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
1752 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
1753 }
1754
1755 /* If any of these overlays ends before endpos,
1756 use its ending point instead. */
1757 for (i = 0; i < noverlays; ++i)
1758 {
1759 Lisp_Object oend;
1760 int oendpos;
1761
1762 oend = OVERLAY_END (overlays[i]);
1763 oendpos = OVERLAY_POSITION (oend);
1764 endpos = min (endpos, oendpos);
1765 }
1766
1767 return endpos;
1768}
1769
1770
1771\f
1772/***********************************************************************
1773 Fontification
1774 ***********************************************************************/
1775
1776/* Handle changes in the `fontified' property of the current buffer by
1777 calling hook functions from Qfontification_functions to fontify
1778 regions of text. */
1779
1780static enum prop_handled
1781handle_fontified_prop (it)
1782 struct it *it;
1783{
1784 Lisp_Object prop, pos;
1785 enum prop_handled handled = HANDLED_NORMALLY;
1786
1787 /* Get the value of the `fontified' property at IT's current buffer
1788 position. (The `fontified' property doesn't have a special
1789 meaning in strings.) If the value is nil, call functions from
1790 Qfontification_functions. */
1791 if (!STRINGP (it->string)
1792 && it->s == NULL
1793 && !NILP (Vfontification_functions)
1794 && (pos = make_number (IT_CHARPOS (*it)),
1795 prop = Fget_char_property (pos, Qfontified, Qnil),
1796 NILP (prop)))
1797 {
1798 Lisp_Object args[2];
1799
1800 /* Run the hook functions. */
1801 args[0] = Qfontification_functions;
1802 args[1] = pos;
1803 Frun_hook_with_args (make_number (2), args);
1804
1805 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
1806 something. This avoids an endless loop if they failed to
1807 fontify the text for which reason ever. */
1808 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
1809 handled = HANDLED_RECOMPUTE_PROPS;
1810 }
1811
1812 return handled;
1813}
1814
1815
1816\f
1817/***********************************************************************
1818 Faces
1819 ***********************************************************************/
1820
1821/* Set up iterator IT from face properties at its current position.
1822 Called from handle_stop. */
1823
1824static enum prop_handled
1825handle_face_prop (it)
1826 struct it *it;
1827{
1828 int new_face_id, next_stop;
1829
1830 if (!STRINGP (it->string))
1831 {
1832 new_face_id
1833 = face_at_buffer_position (it->w,
1834 IT_CHARPOS (*it),
1835 it->region_beg_charpos,
1836 it->region_end_charpos,
1837 &next_stop,
1838 (IT_CHARPOS (*it)
1839 + TEXT_PROP_DISTANCE_LIMIT),
1840 0);
1841
1842 /* Is this a start of a run of characters with box face?
1843 Caveat: this can be called for a freshly initialized
1844 iterator; face_id is -1 is this case. We know that the new
1845 face will not change until limit, i.e. if the new face has a
1846 box, all characters up to limit will have one. But, as
1847 usual, we don't know whether limit is really the end. */
1848 if (new_face_id != it->face_id)
1849 {
1850 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1851
1852 /* If new face has a box but old face has not, this is
1853 the start of a run of characters with box, i.e. it has
1854 a shadow on the left side. The value of face_id of the
1855 iterator will be -1 if this is the initial call that gets
1856 the face. In this case, we have to look in front of IT's
1857 position and see whether there is a face != new_face_id. */
1858 it->start_of_box_run_p
1859 = (new_face->box != FACE_NO_BOX
1860 && (it->face_id >= 0
1861 || IT_CHARPOS (*it) == BEG
1862 || new_face_id != face_before_it_pos (it)));
1863 it->face_box_p = new_face->box != FACE_NO_BOX;
1864 }
1865 }
1866 else
1867 {
1868 new_face_id
1869 = face_at_string_position (it->w,
1870 it->string,
1871 IT_STRING_CHARPOS (*it),
1872 (it->current.overlay_string_index >= 0
1873 ? IT_CHARPOS (*it)
1874 : 0),
1875 it->region_beg_charpos,
1876 it->region_end_charpos,
1877 &next_stop,
1878 it->base_face_id);
1879
1880#if 0 /* This shouldn't be neccessary. Let's check it. */
1881 /* If IT is used to display a mode line we would really like to
1882 use the mode line face instead of the frame's default face. */
1883 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
1884 && new_face_id == DEFAULT_FACE_ID)
1885 new_face_id = MODE_LINE_FACE_ID;
1886#endif
1887
1888 /* Is this a start of a run of characters with box? Caveat:
1889 this can be called for a freshly allocated iterator; face_id
1890 is -1 is this case. We know that the new face will not
1891 change until the next check pos, i.e. if the new face has a
1892 box, all characters up to that position will have a
1893 box. But, as usual, we don't know whether that position
1894 is really the end. */
1895 if (new_face_id != it->face_id)
1896 {
1897 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1898 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
1899
1900 /* If new face has a box but old face hasn't, this is the
1901 start of a run of characters with box, i.e. it has a
1902 shadow on the left side. */
1903 it->start_of_box_run_p
1904 = new_face->box && (old_face == NULL || !old_face->box);
1905 it->face_box_p = new_face->box != FACE_NO_BOX;
1906 }
1907 }
1908
1909 it->face_id = new_face_id;
1910 it->charset = CHARSET_ASCII;
1911 return HANDLED_NORMALLY;
1912}
1913
1914
1915/* Compute the face one character before or after the current position
1916 of IT. BEFORE_P non-zero means get the face in front of IT's
1917 position. Value is the id of the face. */
1918
1919static int
1920face_before_or_after_it_pos (it, before_p)
1921 struct it *it;
1922 int before_p;
1923{
1924 int face_id, limit;
1925 int next_check_charpos;
1926 struct text_pos pos;
1927
1928 xassert (it->s == NULL);
1929
1930 if (STRINGP (it->string))
1931 {
1932 /* No face change past the end of the string (for the case
1933 we are padding with spaces). No face change before the
1934 string start. */
1935 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size
1936 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
1937 return it->face_id;
1938
1939 /* Set pos to the position before or after IT's current position. */
1940 if (before_p)
1941 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
1942 else
1943 pos = string_pos (IT_STRING_CHARPOS (*it) + 1, it->string);
1944
1945 /* Get the face for ASCII, or unibyte. */
1946 face_id
1947 = face_at_string_position (it->w,
1948 it->string,
1949 CHARPOS (pos),
1950 (it->current.overlay_string_index >= 0
1951 ? IT_CHARPOS (*it)
1952 : 0),
1953 it->region_beg_charpos,
1954 it->region_end_charpos,
1955 &next_check_charpos,
1956 it->base_face_id);
1957
1958 /* Correct the face for charsets different from ASCII. Do it
1959 for the multibyte case only. The face returned above is
1960 suitable for unibyte text if IT->string is unibyte. */
1961 if (STRING_MULTIBYTE (it->string))
1962 {
1963 unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
1964 int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
1965 int c, len, charset;
1966
4fdb80f2 1967 c = string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1968 charset = CHAR_CHARSET (c);
1969 if (charset != CHARSET_ASCII)
1970 face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
1971 }
1972 }
1973 else
1974 {
70851746
GM
1975 if ((IT_CHARPOS (*it) >= ZV && !before_p)
1976 || (IT_CHARPOS (*it) <= BEGV && before_p))
1977 return it->face_id;
1978
5f5c8ee5
GM
1979 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
1980 pos = it->current.pos;
1981
1982 if (before_p)
1983 DEC_TEXT_POS (pos);
1984 else
1985 INC_TEXT_POS (pos);
70851746 1986
5f5c8ee5
GM
1987 /* Determine face for CHARSET_ASCII, or unibyte. */
1988 face_id = face_at_buffer_position (it->w,
1989 CHARPOS (pos),
1990 it->region_beg_charpos,
1991 it->region_end_charpos,
1992 &next_check_charpos,
1993 limit, 0);
1994
1995 /* Correct the face for charsets different from ASCII. Do it
1996 for the multibyte case only. The face returned above is
1997 suitable for unibyte text if current_buffer is unibyte. */
1998 if (it->multibyte_p)
1999 {
2000 int charset = charset_at_position (pos);
2001 if (charset != CHARSET_ASCII)
2002 face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
2003 }
2004 }
2005
2006 return face_id;
2007}
2008
2009
2010\f
2011/***********************************************************************
2012 Invisible text
2013 ***********************************************************************/
2014
2015/* Set up iterator IT from invisible properties at its current
2016 position. Called from handle_stop. */
2017
2018static enum prop_handled
2019handle_invisible_prop (it)
2020 struct it *it;
2021{
2022 enum prop_handled handled = HANDLED_NORMALLY;
2023
2024 if (STRINGP (it->string))
2025 {
2026 extern Lisp_Object Qinvisible;
2027 Lisp_Object prop, end_charpos, limit, charpos;
2028
2029 /* Get the value of the invisible text property at the
2030 current position. Value will be nil if there is no such
2031 property. */
2032 XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
2033 prop = Fget_text_property (charpos, Qinvisible, it->string);
2034
2035 if (!NILP (prop))
2036 {
2037 handled = HANDLED_RECOMPUTE_PROPS;
2038
2039 /* Get the position at which the next change of the
2040 invisible text property can be found in IT->string.
2041 Value will be nil if the property value is the same for
2042 all the rest of IT->string. */
2043 XSETINT (limit, XSTRING (it->string)->size);
2044 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2045 it->string, limit);
2046
2047 /* Text at current position is invisible. The next
2048 change in the property is at position end_charpos.
2049 Move IT's current position to that position. */
2050 if (INTEGERP (end_charpos)
2051 && XFASTINT (end_charpos) < XFASTINT (limit))
2052 {
2053 struct text_pos old;
2054 old = it->current.string_pos;
2055 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
2056 compute_string_pos (&it->current.string_pos, old, it->string);
2057 }
2058 else
2059 {
2060 /* The rest of the string is invisible. If this is an
2061 overlay string, proceed with the next overlay string
2062 or whatever comes and return a character from there. */
2063 if (it->current.overlay_string_index >= 0)
2064 {
2065 next_overlay_string (it);
2066 /* Don't check for overlay strings when we just
2067 finished processing them. */
2068 handled = HANDLED_OVERLAY_STRING_CONSUMED;
2069 }
2070 else
2071 {
2072 struct Lisp_String *s = XSTRING (it->string);
2073 IT_STRING_CHARPOS (*it) = s->size;
2074 IT_STRING_BYTEPOS (*it) = STRING_BYTES (s);
2075 }
2076 }
2077 }
2078 }
2079 else
2080 {
2081 int visible_p, newpos, next_stop;
2082 Lisp_Object pos, prop;
2083
2084 /* First of all, is there invisible text at this position? */
2085 XSETFASTINT (pos, IT_CHARPOS (*it));
2086 prop = Fget_char_property (pos, Qinvisible, it->window);
2087
2088 /* If we are on invisible text, skip over it. */
2089 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2090 {
2091 /* Record whether we have to display an ellipsis for the
2092 invisible text. */
2093 int display_ellipsis_p
2094 = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
2095
2096 handled = HANDLED_RECOMPUTE_PROPS;
2097
2098 /* Loop skipping over invisible text. The loop is left at
2099 ZV or with IT on the first char being visible again. */
2100 do
2101 {
2102 /* Try to skip some invisible text. Return value is the
2103 position reached which can be equal to IT's position
2104 if there is nothing invisible here. This skips both
2105 over invisible text properties and overlays with
2106 invisible property. */
2107 newpos = skip_invisible (IT_CHARPOS (*it),
2108 &next_stop, ZV, it->window);
2109
2110 /* If we skipped nothing at all we weren't at invisible
2111 text in the first place. If everything to the end of
2112 the buffer was skipped, end the loop. */
2113 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
2114 visible_p = 1;
2115 else
2116 {
2117 /* We skipped some characters but not necessarily
2118 all there are. Check if we ended up on visible
2119 text. Fget_char_property returns the property of
2120 the char before the given position, i.e. if we
2121 get visible_p = 1, this means that the char at
2122 newpos is visible. */
2123 XSETFASTINT (pos, newpos);
2124 prop = Fget_char_property (pos, Qinvisible, it->window);
2125 visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
2126 }
2127
2128 /* If we ended up on invisible text, proceed to
2129 skip starting with next_stop. */
2130 if (!visible_p)
2131 IT_CHARPOS (*it) = next_stop;
2132 }
2133 while (!visible_p);
2134
2135 /* The position newpos is now either ZV or on visible text. */
2136 IT_CHARPOS (*it) = newpos;
2137 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2138
2139 /* Maybe return `...' next for the end of the invisible text. */
2140 if (display_ellipsis_p)
2141 {
2142 if (it->dp
2143 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
2144 {
2145 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
2146 it->dpvec = v->contents;
2147 it->dpend = v->contents + v->size;
2148 }
2149 else
2150 {
2151 /* Default `...'. */
2152 it->dpvec = default_invis_vector;
2153 it->dpend = default_invis_vector + 3;
2154 }
2155
2156 /* The ellipsis display does not replace the display of
2157 the character at the new position. Indicate this by
2158 setting IT->dpvec_char_len to zero. */
2159 it->dpvec_char_len = 0;
2160
2161 it->current.dpvec_index = 0;
2162 it->method = next_element_from_display_vector;
2163 }
2164 }
2165 }
2166
2167 return handled;
2168}
2169
2170
2171\f
2172/***********************************************************************
2173 'display' property
2174 ***********************************************************************/
2175
2176/* Set up iterator IT from `display' property at its current position.
2177 Called from handle_stop. */
2178
2179static enum prop_handled
2180handle_display_prop (it)
2181 struct it *it;
2182{
2183 Lisp_Object prop, object;
2184 struct text_pos *position;
2185 int space_or_image_found_p;
2186
2187 if (STRINGP (it->string))
2188 {
2189 object = it->string;
2190 position = &it->current.string_pos;
2191 }
2192 else
2193 {
2194 object = Qnil;
2195 position = &it->current.pos;
2196 }
2197
2198 /* Reset those iterator values set from display property values. */
2199 it->font_height = Qnil;
2200 it->space_width = Qnil;
2201 it->voffset = 0;
2202
2203 /* We don't support recursive `display' properties, i.e. string
2204 values that have a string `display' property, that have a string
2205 `display' property etc. */
2206 if (!it->string_from_display_prop_p)
2207 it->area = TEXT_AREA;
2208
2209 prop = Fget_char_property (make_number (position->charpos),
2210 Qdisplay, object);
2211 if (NILP (prop))
2212 return HANDLED_NORMALLY;
2213
2214 space_or_image_found_p = 0;
2215 if (CONSP (prop) && CONSP (XCAR (prop)))
2216 {
2217 while (CONSP (prop))
2218 {
2219 if (handle_single_display_prop (it, XCAR (prop), object, position))
2220 space_or_image_found_p = 1;
2221 prop = XCDR (prop);
2222 }
2223 }
2224 else if (VECTORP (prop))
2225 {
2226 int i;
2227 for (i = 0; i < XVECTOR (prop)->size; ++i)
2228 if (handle_single_display_prop (it, XVECTOR (prop)->contents[i],
2229 object, position))
2230 space_or_image_found_p = 1;
2231 }
2232 else
2233 {
2234 if (handle_single_display_prop (it, prop, object, position))
2235 space_or_image_found_p = 1;
2236 }
2237
2238 return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY;
2239}
2240
2241
2242/* Value is the position of the end of the `display' property stating
2243 at START_POS in OBJECT. */
2244
2245static struct text_pos
2246display_prop_end (it, object, start_pos)
2247 struct it *it;
2248 Lisp_Object object;
2249 struct text_pos start_pos;
2250{
2251 Lisp_Object end;
2252 struct text_pos end_pos;
2253
2254 /* Characters having this form of property are not displayed, so
2255 we have to find the end of the property. */
2256 end = Fnext_single_property_change (make_number (start_pos.charpos),
2257 Qdisplay, object, Qnil);
2258 if (NILP (end))
2259 {
2260 /* A nil value of `end' means there are no changes of the
2261 property to the end of the buffer or string. */
2262 if (it->current.overlay_string_index >= 0)
2263 end_pos.charpos = XSTRING (it->string)->size;
2264 else
2265 end_pos.charpos = it->end_charpos;
2266 }
2267 else
2268 end_pos.charpos = XFASTINT (end);
2269
2270 if (STRINGP (it->string))
2271 compute_string_pos (&end_pos, start_pos, it->string);
2272 else
2273 end_pos.bytepos = CHAR_TO_BYTE (end_pos.charpos);
2274
2275 return end_pos;
2276}
2277
2278
2279/* Set up IT from a single `display' sub-property value PROP. OBJECT
2280 is the object in which the `display' property was found. *POSITION
2281 is the position at which it was found.
2282
2283 If PROP is a `space' or `image' sub-property, set *POSITION to the
2284 end position of the `display' property.
2285
2286 Value is non-zero if a `space' or `image' property value was found. */
2287
2288static int
2289handle_single_display_prop (it, prop, object, position)
2290 struct it *it;
2291 Lisp_Object prop;
2292 Lisp_Object object;
2293 struct text_pos *position;
2294{
2295 Lisp_Object value;
2296 int space_or_image_found_p = 0;
2297
2298 Lisp_Object form;
2299
d3acf96b 2300 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
5a4c88c4 2301 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 2302 form = Qt;
d3acf96b 2303 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
2304 {
2305 prop = XCDR (prop);
2306 if (!CONSP (prop))
2307 return 0;
2308 form = XCAR (prop);
2309 prop = XCDR (prop);
5f5c8ee5
GM
2310 }
2311
2312 if (!NILP (form) && !EQ (form, Qt))
2313 {
2314 struct gcpro gcpro1;
2315 struct text_pos end_pos, pt;
2316
2317 end_pos = display_prop_end (it, object, *position);
2318 GCPRO1 (form);
2319
2320 /* Temporarily set point to the end position, and then evaluate
2321 the form. This makes `(eolp)' work as FORM. */
2322 CHARPOS (pt) = PT;
2323 BYTEPOS (pt) = PT_BYTE;
2324 TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
2325 form = eval_form (form);
2326 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
2327 UNGCPRO;
2328 }
2329
2330 if (NILP (form))
2331 return 0;
2332
2333 if (CONSP (prop)
2334 && EQ (XCAR (prop), Qheight)
2335 && CONSP (XCDR (prop)))
2336 {
2337 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2338 return 0;
2339
2340 /* `(height HEIGHT)'. */
2341 it->font_height = XCAR (XCDR (prop));
2342 if (!NILP (it->font_height))
2343 {
2344 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2345 int new_height = -1;
2346
2347 if (CONSP (it->font_height)
2348 && (EQ (XCAR (it->font_height), Qplus)
2349 || EQ (XCAR (it->font_height), Qminus))
2350 && CONSP (XCDR (it->font_height))
2351 && INTEGERP (XCAR (XCDR (it->font_height))))
2352 {
2353 /* `(+ N)' or `(- N)' where N is an integer. */
2354 int steps = XINT (XCAR (XCDR (it->font_height)));
2355 if (EQ (XCAR (it->font_height), Qplus))
2356 steps = - steps;
2357 it->face_id = smaller_face (it->f, it->face_id, steps);
2358 }
2359 else if (SYMBOLP (it->font_height))
2360 {
2361 /* Call function with current height as argument.
2362 Value is the new height. */
2363 Lisp_Object form, height;
2364 struct gcpro gcpro1;
2365
2366 height = face->lface[LFACE_HEIGHT_INDEX];
2367 form = Fcons (it->font_height, Fcons (height, Qnil));
2368 GCPRO1 (form);
2369 height = eval_form (form);
2370 if (NUMBERP (height))
2371 new_height = XFLOATINT (height);
2372 UNGCPRO;
2373 }
2374 else if (NUMBERP (it->font_height))
2375 {
2376 /* Value is a multiple of the canonical char height. */
2377 struct face *face;
2378
2379 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
2380 new_height = (XFLOATINT (it->font_height)
2381 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
2382 }
2383 else
2384 {
2385 /* Evaluate IT->font_height with `height' bound to the
2386 current specified height to get the new height. */
2387 Lisp_Object value;
2388 int count = specpdl_ptr - specpdl;
2389
2390 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
2391 value = eval_form (it->font_height);
2392 unbind_to (count, Qnil);
2393
2394 if (NUMBERP (value))
2395 new_height = XFLOATINT (value);
2396 }
2397
2398 if (new_height > 0)
2399 it->face_id = face_with_height (it->f, it->face_id, new_height);
2400 }
2401 }
2402 else if (CONSP (prop)
2403 && EQ (XCAR (prop), Qspace_width)
2404 && CONSP (XCDR (prop)))
2405 {
2406 /* `(space_width WIDTH)'. */
2407 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2408 return 0;
2409
2410 value = XCAR (XCDR (prop));
2411 if (NUMBERP (value) && XFLOATINT (value) > 0)
2412 it->space_width = value;
2413 }
2414 else if (CONSP (prop)
2415 && EQ (XCAR (prop), Qraise)
2416 && CONSP (XCDR (prop)))
2417 {
2418#ifdef HAVE_WINDOW_SYSTEM
2419 /* `(raise FACTOR)'. */
2420 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2421 return 0;
2422
2423 value = XCAR (XCDR (prop));
2424 if (NUMBERP (value))
2425 {
2426 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2427 it->voffset = - (XFLOATINT (value)
2428 * (face->font->ascent + face->font->descent));
2429 }
2430#endif /* HAVE_WINDOW_SYSTEM */
2431 }
2432 else if (!it->string_from_display_prop_p)
2433 {
2434 /* `(left-margin VALUE)' or `(right-margin VALUE)
2435 or `(nil VALUE)' or VALUE. */
2436 Lisp_Object location, value;
2437 struct text_pos start_pos;
2438 int valid_p;
2439
2440 /* Characters having this form of property are not displayed, so
2441 we have to find the end of the property. */
2442 space_or_image_found_p = 1;
2443 start_pos = *position;
2444 *position = display_prop_end (it, object, start_pos);
2445
2446 /* Let's stop at the new position and assume that all
2447 text properties change there. */
2448 it->stop_charpos = position->charpos;
2449
2450 if (CONSP (prop)
2451 && !EQ (XCAR (prop), Qspace)
2452 && !EQ (XCAR (prop), Qimage))
2453 {
2454 location = XCAR (prop);
2455 value = XCDR (prop);
2456 }
2457 else
2458 {
2459 location = Qnil;
2460 value = prop;
2461 }
2462
2463#ifdef HAVE_WINDOW_SYSTEM
2464 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2465 valid_p = STRINGP (value);
2466 else
2467 valid_p = (STRINGP (value)
2468 || (CONSP (value) && EQ (XCAR (value), Qspace))
2469 || valid_image_p (value));
2470#else /* not HAVE_WINDOW_SYSTEM */
2471 valid_p = STRINGP (value);
2472#endif /* not HAVE_WINDOW_SYSTEM */
2473
2474 if ((EQ (location, Qleft_margin)
2475 || EQ (location, Qright_margin)
2476 || NILP (location))
2477 && valid_p)
2478 {
2479 /* Save current settings of IT so that we can restore them
2480 when we are finished with the glyph property value. */
2481 push_it (it);
2482
2483 if (NILP (location))
2484 it->area = TEXT_AREA;
2485 else if (EQ (location, Qleft_margin))
2486 it->area = LEFT_MARGIN_AREA;
2487 else
2488 it->area = RIGHT_MARGIN_AREA;
2489
2490 if (STRINGP (value))
2491 {
2492 it->string = value;
2493 it->multibyte_p = STRING_MULTIBYTE (it->string);
2494 it->current.overlay_string_index = -1;
2495 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2496 it->end_charpos = it->string_nchars
2497 = XSTRING (it->string)->size;
2498 it->method = next_element_from_string;
2499 it->stop_charpos = 0;
2500 it->string_from_display_prop_p = 1;
2501 }
2502 else if (CONSP (value) && EQ (XCAR (value), Qspace))
2503 {
2504 it->method = next_element_from_stretch;
2505 it->object = value;
2506 it->current.pos = it->position = start_pos;
2507 }
2508#ifdef HAVE_WINDOW_SYSTEM
2509 else
2510 {
2511 it->what = IT_IMAGE;
2512 it->image_id = lookup_image (it->f, value);
2513 it->position = start_pos;
2514 it->object = NILP (object) ? it->w->buffer : object;
2515 it->method = next_element_from_image;
2516
2517 /* Say that we don't have consumed the characters with
2518 `display' property yet. The call to pop_it in
2519 set_iterator_to_next will clean this up. */
2520 *position = start_pos;
2521 }
2522#endif /* HAVE_WINDOW_SYSTEM */
2523 }
2524 }
2525
2526 return space_or_image_found_p;
2527}
2528
2529
2530\f
2531/***********************************************************************
2532 Overlay strings
2533 ***********************************************************************/
2534
2535/* The following structure is used to record overlay strings for
2536 later sorting in load_overlay_strings. */
2537
2538struct overlay_entry
2539{
2540 Lisp_Object string;
2541 int priority;
2542 int after_string_p;
2543};
2544
2545
2546/* Set up iterator IT from overlay strings at its current position.
2547 Called from handle_stop. */
2548
2549static enum prop_handled
2550handle_overlay_change (it)
2551 struct it *it;
2552{
2553 /* Overlays are handled in current_buffer only. */
2554 if (STRINGP (it->string))
2555 return HANDLED_NORMALLY;
2556 else
2557 return (get_overlay_strings (it)
2558 ? HANDLED_RECOMPUTE_PROPS
2559 : HANDLED_NORMALLY);
2560}
2561
2562
2563/* Set up the next overlay string for delivery by IT, if there is an
2564 overlay string to deliver. Called by set_iterator_to_next when the
2565 end of the current overlay string is reached. If there are more
2566 overlay strings to display, IT->string and
2567 IT->current.overlay_string_index are set appropriately here.
2568 Otherwise IT->string is set to nil. */
2569
2570static void
2571next_overlay_string (it)
2572 struct it *it;
2573{
2574 ++it->current.overlay_string_index;
2575 if (it->current.overlay_string_index == it->n_overlay_strings)
2576 {
2577 /* No more overlay strings. Restore IT's settings to what
2578 they were before overlay strings were processed, and
2579 continue to deliver from current_buffer. */
2580 pop_it (it);
2581 xassert (it->stop_charpos >= BEGV
2582 && it->stop_charpos <= it->end_charpos);
2583 it->string = Qnil;
2584 it->current.overlay_string_index = -1;
2585 SET_TEXT_POS (it->current.string_pos, -1, -1);
2586 it->n_overlay_strings = 0;
2587 it->method = next_element_from_buffer;
2588 }
2589 else
2590 {
2591 /* There are more overlay strings to process. If
2592 IT->current.overlay_string_index has advanced to a position
2593 where we must load IT->overlay_strings with more strings, do
2594 it. */
2595 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2596
2597 if (it->current.overlay_string_index && i == 0)
2598 load_overlay_strings (it);
2599
2600 /* Initialize IT to deliver display elements from the overlay
2601 string. */
2602 it->string = it->overlay_strings[i];
2603 it->multibyte_p = STRING_MULTIBYTE (it->string);
2604 SET_TEXT_POS (it->current.string_pos, 0, 0);
2605 it->method = next_element_from_string;
2606 it->stop_charpos = 0;
2607 }
2608
2609 CHECK_IT (it);
2610}
2611
2612
2613/* Compare two overlay_entry structures E1 and E2. Used as a
2614 comparison function for qsort in load_overlay_strings. Overlay
2615 strings for the same position are sorted so that
2616
2617 1. All after-strings come in front of before-strings.
2618
2619 2. Within after-strings, strings are sorted so that overlay strings
2620 from overlays with higher priorities come first.
2621
2622 2. Within before-strings, strings are sorted so that overlay
2623 strings from overlays with higher priorities come last.
2624
2625 Value is analogous to strcmp. */
2626
2627
2628static int
2629compare_overlay_entries (e1, e2)
2630 void *e1, *e2;
2631{
2632 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
2633 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
2634 int result;
2635
2636 if (entry1->after_string_p != entry2->after_string_p)
2637 /* Let after-strings appear in front of before-strings. */
2638 result = entry1->after_string_p ? -1 : 1;
2639 else if (entry1->after_string_p)
2640 /* After-strings sorted in order of decreasing priority. */
2641 result = entry2->priority - entry1->priority;
2642 else
2643 /* Before-strings sorted in order of increasing priority. */
2644 result = entry1->priority - entry2->priority;
2645
2646 return result;
2647}
2648
2649
2650/* Load the vector IT->overlay_strings with overlay strings from IT's
2651 current buffer position. Set IT->n_overlays to the total number of
2652 overlay strings found.
2653
2654 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
2655 a time. On entry into load_overlay_strings,
2656 IT->current.overlay_string_index gives the number of overlay
2657 strings that have already been loaded by previous calls to this
2658 function.
2659
2660 Overlay strings are sorted so that after-string strings come in
2661 front of before-string strings. Within before and after-strings,
2662 strings are sorted by overlay priority. See also function
2663 compare_overlay_entries. */
2664
2665static void
2666load_overlay_strings (it)
2667 struct it *it;
2668{
2669 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
2670 Lisp_Object ov, overlay, window, str;
2671 int start, end;
2672 int size = 20;
2673 int n = 0, i, j;
2674 struct overlay_entry *entries
2675 = (struct overlay_entry *) alloca (size * sizeof *entries);
2676
2677 /* Append the overlay string STRING of overlay OVERLAY to vector
2678 `entries' which has size `size' and currently contains `n'
2679 elements. AFTER_P non-zero means STRING is an after-string of
2680 OVERLAY. */
2681#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
2682 do \
2683 { \
2684 Lisp_Object priority; \
2685 \
2686 if (n == size) \
2687 { \
2688 int new_size = 2 * size; \
2689 struct overlay_entry *old = entries; \
2690 entries = \
2691 (struct overlay_entry *) alloca (new_size \
2692 * sizeof *entries); \
2693 bcopy (old, entries, size * sizeof *entries); \
2694 size = new_size; \
2695 } \
2696 \
2697 entries[n].string = (STRING); \
2698 priority = Foverlay_get ((OVERLAY), Qpriority); \
2699 entries[n].priority \
2700 = INTEGERP (priority) ? XFASTINT (priority) : 0; \
2701 entries[n].after_string_p = (AFTER_P); \
2702 ++n; \
2703 } \
2704 while (0)
2705
2706 /* Process overlay before the overlay center. */
2707 for (ov = current_buffer->overlays_before;
2708 CONSP (ov);
9472f927 2709 ov = XCDR (ov))
5f5c8ee5 2710 {
9472f927 2711 overlay = XCAR (ov);
5f5c8ee5
GM
2712 xassert (OVERLAYP (overlay));
2713 start = OVERLAY_POSITION (OVERLAY_START (overlay));
2714 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2715
2716 if (end < IT_CHARPOS (*it))
2717 break;
2718
2719 /* Skip this overlay if it doesn't start or end at IT's current
2720 position. */
2721 if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
2722 continue;
2723
2724 /* Skip this overlay if it doesn't apply to IT->w. */
2725 window = Foverlay_get (overlay, Qwindow);
2726 if (WINDOWP (window) && XWINDOW (window) != it->w)
2727 continue;
2728
2729 /* If overlay has a non-empty before-string, record it. */
2730 if (start == IT_CHARPOS (*it)
2731 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2732 && XSTRING (str)->size)
2733 RECORD_OVERLAY_STRING (overlay, str, 0);
2734
2735 /* If overlay has a non-empty after-string, record it. */
2736 if (end == IT_CHARPOS (*it)
2737 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2738 && XSTRING (str)->size)
2739 RECORD_OVERLAY_STRING (overlay, str, 1);
2740 }
2741
2742 /* Process overlays after the overlay center. */
2743 for (ov = current_buffer->overlays_after;
2744 CONSP (ov);
9472f927 2745 ov = XCDR (ov))
5f5c8ee5 2746 {
9472f927 2747 overlay = XCAR (ov);
5f5c8ee5
GM
2748 xassert (OVERLAYP (overlay));
2749 start = OVERLAY_POSITION (OVERLAY_START (overlay));
2750 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2751
2752 if (start > IT_CHARPOS (*it))
2753 break;
2754
2755 /* Skip this overlay if it doesn't start or end at IT's current
2756 position. */
2757 if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
2758 continue;
2759
2760 /* Skip this overlay if it doesn't apply to IT->w. */
2761 window = Foverlay_get (overlay, Qwindow);
2762 if (WINDOWP (window) && XWINDOW (window) != it->w)
2763 continue;
2764
2765 /* If overlay has a non-empty before-string, record it. */
2766 if (start == IT_CHARPOS (*it)
2767 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2768 && XSTRING (str)->size)
2769 RECORD_OVERLAY_STRING (overlay, str, 0);
2770
2771 /* If overlay has a non-empty after-string, record it. */
2772 if (end == IT_CHARPOS (*it)
2773 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2774 && XSTRING (str)->size)
2775 RECORD_OVERLAY_STRING (overlay, str, 1);
2776 }
2777
2778#undef RECORD_OVERLAY_STRING
2779
2780 /* Sort entries. */
2781 qsort (entries, n, sizeof *entries, compare_overlay_entries);
2782
2783 /* Record the total number of strings to process. */
2784 it->n_overlay_strings = n;
2785
2786 /* IT->current.overlay_string_index is the number of overlay strings
2787 that have already been consumed by IT. Copy some of the
2788 remaining overlay strings to IT->overlay_strings. */
2789 i = 0;
2790 j = it->current.overlay_string_index;
2791 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
2792 it->overlay_strings[i++] = entries[j++].string;
2793
2794 CHECK_IT (it);
2795}
2796
2797
2798/* Get the first chunk of overlay strings at IT's current buffer
2799 position. Value is non-zero if at least one overlay string was
2800 found. */
2801
2802static int
2803get_overlay_strings (it)
2804 struct it *it;
2805{
2806 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
2807 process. This fills IT->overlay_strings with strings, and sets
2808 IT->n_overlay_strings to the total number of strings to process.
2809 IT->pos.overlay_string_index has to be set temporarily to zero
2810 because load_overlay_strings needs this; it must be set to -1
2811 when no overlay strings are found because a zero value would
2812 indicate a position in the first overlay string. */
2813 it->current.overlay_string_index = 0;
2814 load_overlay_strings (it);
2815
2816 /* If we found overlay strings, set up IT to deliver display
2817 elements from the first one. Otherwise set up IT to deliver
2818 from current_buffer. */
2819 if (it->n_overlay_strings)
2820 {
2821 /* Make sure we know settings in current_buffer, so that we can
2822 restore meaningful values when we're done with the overlay
2823 strings. */
2824 compute_stop_pos (it);
2825 xassert (it->face_id >= 0);
2826
2827 /* Save IT's settings. They are restored after all overlay
2828 strings have been processed. */
2829 xassert (it->sp == 0);
2830 push_it (it);
2831
2832 /* Set up IT to deliver display elements from the first overlay
2833 string. */
2834 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2835 it->stop_charpos = 0;
2836 it->string = it->overlay_strings[0];
2837 it->multibyte_p = STRING_MULTIBYTE (it->string);
2838 xassert (STRINGP (it->string));
2839 it->method = next_element_from_string;
2840 }
2841 else
2842 {
2843 it->string = Qnil;
2844 it->current.overlay_string_index = -1;
2845 it->method = next_element_from_buffer;
2846 }
2847
2848 CHECK_IT (it);
2849
2850 /* Value is non-zero if we found at least one overlay string. */
2851 return STRINGP (it->string);
2852}
2853
2854
2855\f
2856/***********************************************************************
2857 Saving and restoring state
2858 ***********************************************************************/
2859
2860/* Save current settings of IT on IT->stack. Called, for example,
2861 before setting up IT for an overlay string, to be able to restore
2862 IT's settings to what they were after the overlay string has been
2863 processed. */
2864
2865static void
2866push_it (it)
2867 struct it *it;
2868{
2869 struct iterator_stack_entry *p;
2870
2871 xassert (it->sp < 2);
2872 p = it->stack + it->sp;
2873
2874 p->stop_charpos = it->stop_charpos;
2875 xassert (it->face_id >= 0);
2876 p->face_id = it->face_id;
2877 p->string = it->string;
2878 p->pos = it->current;
2879 p->end_charpos = it->end_charpos;
2880 p->string_nchars = it->string_nchars;
2881 p->area = it->area;
2882 p->multibyte_p = it->multibyte_p;
2883 p->space_width = it->space_width;
2884 p->font_height = it->font_height;
2885 p->voffset = it->voffset;
2886 p->string_from_display_prop_p = it->string_from_display_prop_p;
2887 ++it->sp;
2888}
2889
2890
2891/* Restore IT's settings from IT->stack. Called, for example, when no
2892 more overlay strings must be processed, and we return to delivering
2893 display elements from a buffer, or when the end of a string from a
2894 `display' property is reached and we return to delivering display
2895 elements from an overlay string, or from a buffer. */
2896
2897static void
2898pop_it (it)
2899 struct it *it;
2900{
2901 struct iterator_stack_entry *p;
2902
2903 xassert (it->sp > 0);
2904 --it->sp;
2905 p = it->stack + it->sp;
2906 it->stop_charpos = p->stop_charpos;
2907 it->face_id = p->face_id;
2908 it->string = p->string;
2909 it->current = p->pos;
2910 it->end_charpos = p->end_charpos;
2911 it->string_nchars = p->string_nchars;
2912 it->area = p->area;
2913 it->multibyte_p = p->multibyte_p;
2914 it->space_width = p->space_width;
2915 it->font_height = p->font_height;
2916 it->voffset = p->voffset;
2917 it->string_from_display_prop_p = p->string_from_display_prop_p;
2918}
2919
2920
2921\f
2922/***********************************************************************
2923 Moving over lines
2924 ***********************************************************************/
2925
2926/* Set IT's current position to the previous line start. */
2927
2928static void
2929back_to_previous_line_start (it)
2930 struct it *it;
2931{
2932 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
2933 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
2934}
2935
2936
2937/* Set IT's current position to the next line start. */
2938
2939static void
2940forward_to_next_line_start (it)
2941 struct it *it;
2942{
2943 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it), 1);
2944 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
2945}
2946
2947
2948/* Set IT's current position to the previous visible line start. Skip
2949 invisible text that is so either due to text properties or due to
2950 selective display. Caution: this does not change IT->current_x and
2951 IT->hpos. */
2952
2953static void
2954back_to_previous_visible_line_start (it)
2955 struct it *it;
2956{
2957 int visible_p = 0;
2958
2959 /* Go back one newline if not on BEGV already. */
2960 if (IT_CHARPOS (*it) > BEGV)
2961 back_to_previous_line_start (it);
2962
2963 /* Move over lines that are invisible because of selective display
2964 or text properties. */
2965 while (IT_CHARPOS (*it) > BEGV
2966 && !visible_p)
2967 {
2968 visible_p = 1;
2969
2970 /* If selective > 0, then lines indented more than that values
2971 are invisible. */
2972 if (it->selective > 0
2973 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
2974 it->selective))
2975 visible_p = 0;
2976#ifdef USE_TEXT_PROPERTIES
2977 else
2978 {
2979 Lisp_Object prop;
2980
2981 prop = Fget_char_property (IT_CHARPOS (*it), Qinvisible, it->window);
2982 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2983 visible_p = 0;
2984 }
2985#endif /* USE_TEXT_PROPERTIES */
2986
2987 /* Back one more newline if the current one is invisible. */
2988 if (!visible_p)
2989 back_to_previous_line_start (it);
2990 }
2991
2992 xassert (IT_CHARPOS (*it) >= BEGV);
2993 xassert (IT_CHARPOS (*it) == BEGV
2994 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
2995 CHECK_IT (it);
2996}
2997
2998
2999/* Reseat iterator IT at the previous visible line start. Skip
3000 invisible text that is so either due to text properties or due to
3001 selective display. At the end, update IT's overlay information,
3002 face information etc. */
3003
3004static void
3005reseat_at_previous_visible_line_start (it)
3006 struct it *it;
3007{
3008 back_to_previous_visible_line_start (it);
3009 reseat (it, it->current.pos, 1);
3010 CHECK_IT (it);
3011}
3012
3013
3014/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
3015 buffer. ON_NEWLINE_P non-zero means position IT on the newline
3016 preceding the line start. Skip over invisible text that is so
3017 because of selective display. Compute faces, overlays etc at the
3018 new position. Note that this function does not skip over text that
3019 is invisible because of text properties. */
5f5c8ee5
GM
3020
3021static void
312246d1 3022reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 3023 struct it *it;
312246d1 3024 int on_newline_p;
5f5c8ee5
GM
3025{
3026 /* Restore the buffer position when currently not delivering display
3027 elements from the current buffer. This is the case, for example,
3028 when called at the end of a truncated overlay string. */
3029 while (it->sp)
3030 pop_it (it);
3031 it->method = next_element_from_buffer;
3032
3033 /* Otherwise, scan_buffer would not work. */
3034 if (IT_CHARPOS (*it) < ZV)
3035 {
3036 /* If on a newline, advance past it. Otherwise, find the next
3037 newline which automatically gives us the position following
3038 the newline. */
3039 if (FETCH_BYTE (IT_BYTEPOS (*it)) == '\n')
3040 {
3041 ++IT_CHARPOS (*it);
3042 ++IT_BYTEPOS (*it);
3043 }
3044 else
3045 forward_to_next_line_start (it);
3046
3047 /* We must either have reached the end of the buffer or end up
3048 after a newline. */
3049 xassert (IT_CHARPOS (*it) == ZV
3050 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3051
3052 /* Skip over lines that are invisible because they are indented
3053 more than the value of IT->selective. */
3054 if (it->selective > 0)
3055 while (IT_CHARPOS (*it) < ZV
3056 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3057 it->selective))
3058 forward_to_next_line_start (it);
312246d1
GM
3059
3060 /* Position on the newline if we should. */
3061 if (on_newline_p && IT_CHARPOS (*it) > BEGV)
3062 {
3063 --IT_CHARPOS (*it);
3064 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3065 }
5f5c8ee5
GM
3066
3067 /* Set the iterator there. The 0 as the last parameter of
3068 reseat means don't force a text property lookup. The lookup
3069 is then only done if we've skipped past the iterator's
3070 check_charpos'es. This optimization is important because
3071 text property lookups tend to be expensive. */
3072 reseat (it, it->current.pos, 0);
3073 }
3074
3075 CHECK_IT (it);
3076}
3077
3078
3079\f
3080/***********************************************************************
3081 Changing an iterator's position
3082***********************************************************************/
3083
3084/* Change IT's current position to POS in current_buffer. If FORCE_P
3085 is non-zero, always check for text properties at the new position.
3086 Otherwise, text properties are only looked up if POS >=
3087 IT->check_charpos of a property. */
3088
3089static void
3090reseat (it, pos, force_p)
3091 struct it *it;
3092 struct text_pos pos;
3093 int force_p;
3094{
3095 int original_pos = IT_CHARPOS (*it);
3096
3097 reseat_1 (it, pos, 0);
3098
3099 /* Determine where to check text properties. Avoid doing it
3100 where possible because text property lookup is very expensive. */
3101 if (force_p
3102 || CHARPOS (pos) > it->stop_charpos
3103 || CHARPOS (pos) < original_pos)
3104 handle_stop (it);
3105
3106 CHECK_IT (it);
3107}
3108
3109
3110/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
3111 IT->stop_pos to POS, also. */
3112
3113static void
3114reseat_1 (it, pos, set_stop_p)
3115 struct it *it;
3116 struct text_pos pos;
3117 int set_stop_p;
3118{
3119 /* Don't call this function when scanning a C string. */
3120 xassert (it->s == NULL);
3121
3122 /* POS must be a reasonable value. */
3123 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
3124
3125 it->current.pos = it->position = pos;
3126 XSETBUFFER (it->object, current_buffer);
3127 it->dpvec = NULL;
3128 it->current.dpvec_index = -1;
3129 it->current.overlay_string_index = -1;
3130 IT_STRING_CHARPOS (*it) = -1;
3131 IT_STRING_BYTEPOS (*it) = -1;
3132 it->string = Qnil;
3133 it->method = next_element_from_buffer;
3134 it->sp = 0;
3135
3136 if (set_stop_p)
3137 it->stop_charpos = CHARPOS (pos);
3138}
3139
3140
3141/* Set up IT for displaying a string, starting at CHARPOS in window W.
3142 If S is non-null, it is a C string to iterate over. Otherwise,
3143 STRING gives a Lisp string to iterate over.
3144
3145 If PRECISION > 0, don't return more then PRECISION number of
3146 characters from the string.
3147
3148 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
3149 characters have been returned. FIELD_WIDTH < 0 means an infinite
3150 field width.
3151
3152 MULTIBYTE = 0 means disable processing of multibyte characters,
3153 MULTIBYTE > 0 means enable it,
3154 MULTIBYTE < 0 means use IT->multibyte_p.
3155
3156 IT must be initialized via a prior call to init_iterator before
3157 calling this function. */
3158
3159static void
3160reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
3161 struct it *it;
3162 unsigned char *s;
3163 Lisp_Object string;
3164 int charpos;
3165 int precision, field_width, multibyte;
3166{
3167 /* No region in strings. */
3168 it->region_beg_charpos = it->region_end_charpos = -1;
3169
3170 /* No text property checks performed by default, but see below. */
3171 it->stop_charpos = -1;
3172
3173 /* Set iterator position and end position. */
3174 bzero (&it->current, sizeof it->current);
3175 it->current.overlay_string_index = -1;
3176 it->current.dpvec_index = -1;
3177 it->charset = CHARSET_ASCII;
3178 xassert (charpos >= 0);
3179
3180 /* Use the setting of MULTIBYTE if specified. */
3181 if (multibyte >= 0)
3182 it->multibyte_p = multibyte > 0;
3183
3184 if (s == NULL)
3185 {
3186 xassert (STRINGP (string));
3187 it->string = string;
3188 it->s = NULL;
3189 it->end_charpos = it->string_nchars = XSTRING (string)->size;
3190 it->method = next_element_from_string;
3191 it->current.string_pos = string_pos (charpos, string);
3192 }
3193 else
3194 {
3195 it->s = s;
3196 it->string = Qnil;
3197
3198 /* Note that we use IT->current.pos, not it->current.string_pos,
3199 for displaying C strings. */
3200 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3201 if (it->multibyte_p)
3202 {
3203 it->current.pos = c_string_pos (charpos, s, 1);
3204 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
3205 }
3206 else
3207 {
3208 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
3209 it->end_charpos = it->string_nchars = strlen (s);
3210 }
3211
3212 it->method = next_element_from_c_string;
3213 }
3214
3215 /* PRECISION > 0 means don't return more than PRECISION characters
3216 from the string. */
3217 if (precision > 0 && it->end_charpos - charpos > precision)
3218 it->end_charpos = it->string_nchars = charpos + precision;
3219
3220 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
3221 characters have been returned. FIELD_WIDTH == 0 means don't pad,
3222 FIELD_WIDTH < 0 means infinite field width. This is useful for
3223 padding with `-' at the end of a mode line. */
3224 if (field_width < 0)
3225 field_width = INFINITY;
3226 if (field_width > it->end_charpos - charpos)
3227 it->end_charpos = charpos + field_width;
3228
3229 /* Use the standard display table for displaying strings. */
3230 if (DISP_TABLE_P (Vstandard_display_table))
3231 it->dp = XCHAR_TABLE (Vstandard_display_table);
3232
3233 it->stop_charpos = charpos;
3234 CHECK_IT (it);
3235}
3236
3237
3238\f
3239/***********************************************************************
3240 Iteration
3241 ***********************************************************************/
3242
3243/* Load IT's display element fields with information about the next
3244 display element from the current position of IT. Value is zero if
3245 end of buffer (or C string) is reached. */
3246
3247int
3248get_next_display_element (it)
3249 struct it *it;
3250{
3251 /* Non-zero means that we found an display element. Zero means that
3252 we hit the end of what we iterate over. Performance note: the
3253 function pointer `method' used here turns out to be faster than
3254 using a sequence of if-statements. */
3255 int success_p = (*it->method) (it);
3256 int charset;
3257
3258 if (it->what == IT_CHARACTER)
3259 {
3260 /* Map via display table or translate control characters.
3261 IT->c, IT->len etc. have been set to the next character by
3262 the function call above. If we have a display table, and it
3263 contains an entry for IT->c, translate it. Don't do this if
3264 IT->c itself comes from a display table, otherwise we could
3265 end up in an infinite recursion. (An alternative could be to
3266 count the recursion depth of this function and signal an
3267 error when a certain maximum depth is reached.) Is it worth
3268 it? */
3269 if (success_p && it->dpvec == NULL)
3270 {
3271 Lisp_Object dv;
3272
3273 if (it->dp
3274 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
3275 VECTORP (dv)))
3276 {
3277 struct Lisp_Vector *v = XVECTOR (dv);
3278
3279 /* Return the first character from the display table
3280 entry, if not empty. If empty, don't display the
3281 current character. */
3282 if (v->size)
3283 {
3284 it->dpvec_char_len = it->len;
3285 it->dpvec = v->contents;
3286 it->dpend = v->contents + v->size;
3287 it->current.dpvec_index = 0;
3288 it->method = next_element_from_display_vector;
3289 }
3290
3291 success_p = get_next_display_element (it);
3292 }
3293
3294 /* Translate control characters into `\003' or `^C' form.
3295 Control characters coming from a display table entry are
3296 currently not translated because we use IT->dpvec to hold
3297 the translation. This could easily be changed but I
197516c2
KH
3298 don't believe that it is worth doing.
3299
3300 Non-printable multibyte characters are also translated
3301 octal form. */
5f5c8ee5
GM
3302 else if ((it->c < ' '
3303 && (it->area != TEXT_AREA
c6e89d6c 3304 || (it->c != '\n' && it->c != '\t')))
54c85a23 3305 || (it->c >= 127
197516c2
KH
3306 && it->len == 1)
3307 || !CHAR_PRINTABLE_P (it->c))
5f5c8ee5
GM
3308 {
3309 /* IT->c is a control character which must be displayed
3310 either as '\003' or as `^C' where the '\\' and '^'
3311 can be defined in the display table. Fill
3312 IT->ctl_chars with glyphs for what we have to
3313 display. Then, set IT->dpvec to these glyphs. */
3314 GLYPH g;
3315
54c85a23 3316 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
3317 {
3318 /* Set IT->ctl_chars[0] to the glyph for `^'. */
3319 if (it->dp
3320 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
3321 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
3322 g = XINT (DISP_CTRL_GLYPH (it->dp));
3323 else
3324 g = FAST_MAKE_GLYPH ('^', 0);
3325 XSETINT (it->ctl_chars[0], g);
3326
3327 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
3328 XSETINT (it->ctl_chars[1], g);
3329
3330 /* Set up IT->dpvec and return first character from it. */
3331 it->dpvec_char_len = it->len;
3332 it->dpvec = it->ctl_chars;
3333 it->dpend = it->dpvec + 2;
3334 it->current.dpvec_index = 0;
3335 it->method = next_element_from_display_vector;
3336 get_next_display_element (it);
3337 }
3338 else
3339 {
197516c2
KH
3340 unsigned char work[4], *str;
3341 int len = CHAR_STRING (it->c, work, str);
3342 int i;
3343 GLYPH escape_glyph;
3344
5f5c8ee5
GM
3345 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
3346 if (it->dp
3347 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
3348 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 3349 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 3350 else
197516c2
KH
3351 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
3352
3353 for (i = 0; i < len; i++)
3354 {
3355 XSETINT (it->ctl_chars[i * 4], escape_glyph);
3356 /* Insert three more glyphs into IT->ctl_chars for
3357 the octal display of the character. */
3358 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
3359 XSETINT (it->ctl_chars[i * 4 + 1], g);
3360 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
3361 XSETINT (it->ctl_chars[i * 4 + 2], g);
3362 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
3363 XSETINT (it->ctl_chars[i * 4 + 3], g);
3364 }
5f5c8ee5
GM
3365
3366 /* Set up IT->dpvec and return the first character
3367 from it. */
3368 it->dpvec_char_len = it->len;
3369 it->dpvec = it->ctl_chars;
197516c2 3370 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
3371 it->current.dpvec_index = 0;
3372 it->method = next_element_from_display_vector;
3373 get_next_display_element (it);
3374 }
3375 }
3376 }
3377
3378 /* Adjust face id if charset changes. There are no charset
3379 changes in unibyte text because Emacs' charsets are not
3380 applicable there. */
3381 if (it->multibyte_p
3382 && success_p
3383 && (charset = CHAR_CHARSET (it->c),
3384 charset != it->charset))
3385 {
3386 it->charset = charset;
3387 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, charset);
3388 }
3389 }
3390
3391 /* Is this character the last one of a run of characters with
3392 box? If yes, set IT->end_of_box_run_p to 1. */
3393 if (it->face_box_p
3394 && it->s == NULL)
3395 {
3396 int face_id;
3397 struct face *face;
3398
3399 it->end_of_box_run_p
3400 = ((face_id = face_after_it_pos (it),
3401 face_id != it->face_id)
3402 && (face = FACE_FROM_ID (it->f, face_id),
3403 face->box == FACE_NO_BOX));
3404 }
3405
3406 /* Value is 0 if end of buffer or string reached. */
3407 return success_p;
3408}
3409
3410
3411/* Move IT to the next display element.
3412
3413 Functions get_next_display_element and set_iterator_to_next are
3414 separate because I find this arrangement easier to handle than a
3415 get_next_display_element function that also increments IT's
3416 position. The way it is we can first look at an iterator's current
3417 display element, decide whether it fits on a line, and if it does,
3418 increment the iterator position. The other way around we probably
3419 would either need a flag indicating whether the iterator has to be
3420 incremented the next time, or we would have to implement a
3421 decrement position function which would not be easy to write. */
3422
3423void
3424set_iterator_to_next (it)
3425 struct it *it;
3426{
3427 if (it->method == next_element_from_buffer)
3428 {
3429 /* The current display element of IT is a character from
3430 current_buffer. Advance in the buffer, and maybe skip over
3431 invisible lines that are so because of selective display. */
3432 if (ITERATOR_AT_END_OF_LINE_P (it))
312246d1 3433 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
3434 else
3435 {
3436 xassert (it->len != 0);
3437 IT_BYTEPOS (*it) += it->len;
3438 IT_CHARPOS (*it) += 1;
3439 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
3440 }
3441 }
3442 else if (it->method == next_element_from_c_string)
3443 {
3444 /* Current display element of IT is from a C string. */
3445 IT_BYTEPOS (*it) += it->len;
3446 IT_CHARPOS (*it) += 1;
3447 }
3448 else if (it->method == next_element_from_display_vector)
3449 {
3450 /* Current display element of IT is from a display table entry.
3451 Advance in the display table definition. Reset it to null if
3452 end reached, and continue with characters from buffers/
3453 strings. */
3454 ++it->current.dpvec_index;
286bcbc9
GM
3455
3456 /* Restore face and charset of the iterator to what they were
3457 before the display vector entry (these entries may contain
3458 faces, and of course characters of different charsets). */
5f5c8ee5 3459 it->face_id = it->saved_face_id;
286bcbc9
GM
3460 it->charset = FACE_FROM_ID (it->f, it->face_id)->charset;
3461
5f5c8ee5
GM
3462 if (it->dpvec + it->current.dpvec_index == it->dpend)
3463 {
3464 if (it->s)
3465 it->method = next_element_from_c_string;
3466 else if (STRINGP (it->string))
3467 it->method = next_element_from_string;
3468 else
3469 it->method = next_element_from_buffer;
3470
3471 it->dpvec = NULL;
3472 it->current.dpvec_index = -1;
3473
312246d1
GM
3474 /* Skip over characters which were displayed via IT->dpvec. */
3475 if (it->dpvec_char_len < 0)
3476 reseat_at_next_visible_line_start (it, 1);
3477 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
3478 {
3479 it->len = it->dpvec_char_len;
3480 set_iterator_to_next (it);
3481 }
3482 }
3483 }
3484 else if (it->method == next_element_from_string)
3485 {
3486 /* Current display element is a character from a Lisp string. */
3487 xassert (it->s == NULL && STRINGP (it->string));
3488 IT_STRING_BYTEPOS (*it) += it->len;
3489 IT_STRING_CHARPOS (*it) += 1;
3490
3491 consider_string_end:
3492
3493 if (it->current.overlay_string_index >= 0)
3494 {
3495 /* IT->string is an overlay string. Advance to the
3496 next, if there is one. */
3497 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3498 next_overlay_string (it);
3499 }
3500 else
3501 {
3502 /* IT->string is not an overlay string. If we reached
3503 its end, and there is something on IT->stack, proceed
3504 with what is on the stack. This can be either another
3505 string, this time an overlay string, or a buffer. */
3506 if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size
3507 && it->sp > 0)
3508 {
3509 pop_it (it);
3510 if (!STRINGP (it->string))
3511 it->method = next_element_from_buffer;
3512 }
3513 }
3514 }
3515 else if (it->method == next_element_from_image
3516 || it->method == next_element_from_stretch)
3517 {
3518 /* The position etc with which we have to proceed are on
3519 the stack. The position may be at the end of a string,
3520 if the `display' property takes up the whole string. */
3521 pop_it (it);
3522 it->image_id = 0;
3523 if (STRINGP (it->string))
3524 {
3525 it->method = next_element_from_string;
3526 goto consider_string_end;
3527 }
3528 else
3529 it->method = next_element_from_buffer;
3530 }
3531 else
3532 /* There are no other methods defined, so this should be a bug. */
3533 abort ();
3534
3535 /* Reset flags indicating start and end of a sequence of
3536 characters with box. */
3537 it->start_of_box_run_p = it->end_of_box_run_p = 0;
3538
3539 xassert (it->method != next_element_from_string
3540 || (STRINGP (it->string)
3541 && IT_STRING_CHARPOS (*it) >= 0));
3542}
3543
3544
3545/* Load IT's display element fields with information about the next
3546 display element which comes from a display table entry or from the
3547 result of translating a control character to one of the forms `^C'
3548 or `\003'. IT->dpvec holds the glyphs to return as characters. */
3549
3550static int
3551next_element_from_display_vector (it)
3552 struct it *it;
3553{
3554 /* Precondition. */
3555 xassert (it->dpvec && it->current.dpvec_index >= 0);
3556
3557 /* Remember the current face id in case glyphs specify faces.
3558 IT's face is restored in set_iterator_to_next. */
3559 it->saved_face_id = it->face_id;
3560
3561 if (INTEGERP (*it->dpvec)
3562 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
3563 {
3564 int lface_id;
3565 GLYPH g;
3566
3567 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
3568 it->c = FAST_GLYPH_CHAR (g);
3569 it->len = CHAR_LEN (it->c);
3570
3571 /* The entry may contain a face id to use. Such a face id is
3572 the id of a Lisp face, not a realized face. A face id of
3573 zero means no face. */
3574 lface_id = FAST_GLYPH_FACE (g);
3575 if (lface_id)
3576 {
3577 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
3578 if (face_id >= 0)
3579 {
3580 it->face_id = face_id;
3581 it->charset = CHARSET_ASCII;
3582 }
3583 }
3584 }
3585 else
3586 /* Display table entry is invalid. Return a space. */
3587 it->c = ' ', it->len = 1;
3588
3589 /* Don't change position and object of the iterator here. They are
3590 still the values of the character that had this display table
3591 entry or was translated, and that's what we want. */
3592 it->what = IT_CHARACTER;
3593 return 1;
3594}
3595
3596
3597/* Load IT with the next display element from Lisp string IT->string.
3598 IT->current.string_pos is the current position within the string.
3599 If IT->current.overlay_string_index >= 0, the Lisp string is an
3600 overlay string. */
3601
3602static int
3603next_element_from_string (it)
3604 struct it *it;
3605{
3606 struct text_pos position;
3607
3608 xassert (STRINGP (it->string));
3609 xassert (IT_STRING_CHARPOS (*it) >= 0);
3610 position = it->current.string_pos;
3611
3612 /* Time to check for invisible text? */
3613 if (IT_STRING_CHARPOS (*it) < it->end_charpos
3614 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
3615 {
3616 handle_stop (it);
3617
3618 /* Since a handler may have changed IT->method, we must
3619 recurse here. */
3620 return get_next_display_element (it);
3621 }
3622
3623 if (it->current.overlay_string_index >= 0)
3624 {
3625 /* Get the next character from an overlay string. In overlay
3626 strings, There is no field width or padding with spaces to
3627 do. */
3628 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3629 {
3630 it->what = IT_EOB;
3631 return 0;
3632 }
3633 else if (STRING_MULTIBYTE (it->string))
3634 {
3635 int remaining = (STRING_BYTES (XSTRING (it->string))
3636 - IT_STRING_BYTEPOS (*it));
3637 unsigned char *s = (XSTRING (it->string)->data
3638 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3639 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
3640 }
3641 else
3642 {
3643 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3644 it->len = 1;
3645 }
3646 }
3647 else
3648 {
3649 /* Get the next character from a Lisp string that is not an
3650 overlay string. Such strings come from the mode line, for
3651 example. We may have to pad with spaces, or truncate the
3652 string. See also next_element_from_c_string. */
3653 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
3654 {
3655 it->what = IT_EOB;
3656 return 0;
3657 }
3658 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
3659 {
3660 /* Pad with spaces. */
3661 it->c = ' ', it->len = 1;
3662 CHARPOS (position) = BYTEPOS (position) = -1;
3663 }
3664 else if (STRING_MULTIBYTE (it->string))
3665 {
3666 int maxlen = (STRING_BYTES (XSTRING (it->string))
3667 - IT_STRING_BYTEPOS (*it));
3668 unsigned char *s = (XSTRING (it->string)->data
3669 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3670 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
3671 }
3672 else
3673 {
3674 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3675 it->len = 1;
3676 }
3677 }
3678
3679 /* Record what we have and where it came from. Note that we store a
3680 buffer position in IT->position although it could arguably be a
3681 string position. */
3682 it->what = IT_CHARACTER;
3683 it->object = it->string;
3684 it->position = position;
3685 return 1;
3686}
3687
3688
3689/* Load IT with next display element from C string IT->s.
3690 IT->string_nchars is the maximum number of characters to return
3691 from the string. IT->end_charpos may be greater than
3692 IT->string_nchars when this function is called, in which case we
3693 may have to return padding spaces. Value is zero if end of string
3694 reached, including padding spaces. */
3695
3696static int
3697next_element_from_c_string (it)
3698 struct it *it;
3699{
3700 int success_p = 1;
3701
3702 xassert (it->s);
3703 it->what = IT_CHARACTER;
3704 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
3705 it->object = Qnil;
3706
3707 /* IT's position can be greater IT->string_nchars in case a field
3708 width or precision has been specified when the iterator was
3709 initialized. */
3710 if (IT_CHARPOS (*it) >= it->end_charpos)
3711 {
3712 /* End of the game. */
3713 it->what = IT_EOB;
3714 success_p = 0;
3715 }
3716 else if (IT_CHARPOS (*it) >= it->string_nchars)
3717 {
3718 /* Pad with spaces. */
3719 it->c = ' ', it->len = 1;
3720 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
3721 }
3722 else if (it->multibyte_p)
3723 {
3724 /* Implementation note: The calls to strlen apparently aren't a
3725 performance problem because there is no noticeable performance
3726 difference between Emacs running in unibyte or multibyte mode. */
3727 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
3728 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
3729 maxlen, &it->len);
5f5c8ee5
GM
3730 }
3731 else
3732 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
3733
3734 return success_p;
3735}
3736
3737
3738/* Set up IT to return characters from an ellipsis, if appropriate.
3739 The definition of the ellipsis glyphs may come from a display table
3740 entry. This function Fills IT with the first glyph from the
3741 ellipsis if an ellipsis is to be displayed. */
3742
3743static void
3744next_element_from_ellipsis (it)
3745 struct it *it;
3746{
3747 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
3748 {
3749 /* Use the display table definition for `...'. Invalid glyphs
3750 will be handled by the method returning elements from dpvec. */
3751 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
3752 it->dpvec_char_len = it->len;
3753 it->dpvec = v->contents;
3754 it->dpend = v->contents + v->size;
3755 it->current.dpvec_index = 0;
3756 it->method = next_element_from_display_vector;
3757 get_next_display_element (it);
3758 }
3759 else if (it->selective_display_ellipsis_p)
3760 {
3761 /* Use default `...' which is stored in default_invis_vector. */
3762 it->dpvec_char_len = it->len;
3763 it->dpvec = default_invis_vector;
3764 it->dpend = default_invis_vector + 3;
3765 it->current.dpvec_index = 0;
3766 it->method = next_element_from_display_vector;
3767 get_next_display_element (it);
3768 }
3769}
3770
3771
3772/* Deliver an image display element. The iterator IT is already
3773 filled with image information (done in handle_display_prop). Value
3774 is always 1. */
3775
3776
3777static int
3778next_element_from_image (it)
3779 struct it *it;
3780{
3781 it->what = IT_IMAGE;
3782 return 1;
3783}
3784
3785
3786/* Fill iterator IT with next display element from a stretch glyph
3787 property. IT->object is the value of the text property. Value is
3788 always 1. */
3789
3790static int
3791next_element_from_stretch (it)
3792 struct it *it;
3793{
3794 it->what = IT_STRETCH;
3795 return 1;
3796}
3797
3798
3799/* Load IT with the next display element from current_buffer. Value
3800 is zero if end of buffer reached. IT->stop_charpos is the next
3801 position at which to stop and check for text properties or buffer
3802 end. */
3803
3804static int
3805next_element_from_buffer (it)
3806 struct it *it;
3807{
3808 int success_p = 1;
3809
3810 /* Check this assumption, otherwise, we would never enter the
3811 if-statement, below. */
3812 xassert (IT_CHARPOS (*it) >= BEGV
3813 && IT_CHARPOS (*it) <= it->stop_charpos);
3814
3815 if (IT_CHARPOS (*it) >= it->stop_charpos)
3816 {
3817 if (IT_CHARPOS (*it) >= it->end_charpos)
3818 {
3819 int overlay_strings_follow_p;
3820
3821 /* End of the game, except when overlay strings follow that
3822 haven't been returned yet. */
3823 if (it->overlay_strings_at_end_processed_p)
3824 overlay_strings_follow_p = 0;
3825 else
3826 {
3827 it->overlay_strings_at_end_processed_p = 1;
3828 overlay_strings_follow_p
3829 = get_overlay_strings (it);
3830 }
3831
3832 if (overlay_strings_follow_p)
3833 success_p = get_next_display_element (it);
3834 else
3835 {
3836 it->what = IT_EOB;
3837 it->position = it->current.pos;
3838 success_p = 0;
3839 }
3840 }
3841 else
3842 {
3843 handle_stop (it);
3844 return get_next_display_element (it);
3845 }
3846 }
3847 else
3848 {
3849 /* No face changes, overlays etc. in sight, so just return a
3850 character from current_buffer. */
3851 unsigned char *p;
3852
3853 /* Maybe run the redisplay end trigger hook. Performance note:
3854 This doesn't seem to cost measurable time. */
3855 if (it->redisplay_end_trigger_charpos
3856 && it->glyph_row
3857 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
3858 run_redisplay_end_trigger_hook (it);
3859
3860 /* Get the next character, maybe multibyte. */
3861 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
3862 if (it->multibyte_p)
3863 {
3864 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
3865 - IT_BYTEPOS (*it));
4fdb80f2 3866 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
3867 }
3868 else
3869 it->c = *p, it->len = 1;
3870
3871 /* Record what we have and where it came from. */
3872 it->what = IT_CHARACTER;;
3873 it->object = it->w->buffer;
3874 it->position = it->current.pos;
3875
3876 /* Normally we return the character found above, except when we
3877 really want to return an ellipsis for selective display. */
3878 if (it->selective)
3879 {
3880 if (it->c == '\n')
3881 {
3882 /* A value of selective > 0 means hide lines indented more
3883 than that number of columns. */
3884 if (it->selective > 0
3885 && IT_CHARPOS (*it) + 1 < ZV
3886 && indented_beyond_p (IT_CHARPOS (*it) + 1,
3887 IT_BYTEPOS (*it) + 1,
3888 it->selective))
312246d1
GM
3889 {
3890 next_element_from_ellipsis (it);
3891 it->dpvec_char_len = -1;
3892 }
5f5c8ee5
GM
3893 }
3894 else if (it->c == '\r' && it->selective == -1)
3895 {
3896 /* A value of selective == -1 means that everything from the
3897 CR to the end of the line is invisible, with maybe an
3898 ellipsis displayed for it. */
3899 next_element_from_ellipsis (it);
312246d1 3900 it->dpvec_char_len = -1;
5f5c8ee5
GM
3901 }
3902 }
3903 }
3904
3905 /* Value is zero if end of buffer reached. */
3906 xassert (!success_p || it->len > 0);
3907 return success_p;
3908}
3909
3910
3911/* Run the redisplay end trigger hook for IT. */
3912
3913static void
3914run_redisplay_end_trigger_hook (it)
3915 struct it *it;
3916{
3917 Lisp_Object args[3];
3918
3919 /* IT->glyph_row should be non-null, i.e. we should be actually
3920 displaying something, or otherwise we should not run the hook. */
3921 xassert (it->glyph_row);
3922
3923 /* Set up hook arguments. */
3924 args[0] = Qredisplay_end_trigger_functions;
3925 args[1] = it->window;
3926 XSETINT (args[2], it->redisplay_end_trigger_charpos);
3927 it->redisplay_end_trigger_charpos = 0;
3928
3929 /* Since we are *trying* to run these functions, don't try to run
3930 them again, even if they get an error. */
3931 it->w->redisplay_end_trigger = Qnil;
3932 Frun_hook_with_args (3, args);
3933
3934 /* Notice if it changed the face of the character we are on. */
3935 handle_face_prop (it);
3936}
3937
3938
3939\f
3940/***********************************************************************
3941 Moving an iterator without producing glyphs
3942 ***********************************************************************/
3943
3944/* Move iterator IT to a specified buffer or X position within one
3945 line on the display without producing glyphs.
3946
3947 Begin to skip at IT's current position. Skip to TO_CHARPOS or TO_X
3948 whichever is reached first.
3949
3950 TO_CHARPOS <= 0 means no TO_CHARPOS is specified.
3951
3952 TO_X < 0 means that no TO_X is specified. TO_X is normally a value
3953 0 <= TO_X <= IT->last_visible_x. This means in particular, that
3954 TO_X includes the amount by which a window is horizontally
3955 scrolled.
3956
3957 Value is
3958
3959 MOVE_POS_MATCH_OR_ZV
3960 - when TO_POS or ZV was reached.
3961
3962 MOVE_X_REACHED
3963 -when TO_X was reached before TO_POS or ZV were reached.
3964
3965 MOVE_LINE_CONTINUED
3966 - when we reached the end of the display area and the line must
3967 be continued.
3968
3969 MOVE_LINE_TRUNCATED
3970 - when we reached the end of the display area and the line is
3971 truncated.
3972
3973 MOVE_NEWLINE_OR_CR
3974 - when we stopped at a line end, i.e. a newline or a CR and selective
3975 display is on. */
3976
701552dd 3977static enum move_it_result
5f5c8ee5
GM
3978move_it_in_display_line_to (it, to_charpos, to_x, op)
3979 struct it *it;
3980 int to_charpos, to_x, op;
3981{
3982 enum move_it_result result = MOVE_UNDEFINED;
3983 struct glyph_row *saved_glyph_row;
3984
3985 /* Don't produce glyphs in produce_glyphs. */
3986 saved_glyph_row = it->glyph_row;
3987 it->glyph_row = NULL;
3988
5f5c8ee5
GM
3989 while (1)
3990 {
3991 int x, i;
3992
3993 /* Stop when ZV or TO_CHARPOS reached. */
3994 if (!get_next_display_element (it)
3995 || ((op & MOVE_TO_POS) != 0
3996 && BUFFERP (it->object)
3997 && IT_CHARPOS (*it) >= to_charpos))
3998 {
3999 result = MOVE_POS_MATCH_OR_ZV;
4000 break;
4001 }
4002
4003 /* The call to produce_glyphs will get the metrics of the
4004 display element IT is loaded with. We record in x the
4005 x-position before this display element in case it does not
4006 fit on the line. */
4007 x = it->current_x;
4008 PRODUCE_GLYPHS (it);
4009
4010 if (it->area != TEXT_AREA)
4011 {
4012 set_iterator_to_next (it);
4013 continue;
4014 }
4015
4016 /* The number of glyphs we get back in IT->nglyphs will normally
4017 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
4018 character on a terminal frame, or (iii) a line end. For the
4019 second case, IT->nglyphs - 1 padding glyphs will be present
4020 (on X frames, there is only one glyph produced for a
4021 composite character.
4022
4023 The behavior implemented below means, for continuation lines,
4024 that as many spaces of a TAB as fit on the current line are
4025 displayed there. For terminal frames, as many glyphs of a
4026 multi-glyph character are displayed in the current line, too.
4027 This is what the old redisplay code did, and we keep it that
4028 way. Under X, the whole shape of a complex character must
4029 fit on the line or it will be completely displayed in the
4030 next line.
4031
4032 Note that both for tabs and padding glyphs, all glyphs have
4033 the same width. */
4034 if (it->nglyphs)
4035 {
4036 /* More than one glyph or glyph doesn't fit on line. All
4037 glyphs have the same width. */
4038 int single_glyph_width = it->pixel_width / it->nglyphs;
4039 int new_x;
4040
4041 for (i = 0; i < it->nglyphs; ++i, x = new_x)
4042 {
4043 new_x = x + single_glyph_width;
4044
4045 /* We want to leave anything reaching TO_X to the caller. */
4046 if ((op & MOVE_TO_X) && new_x > to_x)
4047 {
4048 it->current_x = x;
4049 result = MOVE_X_REACHED;
4050 break;
4051 }
4052 else if (/* Lines are continued. */
4053 !it->truncate_lines_p
4054 && (/* And glyph doesn't fit on the line. */
4055 new_x > it->last_visible_x
4056 /* Or it fits exactly and we're on a window
4057 system frame. */
4058 || (new_x == it->last_visible_x
4059 && FRAME_WINDOW_P (it->f))))
4060 {
4061 if (/* IT->hpos == 0 means the very first glyph
4062 doesn't fit on the line, e.g. a wide image. */
4063 it->hpos == 0
4064 || (new_x == it->last_visible_x
4065 && FRAME_WINDOW_P (it->f)))
4066 {
4067 ++it->hpos;
4068 it->current_x = new_x;
4069 if (i == it->nglyphs - 1)
4070 set_iterator_to_next (it);
4071 }
4072 else
4073 it->current_x = x;
4074
4075 result = MOVE_LINE_CONTINUED;
4076 break;
4077 }
4078 else if (new_x > it->first_visible_x)
4079 {
4080 /* Glyph is visible. Increment number of glyphs that
4081 would be displayed. */
4082 ++it->hpos;
4083 }
4084 else
4085 {
4086 /* Glyph is completely off the left margin of the display
4087 area. Nothing to do. */
4088 }
4089 }
4090
4091 if (result != MOVE_UNDEFINED)
4092 break;
4093 }
4094 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
4095 {
4096 /* Stop when TO_X specified and reached. This check is
4097 necessary here because of lines consisting of a line end,
4098 only. The line end will not produce any glyphs and we
4099 would never get MOVE_X_REACHED. */
4100 xassert (it->nglyphs == 0);
4101 result = MOVE_X_REACHED;
4102 break;
4103 }
4104
4105 /* Is this a line end? If yes, we're done. */
4106 if (ITERATOR_AT_END_OF_LINE_P (it))
4107 {
4108 result = MOVE_NEWLINE_OR_CR;
4109 break;
4110 }
4111
4112 /* The current display element has been consumed. Advance
4113 to the next. */
4114 set_iterator_to_next (it);
4115
4116 /* Stop if lines are truncated and IT's current x-position is
4117 past the right edge of the window now. */
4118 if (it->truncate_lines_p
4119 && it->current_x >= it->last_visible_x)
4120 {
4121 result = MOVE_LINE_TRUNCATED;
4122 break;
4123 }
4124 }
4125
4126 /* Restore the iterator settings altered at the beginning of this
4127 function. */
4128 it->glyph_row = saved_glyph_row;
4129 return result;
4130}
4131
4132
4133/* Move IT forward to a specified buffer position TO_CHARPOS, TO_X,
4134 TO_Y, TO_VPOS. OP is a bit-mask that specifies where to stop. See
4135 the description of enum move_operation_enum.
4136
4137 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
4138 screen line, this function will set IT to the next position >
4139 TO_CHARPOS. */
4140
4141void
4142move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
4143 struct it *it;
4144 int to_charpos, to_x, to_y, to_vpos;
4145 int op;
4146{
4147 enum move_it_result skip, skip2 = MOVE_X_REACHED;
4148 int line_height;
4149
5f5c8ee5
GM
4150 while (1)
4151 {
4152 if (op & MOVE_TO_VPOS)
4153 {
4154 /* If no TO_CHARPOS and no TO_X specified, stop at the
4155 start of the line TO_VPOS. */
4156 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
4157 {
4158 if (it->vpos == to_vpos)
4159 break;
4160 skip = move_it_in_display_line_to (it, -1, -1, 0);
4161 }
4162 else
4163 {
4164 /* TO_VPOS >= 0 means stop at TO_X in the line at
4165 TO_VPOS, or at TO_POS, whichever comes first. */
4166 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
4167
4168 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
4169 break;
4170 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
4171 {
4172 /* We have reached TO_X but not in the line we want. */
4173 skip = move_it_in_display_line_to (it, to_charpos,
4174 -1, MOVE_TO_POS);
4175 if (skip == MOVE_POS_MATCH_OR_ZV)
4176 break;
4177 }
4178 }
4179 }
4180 else if (op & MOVE_TO_Y)
4181 {
4182 struct it it_backup;
4183 int done_p;
4184
4185 /* TO_Y specified means stop at TO_X in the line containing
4186 TO_Y---or at TO_CHARPOS if this is reached first. The
4187 problem is that we can't really tell whether the line
4188 contains TO_Y before we have completely scanned it, and
4189 this may skip past TO_X. What we do is to first scan to
4190 TO_X.
4191
4192 If TO_X is not specified, use a TO_X of zero. The reason
4193 is to make the outcome of this function more predictable.
4194 If we didn't use TO_X == 0, we would stop at the end of
4195 the line which is probably not what a caller would expect
4196 to happen. */
4197 skip = move_it_in_display_line_to (it, to_charpos,
4198 ((op & MOVE_TO_X)
4199 ? to_x : 0),
4200 (MOVE_TO_X
4201 | (op & MOVE_TO_POS)));
4202
4203 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
4204 if (skip == MOVE_POS_MATCH_OR_ZV)
4205 break;
4206
4207 /* If TO_X was reached, we would like to know whether TO_Y
4208 is in the line. This can only be said if we know the
4209 total line height which requires us to scan the rest of
4210 the line. */
4211 done_p = 0;
4212 if (skip == MOVE_X_REACHED)
4213 {
4214 it_backup = *it;
4215 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
4216 op & MOVE_TO_POS);
4217 }
4218
4219 /* Now, decide whether TO_Y is in this line. */
4220 line_height = it->max_ascent + it->max_descent;
4221
4222 if (to_y >= it->current_y
4223 && to_y < it->current_y + line_height)
4224 {
4225 if (skip == MOVE_X_REACHED)
4226 /* If TO_Y is in this line and TO_X was reached above,
4227 we scanned too far. We have to restore IT's settings
4228 to the ones before skipping. */
4229 *it = it_backup;
4230 done_p = 1;
4231 }
4232 else if (skip == MOVE_X_REACHED)
4233 {
4234 skip = skip2;
4235 if (skip == MOVE_POS_MATCH_OR_ZV)
4236 done_p = 1;
4237 }
4238
4239 if (done_p)
4240 break;
4241 }
4242 else
4243 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
4244
4245 switch (skip)
4246 {
4247 case MOVE_POS_MATCH_OR_ZV:
4248 return;
4249
4250 case MOVE_NEWLINE_OR_CR:
4251 set_iterator_to_next (it);
4252 it->continuation_lines_width = 0;
4253 break;
4254
4255 case MOVE_LINE_TRUNCATED:
4256 it->continuation_lines_width = 0;
312246d1 4257 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4258 if ((op & MOVE_TO_POS) != 0
4259 && IT_CHARPOS (*it) > to_charpos)
4260 goto out;
4261 break;
4262
4263 case MOVE_LINE_CONTINUED:
4264 it->continuation_lines_width += it->current_x;
4265 break;
4266
4267 default:
4268 abort ();
4269 }
4270
4271 /* Reset/increment for the next run. */
4272 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
4273 it->current_x = it->hpos = 0;
4274 it->current_y += it->max_ascent + it->max_descent;
4275 ++it->vpos;
4276 last_height = it->max_ascent + it->max_descent;
4277 last_max_ascent = it->max_ascent;
4278 it->max_ascent = it->max_descent = 0;
4279 }
4280 out:;
4281}
4282
4283
4284/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
4285
4286 If DY > 0, move IT backward at least that many pixels. DY = 0
4287 means move IT backward to the preceding line start or BEGV. This
4288 function may move over more than DY pixels if IT->current_y - DY
4289 ends up in the middle of a line; in this case IT->current_y will be
4290 set to the top of the line moved to. */
4291
4292void
4293move_it_vertically_backward (it, dy)
4294 struct it *it;
4295 int dy;
4296{
4297 int nlines, h, line_height;
4298 struct it it2;
4299 int start_pos = IT_CHARPOS (*it);
4300
4301 xassert (dy >= 0);
4302
4303 /* Estimate how many newlines we must move back. */
4304 nlines = max (1, dy / CANON_Y_UNIT (it->f));
4305
4306 /* Set the iterator's position that many lines back. */
4307 while (nlines-- && IT_CHARPOS (*it) > BEGV)
4308 back_to_previous_visible_line_start (it);
4309
4310 /* Reseat the iterator here. When moving backward, we don't want
4311 reseat to skip forward over invisible text, set up the iterator
4312 to deliver from overlay strings at the new position etc. So,
4313 use reseat_1 here. */
4314 reseat_1 (it, it->current.pos, 1);
4315
4316 /* We are now surely at a line start. */
4317 it->current_x = it->hpos = 0;
4318
4319 /* Move forward and see what y-distance we moved. First move to the
4320 start of the next line so that we get its height. We need this
4321 height to be able to tell whether we reached the specified
4322 y-distance. */
4323 it2 = *it;
4324 it2.max_ascent = it2.max_descent = 0;
4325 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
4326 MOVE_TO_POS | MOVE_TO_VPOS);
4327 xassert (IT_CHARPOS (*it) >= BEGV);
4328 line_height = it2.max_ascent + it2.max_descent;
4329 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
4330 xassert (IT_CHARPOS (*it) >= BEGV);
4331 h = it2.current_y - it->current_y;
4332 nlines = it2.vpos - it->vpos;
4333
4334 /* Correct IT's y and vpos position. */
4335 it->vpos -= nlines;
4336 it->current_y -= h;
4337
4338 if (dy == 0)
4339 {
4340 /* DY == 0 means move to the start of the screen line. The
4341 value of nlines is > 0 if continuation lines were involved. */
4342 if (nlines > 0)
4343 move_it_by_lines (it, nlines, 1);
4344 xassert (IT_CHARPOS (*it) <= start_pos);
4345 }
4346 else if (nlines)
4347 {
4348 /* The y-position we try to reach. Note that h has been
4349 subtracted in front of the if-statement. */
4350 int target_y = it->current_y + h - dy;
4351
4352 /* If we did not reach target_y, try to move further backward if
4353 we can. If we moved too far backward, try to move forward. */
4354 if (target_y < it->current_y
4355 && IT_CHARPOS (*it) > BEGV)
4356 {
4357 move_it_vertically (it, target_y - it->current_y);
4358 xassert (IT_CHARPOS (*it) >= BEGV);
4359 }
4360 else if (target_y >= it->current_y + line_height
4361 && IT_CHARPOS (*it) < ZV)
4362 {
4363 move_it_vertically (it, target_y - (it->current_y + line_height));
4364 xassert (IT_CHARPOS (*it) >= BEGV);
4365 }
4366 }
4367}
4368
4369
4370/* Move IT by a specified amount of pixel lines DY. DY negative means
4371 move backwards. DY = 0 means move to start of screen line. At the
4372 end, IT will be on the start of a screen line. */
4373
4374void
4375move_it_vertically (it, dy)
4376 struct it *it;
4377 int dy;
4378{
4379 if (dy <= 0)
4380 move_it_vertically_backward (it, -dy);
4381 else if (dy > 0)
4382 {
4383 move_it_to (it, ZV, -1, it->current_y + dy, -1,
4384 MOVE_TO_POS | MOVE_TO_Y);
4385
4386 /* If buffer ends in ZV without a newline, move to the start of
4387 the line to satisfy the post-condition. */
4388 if (IT_CHARPOS (*it) == ZV
4389 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
4390 move_it_by_lines (it, 0, 0);
4391 }
4392}
4393
4394
4395/* Return non-zero if some text between buffer positions START_CHARPOS
4396 and END_CHARPOS is invisible. IT->window is the window for text
4397 property lookup. */
4398
4399static int
4400invisible_text_between_p (it, start_charpos, end_charpos)
4401 struct it *it;
4402 int start_charpos, end_charpos;
4403{
4404#ifdef USE_TEXT_PROPERTIES
4405 Lisp_Object prop, limit;
4406 int invisible_found_p;
4407
4408 xassert (it != NULL && start_charpos <= end_charpos);
4409
4410 /* Is text at START invisible? */
4411 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
4412 it->window);
4413 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4414 invisible_found_p = 1;
4415 else
4416 {
4417 limit = Fnext_single_property_change (make_number (start_charpos),
4418 Qinvisible,
4419 Fcurrent_buffer (),
4420 make_number (end_charpos));
4421 invisible_found_p = XFASTINT (limit) < end_charpos;
4422 }
4423
4424 return invisible_found_p;
4425
4426#else /* not USE_TEXT_PROPERTIES */
4427 return 0;
4428#endif /* not USE_TEXT_PROPERTIES */
4429}
4430
4431
4432/* Move IT by a specified number DVPOS of screen lines down. DVPOS
4433 negative means move up. DVPOS == 0 means move to the start of the
4434 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
4435 NEED_Y_P is zero, IT->current_y will be left unchanged.
4436
4437 Further optimization ideas: If we would know that IT->f doesn't use
4438 a face with proportional font, we could be faster for
4439 truncate-lines nil. */
4440
4441void
4442move_it_by_lines (it, dvpos, need_y_p)
4443 struct it *it;
4444 int dvpos, need_y_p;
4445{
4446 struct position pos;
4447
4448 if (!FRAME_WINDOW_P (it->f))
4449 {
4450 struct text_pos textpos;
4451
4452 /* We can use vmotion on frames without proportional fonts. */
4453 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
4454 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
4455 reseat (it, textpos, 1);
4456 it->vpos += pos.vpos;
4457 it->current_y += pos.vpos;
4458 }
4459 else if (dvpos == 0)
4460 {
4461 /* DVPOS == 0 means move to the start of the screen line. */
4462 move_it_vertically_backward (it, 0);
4463 xassert (it->current_x == 0 && it->hpos == 0);
4464 }
4465 else if (dvpos > 0)
4466 {
4467 /* If there are no continuation lines, and if there is no
4468 selective display, try the simple method of moving forward
4469 DVPOS newlines, then see where we are. */
4470 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4471 {
4472 int shortage = 0, charpos;
4473
4474 if (FETCH_BYTE (IT_BYTEPOS (*it) == '\n'))
4475 charpos = IT_CHARPOS (*it) + 1;
4476 else
4477 charpos = scan_buffer ('\n', IT_CHARPOS (*it), 0, dvpos,
4478 &shortage, 0);
4479
4480 if (!invisible_text_between_p (it, IT_CHARPOS (*it), charpos))
4481 {
4482 struct text_pos pos;
4483 CHARPOS (pos) = charpos;
4484 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4485 reseat (it, pos, 1);
4486 it->vpos += dvpos - shortage;
4487 it->hpos = it->current_x = 0;
4488 return;
4489 }
4490 }
4491
4492 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
4493 }
4494 else
4495 {
4496 struct it it2;
4497 int start_charpos, i;
4498
4499 /* If there are no continuation lines, and if there is no
4500 selective display, try the simple method of moving backward
4501 -DVPOS newlines. */
4502 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4503 {
4504 int shortage;
4505 int charpos = IT_CHARPOS (*it);
4506 int bytepos = IT_BYTEPOS (*it);
4507
4508 /* If in the middle of a line, go to its start. */
4509 if (charpos > BEGV && FETCH_BYTE (bytepos - 1) != '\n')
4510 {
4511 charpos = find_next_newline_no_quit (charpos, -1);
4512 bytepos = CHAR_TO_BYTE (charpos);
4513 }
4514
4515 if (charpos == BEGV)
4516 {
4517 struct text_pos pos;
4518 CHARPOS (pos) = charpos;
4519 BYTEPOS (pos) = bytepos;
4520 reseat (it, pos, 1);
4521 it->hpos = it->current_x = 0;
4522 return;
4523 }
4524 else
4525 {
4526 charpos = scan_buffer ('\n', charpos - 1, 0, dvpos, &shortage, 0);
4527 if (!invisible_text_between_p (it, charpos, IT_CHARPOS (*it)))
4528 {
4529 struct text_pos pos;
4530 CHARPOS (pos) = charpos;
4531 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4532 reseat (it, pos, 1);
4533 it->vpos += dvpos + (shortage ? shortage - 1 : 0);
4534 it->hpos = it->current_x = 0;
4535 return;
4536 }
4537 }
4538 }
4539
4540 /* Go back -DVPOS visible lines and reseat the iterator there. */
4541 start_charpos = IT_CHARPOS (*it);
4542 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
4543 back_to_previous_visible_line_start (it);
4544 reseat (it, it->current.pos, 1);
4545 it->current_x = it->hpos = 0;
4546
4547 /* Above call may have moved too far if continuation lines
4548 are involved. Scan forward and see if it did. */
4549 it2 = *it;
4550 it2.vpos = it2.current_y = 0;
4551 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
4552 it->vpos -= it2.vpos;
4553 it->current_y -= it2.current_y;
4554 it->current_x = it->hpos = 0;
4555
4556 /* If we moved too far, move IT some lines forward. */
4557 if (it2.vpos > -dvpos)
4558 {
4559 int delta = it2.vpos + dvpos;
4560 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
4561 }
4562 }
4563}
4564
4565
4566\f
4567/***********************************************************************
4568 Messages
4569 ***********************************************************************/
4570
4571
4572/* Output a newline in the *Messages* buffer if "needs" one. */
4573
4574void
4575message_log_maybe_newline ()
4576{
4577 if (message_log_need_newline)
4578 message_dolog ("", 0, 1, 0);
4579}
4580
4581
4582/* Add a string M of length LEN to the message log, optionally
4583 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
4584 nonzero, means interpret the contents of M as multibyte. This
4585 function calls low-level routines in order to bypass text property
4586 hooks, etc. which might not be safe to run. */
4587
4588void
4589message_dolog (m, len, nlflag, multibyte)
4590 char *m;
4591 int len, nlflag, multibyte;
4592{
4593 if (!NILP (Vmessage_log_max))
4594 {
4595 struct buffer *oldbuf;
4596 Lisp_Object oldpoint, oldbegv, oldzv;
4597 int old_windows_or_buffers_changed = windows_or_buffers_changed;
4598 int point_at_end = 0;
4599 int zv_at_end = 0;
4600 Lisp_Object old_deactivate_mark, tem;
4601 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4602
4603 old_deactivate_mark = Vdeactivate_mark;
4604 oldbuf = current_buffer;
4605 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
4606 current_buffer->undo_list = Qt;
4607
4608 oldpoint = Fpoint_marker ();
4609 oldbegv = Fpoint_min_marker ();
4610 oldzv = Fpoint_max_marker ();
4611 GCPRO4 (oldpoint, oldbegv, oldzv, old_deactivate_mark);
4612
4613 if (PT == Z)
4614 point_at_end = 1;
4615 if (ZV == Z)
4616 zv_at_end = 1;
4617
4618 BEGV = BEG;
4619 BEGV_BYTE = BEG_BYTE;
4620 ZV = Z;
4621 ZV_BYTE = Z_BYTE;
4622 TEMP_SET_PT_BOTH (Z, Z_BYTE);
4623
4624 /* Insert the string--maybe converting multibyte to single byte
4625 or vice versa, so that all the text fits the buffer. */
4626 if (multibyte
4627 && NILP (current_buffer->enable_multibyte_characters))
4628 {
4629 int i, c, nbytes;
4630 unsigned char work[1];
4631
4632 /* Convert a multibyte string to single-byte
4633 for the *Message* buffer. */
4634 for (i = 0; i < len; i += nbytes)
4635 {
4fdb80f2 4636 c = string_char_and_length (m + i, len - i, &nbytes);
5f5c8ee5
GM
4637 work[0] = (SINGLE_BYTE_CHAR_P (c)
4638 ? c
4639 : multibyte_char_to_unibyte (c, Qnil));
4640 insert_1_both (work, 1, 1, 1, 0, 0);
4641 }
4642 }
4643 else if (! multibyte
4644 && ! NILP (current_buffer->enable_multibyte_characters))
4645 {
4646 int i, c, nbytes;
4647 unsigned char *msg = (unsigned char *) m;
4648 unsigned char *str, work[4];
4649 /* Convert a single-byte string to multibyte
4650 for the *Message* buffer. */
4651 for (i = 0; i < len; i++)
4652 {
4653 c = unibyte_char_to_multibyte (msg[i]);
4654 nbytes = CHAR_STRING (c, work, str);
4655 insert_1_both (work, 1, nbytes, 1, 0, 0);
4656 }
4657 }
4658 else if (len)
4659 insert_1 (m, len, 1, 0, 0);
4660
4661 if (nlflag)
4662 {
4663 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
4664 insert_1 ("\n", 1, 1, 0, 0);
4665
4666 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
4667 this_bol = PT;
4668 this_bol_byte = PT_BYTE;
4669
4670 if (this_bol > BEG)
4671 {
4672 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
4673 prev_bol = PT;
4674 prev_bol_byte = PT_BYTE;
4675
4676 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
4677 this_bol, this_bol_byte);
4678 if (dup)
4679 {
4680 del_range_both (prev_bol, prev_bol_byte,
4681 this_bol, this_bol_byte, 0);
4682 if (dup > 1)
4683 {
4684 char dupstr[40];
4685 int duplen;
4686
4687 /* If you change this format, don't forget to also
4688 change message_log_check_duplicate. */
4689 sprintf (dupstr, " [%d times]", dup);
4690 duplen = strlen (dupstr);
4691 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
4692 insert_1 (dupstr, duplen, 1, 0, 1);
4693 }
4694 }
4695 }
4696
4697 if (NATNUMP (Vmessage_log_max))
4698 {
4699 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
4700 -XFASTINT (Vmessage_log_max) - 1, 0);
4701 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
4702 }
4703 }
4704 BEGV = XMARKER (oldbegv)->charpos;
4705 BEGV_BYTE = marker_byte_position (oldbegv);
4706
4707 if (zv_at_end)
4708 {
4709 ZV = Z;
4710 ZV_BYTE = Z_BYTE;
4711 }
4712 else
4713 {
4714 ZV = XMARKER (oldzv)->charpos;
4715 ZV_BYTE = marker_byte_position (oldzv);
4716 }
4717
4718 if (point_at_end)
4719 TEMP_SET_PT_BOTH (Z, Z_BYTE);
4720 else
4721 /* We can't do Fgoto_char (oldpoint) because it will run some
4722 Lisp code. */
4723 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
4724 XMARKER (oldpoint)->bytepos);
4725
4726 UNGCPRO;
4727 free_marker (oldpoint);
4728 free_marker (oldbegv);
4729 free_marker (oldzv);
4730
4731 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
4732 set_buffer_internal (oldbuf);
4733 if (NILP (tem))
4734 windows_or_buffers_changed = old_windows_or_buffers_changed;
4735 message_log_need_newline = !nlflag;
4736 Vdeactivate_mark = old_deactivate_mark;
4737 }
4738}
4739
4740
4741/* We are at the end of the buffer after just having inserted a newline.
4742 (Note: We depend on the fact we won't be crossing the gap.)
4743 Check to see if the most recent message looks a lot like the previous one.
4744 Return 0 if different, 1 if the new one should just replace it, or a
4745 value N > 1 if we should also append " [N times]". */
4746
4747static int
4748message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
4749 int prev_bol, this_bol;
4750 int prev_bol_byte, this_bol_byte;
4751{
4752 int i;
4753 int len = Z_BYTE - 1 - this_bol_byte;
4754 int seen_dots = 0;
4755 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
4756 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
4757
4758 for (i = 0; i < len; i++)
4759 {
4760 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
4761 && p1[i] != '\n')
4762 seen_dots = 1;
4763 if (p1[i] != p2[i])
4764 return seen_dots;
4765 }
4766 p1 += len;
4767 if (*p1 == '\n')
4768 return 2;
4769 if (*p1++ == ' ' && *p1++ == '[')
4770 {
4771 int n = 0;
4772 while (*p1 >= '0' && *p1 <= '9')
4773 n = n * 10 + *p1++ - '0';
4774 if (strncmp (p1, " times]\n", 8) == 0)
4775 return n+1;
4776 }
4777 return 0;
4778}
4779
4780
4781/* Display an echo area message M with a specified length of LEN
4782 chars. The string may include null characters. If M is 0, clear
4783 out any existing message, and let the mini-buffer text show through.
4784
4785 The buffer M must continue to exist until after the echo area gets
4786 cleared or some other message gets displayed there. This means do
4787 not pass text that is stored in a Lisp string; do not pass text in
4788 a buffer that was alloca'd. */
4789
4790void
4791message2 (m, len, multibyte)
4792 char *m;
4793 int len;
4794 int multibyte;
4795{
4796 /* First flush out any partial line written with print. */
4797 message_log_maybe_newline ();
4798 if (m)
4799 message_dolog (m, len, 1, multibyte);
4800 message2_nolog (m, len, multibyte);
4801}
4802
4803
4804/* The non-logging counterpart of message2. */
4805
4806void
4807message2_nolog (m, len, multibyte)
4808 char *m;
4809 int len;
4810{
886bd6f2 4811 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
4812 message_enable_multibyte = multibyte;
4813
4814 if (noninteractive)
4815 {
4816 if (noninteractive_need_newline)
4817 putc ('\n', stderr);
4818 noninteractive_need_newline = 0;
4819 if (m)
4820 fwrite (m, len, 1, stderr);
4821 if (cursor_in_echo_area == 0)
4822 fprintf (stderr, "\n");
4823 fflush (stderr);
4824 }
4825 /* A null message buffer means that the frame hasn't really been
4826 initialized yet. Error messages get reported properly by
4827 cmd_error, so this must be just an informative message; toss it. */
4828 else if (INTERACTIVE
886bd6f2
GM
4829 && sf->glyphs_initialized_p
4830 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
4831 {
4832 Lisp_Object mini_window;
4833 struct frame *f;
4834
4835 /* Get the frame containing the mini-buffer
4836 that the selected frame is using. */
886bd6f2 4837 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
4838 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
4839
4840 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 4841 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
4842 && ! FRAME_VISIBLE_P (f))
4843 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
4844
4845 if (m)
4846 {
c6e89d6c 4847 set_message (m, Qnil, len, multibyte);
5f5c8ee5
GM
4848 if (minibuffer_auto_raise)
4849 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
4850 }
4851 else
c6e89d6c 4852 clear_message (1, 1);
5f5c8ee5 4853
c6e89d6c 4854 do_pending_window_change (0);
5f5c8ee5 4855 echo_area_display (1);
c6e89d6c 4856 do_pending_window_change (0);
5f5c8ee5
GM
4857 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
4858 (*frame_up_to_date_hook) (f);
4859 }
4860}
4861
4862
c6e89d6c
GM
4863/* Display an echo area message M with a specified length of NBYTES
4864 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
4865 string, clear out any existing message, and let the mini-buffer
4866 text show through. */
4867
4868void
c6e89d6c 4869message3 (m, nbytes, multibyte)
5f5c8ee5 4870 Lisp_Object m;
c6e89d6c 4871 int nbytes;
5f5c8ee5
GM
4872 int multibyte;
4873{
4874 struct gcpro gcpro1;
4875
4876 GCPRO1 (m);
4877
4878 /* First flush out any partial line written with print. */
4879 message_log_maybe_newline ();
4880 if (STRINGP (m))
c6e89d6c
GM
4881 message_dolog (XSTRING (m)->data, nbytes, 1, multibyte);
4882 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
4883
4884 UNGCPRO;
4885}
4886
4887
4888/* The non-logging version of message3. */
4889
4890void
c6e89d6c 4891message3_nolog (m, nbytes, multibyte)
5f5c8ee5 4892 Lisp_Object m;
c6e89d6c 4893 int nbytes, multibyte;
5f5c8ee5 4894{
886bd6f2 4895 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
4896 message_enable_multibyte = multibyte;
4897
4898 if (noninteractive)
4899 {
4900 if (noninteractive_need_newline)
4901 putc ('\n', stderr);
4902 noninteractive_need_newline = 0;
4903 if (STRINGP (m))
c6e89d6c 4904 fwrite (XSTRING (m)->data, nbytes, 1, stderr);
5f5c8ee5
GM
4905 if (cursor_in_echo_area == 0)
4906 fprintf (stderr, "\n");
4907 fflush (stderr);
4908 }
4909 /* A null message buffer means that the frame hasn't really been
4910 initialized yet. Error messages get reported properly by
4911 cmd_error, so this must be just an informative message; toss it. */
4912 else if (INTERACTIVE
886bd6f2
GM
4913 && sf->glyphs_initialized_p
4914 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
4915 {
4916 Lisp_Object mini_window;
c6e89d6c 4917 Lisp_Object frame;
5f5c8ee5
GM
4918 struct frame *f;
4919
4920 /* Get the frame containing the mini-buffer
4921 that the selected frame is using. */
886bd6f2 4922 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
4923 frame = XWINDOW (mini_window)->frame;
4924 f = XFRAME (frame);
5f5c8ee5
GM
4925
4926 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 4927 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
4928 && !FRAME_VISIBLE_P (f))
4929 Fmake_frame_visible (frame);
5f5c8ee5 4930
c6e89d6c 4931 if (STRINGP (m) && XSTRING (m)->size)
5f5c8ee5 4932 {
c6e89d6c 4933 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
4934 if (minibuffer_auto_raise)
4935 Fraise_frame (frame);
5f5c8ee5
GM
4936 }
4937 else
c6e89d6c 4938 clear_message (1, 1);
5f5c8ee5 4939
c6e89d6c 4940 do_pending_window_change (0);
5f5c8ee5 4941 echo_area_display (1);
c6e89d6c 4942 do_pending_window_change (0);
5f5c8ee5
GM
4943 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
4944 (*frame_up_to_date_hook) (f);
4945 }
4946}
4947
4948
4949/* Display a null-terminated echo area message M. If M is 0, clear
4950 out any existing message, and let the mini-buffer text show through.
4951
4952 The buffer M must continue to exist until after the echo area gets
4953 cleared or some other message gets displayed there. Do not pass
4954 text that is stored in a Lisp string. Do not pass text in a buffer
4955 that was alloca'd. */
4956
4957void
4958message1 (m)
4959 char *m;
4960{
4961 message2 (m, (m ? strlen (m) : 0), 0);
4962}
4963
4964
4965/* The non-logging counterpart of message1. */
4966
4967void
4968message1_nolog (m)
4969 char *m;
4970{
4971 message2_nolog (m, (m ? strlen (m) : 0), 0);
4972}
4973
4974/* Display a message M which contains a single %s
4975 which gets replaced with STRING. */
4976
4977void
4978message_with_string (m, string, log)
4979 char *m;
4980 Lisp_Object string;
4981 int log;
4982{
4983 if (noninteractive)
4984 {
4985 if (m)
4986 {
4987 if (noninteractive_need_newline)
4988 putc ('\n', stderr);
4989 noninteractive_need_newline = 0;
4990 fprintf (stderr, m, XSTRING (string)->data);
4991 if (cursor_in_echo_area == 0)
4992 fprintf (stderr, "\n");
4993 fflush (stderr);
4994 }
4995 }
4996 else if (INTERACTIVE)
4997 {
4998 /* The frame whose minibuffer we're going to display the message on.
4999 It may be larger than the selected frame, so we need
5000 to use its buffer, not the selected frame's buffer. */
5001 Lisp_Object mini_window;
886bd6f2 5002 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5003
5004 /* Get the frame containing the minibuffer
5005 that the selected frame is using. */
886bd6f2 5006 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5007 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5008
5009 /* A null message buffer means that the frame hasn't really been
5010 initialized yet. Error messages get reported properly by
5011 cmd_error, so this must be just an informative message; toss it. */
5012 if (FRAME_MESSAGE_BUF (f))
5013 {
5014 int len;
5015 char *a[1];
5016 a[0] = (char *) XSTRING (string)->data;
5017
5018 len = doprnt (FRAME_MESSAGE_BUF (f),
5019 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5020
5021 if (log)
5022 message2 (FRAME_MESSAGE_BUF (f), len,
5023 STRING_MULTIBYTE (string));
5024 else
5025 message2_nolog (FRAME_MESSAGE_BUF (f), len,
5026 STRING_MULTIBYTE (string));
5027
5028 /* Print should start at the beginning of the message
5029 buffer next time. */
5030 message_buf_print = 0;
5031 }
5032 }
5033}
5034
5035
5f5c8ee5
GM
5036/* Dump an informative message to the minibuf. If M is 0, clear out
5037 any existing message, and let the mini-buffer text show through. */
5038
5039/* VARARGS 1 */
5040void
5041message (m, a1, a2, a3)
5042 char *m;
5043 EMACS_INT a1, a2, a3;
5044{
5045 if (noninteractive)
5046 {
5047 if (m)
5048 {
5049 if (noninteractive_need_newline)
5050 putc ('\n', stderr);
5051 noninteractive_need_newline = 0;
5052 fprintf (stderr, m, a1, a2, a3);
5053 if (cursor_in_echo_area == 0)
5054 fprintf (stderr, "\n");
5055 fflush (stderr);
5056 }
5057 }
5058 else if (INTERACTIVE)
5059 {
5060 /* The frame whose mini-buffer we're going to display the message
5061 on. It may be larger than the selected frame, so we need to
5062 use its buffer, not the selected frame's buffer. */
5063 Lisp_Object mini_window;
886bd6f2 5064 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5065
5066 /* Get the frame containing the mini-buffer
5067 that the selected frame is using. */
886bd6f2 5068 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5069 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5070
5071 /* A null message buffer means that the frame hasn't really been
5072 initialized yet. Error messages get reported properly by
5073 cmd_error, so this must be just an informative message; toss
5074 it. */
5075 if (FRAME_MESSAGE_BUF (f))
5076 {
5077 if (m)
5078 {
5079 int len;
5080#ifdef NO_ARG_ARRAY
5081 char *a[3];
5082 a[0] = (char *) a1;
5083 a[1] = (char *) a2;
5084 a[2] = (char *) a3;
5085
5086 len = doprnt (FRAME_MESSAGE_BUF (f),
5087 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5088#else
5089 len = doprnt (FRAME_MESSAGE_BUF (f),
5090 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
5091 (char **) &a1);
5092#endif /* NO_ARG_ARRAY */
5093
5094 message2 (FRAME_MESSAGE_BUF (f), len, 0);
5095 }
5096 else
5097 message1 (0);
5098
5099 /* Print should start at the beginning of the message
5100 buffer next time. */
5101 message_buf_print = 0;
5102 }
5103 }
5104}
5105
5106
5107/* The non-logging version of message. */
5108
5109void
5110message_nolog (m, a1, a2, a3)
5111 char *m;
5112 EMACS_INT a1, a2, a3;
5113{
5114 Lisp_Object old_log_max;
5115 old_log_max = Vmessage_log_max;
5116 Vmessage_log_max = Qnil;
5117 message (m, a1, a2, a3);
5118 Vmessage_log_max = old_log_max;
5119}
5120
5121
c6e89d6c
GM
5122/* Display the current message in the current mini-buffer. This is
5123 only called from error handlers in process.c, and is not time
5124 critical. */
5f5c8ee5
GM
5125
5126void
5127update_echo_area ()
5128{
c6e89d6c
GM
5129 if (!NILP (echo_area_buffer[0]))
5130 {
5131 Lisp_Object string;
5132 string = Fcurrent_message ();
5133 message3 (string, XSTRING (string)->size,
5134 !NILP (current_buffer->enable_multibyte_characters));
5135 }
5136}
5137
5138
5139/* Call FN with args A1..A5 with either the current or last displayed
5140 echo_area_buffer as current buffer.
5141
5142 WHICH zero means use the current message buffer
5143 echo_area_buffer[0]. If that is nil, choose a suitable buffer
5144 from echo_buffer[] and clear it.
5145
5146 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
5147 suitable buffer from echo_buffer[] and clear it.
5148
5149 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
5150 that the current message becomes the last displayed one, make
5151 choose a suitable buffer for echo_area_buffer[0], and clear it.
5152
5153 Value is what FN returns. */
5154
5155static int
5156with_echo_area_buffer (w, which, fn, a1, a2, a3, a4, a5)
5157 struct window *w;
5158 int which;
5159 int (*fn) ();
5160 int a1, a2, a3, a4, a5;
5161{
5162 Lisp_Object buffer;
5163 int i, this_one, the_other, clear_buffer_p, rc;
5164 int count = specpdl_ptr - specpdl;
5165
5166 /* If buffers aren't life, make new ones. */
5167 for (i = 0; i < 2; ++i)
5168 if (!BUFFERP (echo_buffer[i])
5169 || NILP (XBUFFER (echo_buffer[i])->name))
5170 {
5171 char name[30];
5172 sprintf (name, " *Echo Area %d*", i);
5173 echo_buffer[i] = Fget_buffer_create (build_string (name));
5174 }
5175
5176 clear_buffer_p = 0;
5177
5178 if (which == 0)
5179 this_one = 0, the_other = 1;
5180 else if (which > 0)
5181 this_one = 1, the_other = 0;
5f5c8ee5 5182 else
c6e89d6c
GM
5183 {
5184 this_one = 0, the_other = 1;
5185 clear_buffer_p = 1;
5186
5187 /* We need a fresh one in case the current echo buffer equals
5188 the one containing the last displayed echo area message. */
5189 if (!NILP (echo_area_buffer[this_one])
5190 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
5191 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
5192 }
5193
5194 /* Choose a suitable buffer from echo_buffer[] is we don't
5195 have one. */
5196 if (NILP (echo_area_buffer[this_one]))
5197 {
5198 echo_area_buffer[this_one]
5199 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
5200 ? echo_buffer[the_other]
5201 : echo_buffer[this_one]);
5202 clear_buffer_p = 1;
5203 }
5204
5205 buffer = echo_area_buffer[this_one];
5206
5207 record_unwind_protect (unwind_with_echo_area_buffer,
5208 with_echo_area_buffer_unwind_data (w));
5209
5210 /* Make the echo area buffer current. Note that for display
5211 purposes, it is not necessary that the displayed window's buffer
5212 == current_buffer, except for text property lookup. So, let's
5213 only set that buffer temporarily here without doing a full
5214 Fset_window_buffer. We must also change w->pointm, though,
5215 because otherwise an assertions in unshow_buffer fails, and Emacs
5216 aborts. */
9142dd5b 5217 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
5218 if (w)
5219 {
5220 w->buffer = buffer;
5221 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
5222 }
5223 current_buffer->truncate_lines = Qnil;
5224 current_buffer->undo_list = Qt;
5225 current_buffer->read_only = Qnil;
5226
5227 if (clear_buffer_p && Z > BEG)
5228 del_range (BEG, Z);
5229
5230 xassert (BEGV >= BEG);
5231 xassert (ZV <= Z && ZV >= BEGV);
5232
5233 rc = fn (a1, a2, a3, a4, a5);
5234
5235 xassert (BEGV >= BEG);
5236 xassert (ZV <= Z && ZV >= BEGV);
5237
5238 unbind_to (count, Qnil);
5239 return rc;
5f5c8ee5
GM
5240}
5241
5242
c6e89d6c
GM
5243/* Save state that should be preserved around the call to the function
5244 FN called in with_echo_area_buffer. */
5f5c8ee5 5245
c6e89d6c
GM
5246static Lisp_Object
5247with_echo_area_buffer_unwind_data (w)
5248 struct window *w;
5f5c8ee5 5249{
c6e89d6c
GM
5250 int i = 0;
5251 Lisp_Object vector;
5f5c8ee5 5252
c6e89d6c
GM
5253 /* Reduce consing by keeping one vector in
5254 Vwith_echo_area_save_vector. */
5255 vector = Vwith_echo_area_save_vector;
5256 Vwith_echo_area_save_vector = Qnil;
5257
5258 if (NILP (vector))
9142dd5b 5259 vector = Fmake_vector (make_number (7), Qnil);
c6e89d6c
GM
5260
5261 XSETBUFFER (XVECTOR (vector)->contents[i], current_buffer); ++i;
5262 XVECTOR (vector)->contents[i++] = Vdeactivate_mark;
5263 XVECTOR (vector)->contents[i++] = make_number (windows_or_buffers_changed);
c6e89d6c
GM
5264
5265 if (w)
5266 {
5267 XSETWINDOW (XVECTOR (vector)->contents[i], w); ++i;
5268 XVECTOR (vector)->contents[i++] = w->buffer;
5269 XVECTOR (vector)->contents[i++]
5270 = make_number (XMARKER (w->pointm)->charpos);
5271 XVECTOR (vector)->contents[i++]
5272 = make_number (XMARKER (w->pointm)->bytepos);
5273 }
5274 else
5275 {
5276 int end = i + 4;
5277 while (i < end)
5278 XVECTOR (vector)->contents[i++] = Qnil;
5279 }
5f5c8ee5 5280
c6e89d6c
GM
5281 xassert (i == XVECTOR (vector)->size);
5282 return vector;
5283}
5f5c8ee5 5284
5f5c8ee5 5285
c6e89d6c
GM
5286/* Restore global state from VECTOR which was created by
5287 with_echo_area_buffer_unwind_data. */
5288
5289static Lisp_Object
5290unwind_with_echo_area_buffer (vector)
5291 Lisp_Object vector;
5292{
5293 int i = 0;
5294
9142dd5b 5295 set_buffer_internal_1 (XBUFFER (XVECTOR (vector)->contents[i])); ++i;
c6e89d6c
GM
5296 Vdeactivate_mark = XVECTOR (vector)->contents[i]; ++i;
5297 windows_or_buffers_changed = XFASTINT (XVECTOR (vector)->contents[i]); ++i;
c6e89d6c
GM
5298
5299 if (WINDOWP (XVECTOR (vector)->contents[i]))
5300 {
5301 struct window *w;
5302 Lisp_Object buffer, charpos, bytepos;
5303
5304 w = XWINDOW (XVECTOR (vector)->contents[i]); ++i;
5305 buffer = XVECTOR (vector)->contents[i]; ++i;
5306 charpos = XVECTOR (vector)->contents[i]; ++i;
5307 bytepos = XVECTOR (vector)->contents[i]; ++i;
5308
5309 w->buffer = buffer;
5310 set_marker_both (w->pointm, buffer,
5311 XFASTINT (charpos), XFASTINT (bytepos));
5312 }
5313
5314 Vwith_echo_area_save_vector = vector;
5315 return Qnil;
5316}
5317
5318
5319/* Set up the echo area for use by print functions. MULTIBYTE_P
5320 non-zero means we will print multibyte. */
5321
5322void
5323setup_echo_area_for_printing (multibyte_p)
5324 int multibyte_p;
5325{
5326 if (!message_buf_print)
5327 {
5328 /* A message has been output since the last time we printed.
5329 Choose a fresh echo area buffer. */
5330 if (EQ (echo_area_buffer[1], echo_buffer[0]))
5331 echo_area_buffer[0] = echo_buffer[1];
5332 else
5333 echo_area_buffer[0] = echo_buffer[0];
5334
5335 /* Switch to that buffer and clear it. */
5336 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5337 if (Z > BEG)
5338 del_range (BEG, Z);
5339 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5340
5341 /* Set up the buffer for the multibyteness we need. */
5342 if (multibyte_p
5343 != !NILP (current_buffer->enable_multibyte_characters))
5344 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
5345
5346 /* Raise the frame containing the echo area. */
5347 if (minibuffer_auto_raise)
5348 {
886bd6f2 5349 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5350 Lisp_Object mini_window;
886bd6f2 5351 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5352 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5353 }
5354
5355 message_buf_print = 1;
5356 }
5357 else if (current_buffer != XBUFFER (echo_area_buffer[0]))
5358 /* Someone switched buffers between print requests. */
5359 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5360}
5361
5362
dd2eb166
GM
5363/* Display an echo area message in window W. Value is non-zero if W's
5364 height is changed. If display_last_displayed_message_p is
5365 non-zero, display the message that was last displayed, otherwise
5366 display the current message. */
c6e89d6c
GM
5367
5368static int
5369display_echo_area (w)
5370 struct window *w;
5371{
dd2eb166
GM
5372 int i, no_message_p, window_height_changed_p;
5373
5374 /* If there is no message, we must call display_echo_area_1
5375 nevertheless because it resizes the window. But we will have to
5376 reset the echo_area_buffer in question to nil at the end because
5377 with_echo_area_buffer will sets it to an empty buffer. */
5378 i = display_last_displayed_message_p ? 1 : 0;
5379 no_message_p = NILP (echo_area_buffer[i]);
5380
5381 window_height_changed_p
5382 = with_echo_area_buffer (w, display_last_displayed_message_p,
5383 (int (*) ()) display_echo_area_1, w);
5384
5385 if (no_message_p)
5386 echo_area_buffer[i] = Qnil;
5387
5388 return window_height_changed_p;
c6e89d6c
GM
5389}
5390
5391
5392/* Helper for display_echo_area. Display the current buffer which
5393 contains the current echo area message in window W, a mini-window.
5394 Change the height of W so that all of the message is displayed.
5395 Value is non-zero if height of W was changed. */
5396
5397static int
5398display_echo_area_1 (w)
5399 struct window *w;
5400{
5401 Lisp_Object window;
5402 struct frame *f = XFRAME (w->frame);
5403 struct text_pos start;
5404 int window_height_changed_p = 0;
5405
5406 /* Do this before displaying, so that we have a large enough glyph
5407 matrix for the display. */
92a90e89 5408 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
5409
5410 /* Display. */
5411 clear_glyph_matrix (w->desired_matrix);
5412 XSETWINDOW (window, w);
5413 SET_TEXT_POS (start, BEG, BEG_BYTE);
5414 try_window (window, start);
5415
c6e89d6c
GM
5416 return window_height_changed_p;
5417}
5418
5419
92a90e89
GM
5420/* Resize the echo area window to exactly the size needed for the
5421 currently displayed message, if there is one. */
5422
5423void
5424resize_echo_area_axactly ()
5425{
5426 if (BUFFERP (echo_area_buffer[0])
5427 && WINDOWP (echo_area_window))
5428 {
5429 struct window *w = XWINDOW (echo_area_window);
5430 int resized_p;
5431
5432 resized_p = with_echo_area_buffer (w, 0,
5433 (int (*) ()) resize_mini_window,
5434 w, 1);
5435 if (resized_p)
5436 {
5437 ++windows_or_buffers_changed;
5438 ++update_mode_lines;
5439 redisplay_internal (0);
5440 }
5441 }
5442}
5443
5444
5445/* Resize mini-window W to fit the size of its contents. EXACT:P
5446 means size the window exactly to the size needed. Otherwise, it's
5447 only enlarged until W's buffer is empty. Value is non-zero if
5448 the window height has been changed. */
c6e89d6c 5449
9472f927 5450int
92a90e89 5451resize_mini_window (w, exact_p)
c6e89d6c 5452 struct window *w;
92a90e89 5453 int exact_p;
c6e89d6c
GM
5454{
5455 struct frame *f = XFRAME (w->frame);
5456 int window_height_changed_p = 0;
5457
5458 xassert (MINI_WINDOW_P (w));
97cafc0f
GM
5459
5460 /* Nil means don't try to resize. */
5461 if (NILP (Vmax_mini_window_height))
5462 return 0;
c6e89d6c
GM
5463
5464 if (!FRAME_MINIBUF_ONLY_P (f))
5465 {
5466 struct it it;
dd2eb166
GM
5467 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
5468 int total_height = XFASTINT (root->height) + XFASTINT (w->height);
5469 int height, max_height;
5470 int unit = CANON_Y_UNIT (f);
5471 struct text_pos start;
9142dd5b 5472
c6e89d6c 5473 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 5474
dd2eb166
GM
5475 /* Compute the max. number of lines specified by the user. */
5476 if (FLOATP (Vmax_mini_window_height))
5477 max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
5478 else if (INTEGERP (Vmax_mini_window_height))
5479 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
5480 else
5481 max_height = total_height / 4;
dd2eb166
GM
5482
5483 /* Correct that max. height if it's bogus. */
5484 max_height = max (1, max_height);
5485 max_height = min (total_height, max_height);
5486
5487 /* Find out the height of the text in the window. */
5488 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
5489 height = (unit - 1 + it.current_y + last_height) / unit;
5490 height = max (1, height);
5491
5492 /* Compute a suitable window start. */
5493 if (height > max_height)
5494 {
5495 height = max_height;
5496 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5497 move_it_vertically_backward (&it, (height - 1) * unit);
5498 start = it.current.pos;
5499 }
5500 else
5501 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5502 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 5503
9472f927
GM
5504 /* Let it grow only, until we display an empty message, in which
5505 case the window shrinks again. */
5506 if (height > XFASTINT (w->height)
92a90e89 5507 || exact_p
9472f927 5508 || BEGV == ZV)
dd2eb166 5509 {
9472f927 5510 Lisp_Object old_selected_window;
c59c668a 5511
9472f927
GM
5512 freeze_window_starts (f, height > XFASTINT (w->height));
5513 old_selected_window = selected_window;
5514 XSETWINDOW (selected_window, w);
5515 change_window_height (height - XFASTINT (w->height), 0);
5516 selected_window = old_selected_window;
9142dd5b
GM
5517 window_height_changed_p = 1;
5518 }
c6e89d6c
GM
5519 }
5520
5521 return window_height_changed_p;
5522}
5523
5524
5525/* Value is the current message, a string, or nil if there is no
5526 current message. */
5527
5528Lisp_Object
5529current_message ()
5530{
5531 Lisp_Object msg;
5532
5533 if (NILP (echo_area_buffer[0]))
5534 msg = Qnil;
5535 else
5536 {
5537 with_echo_area_buffer (0, 0, (int (*) ()) current_message_1, &msg);
5538 if (NILP (msg))
5539 echo_area_buffer[0] = Qnil;
5540 }
5541
5542 return msg;
5543}
5544
5545
5546static int
5547current_message_1 (msg)
5548 Lisp_Object *msg;
5549{
5550 if (Z > BEG)
5551 *msg = make_buffer_string (BEG, Z, 1);
5552 else
5553 *msg = Qnil;
5554 return 0;
5555}
5556
5557
5558/* Push the current message on Vmessage_stack for later restauration
5559 by restore_message. Value is non-zero if the current message isn't
5560 empty. This is a relatively infrequent operation, so it's not
5561 worth optimizing. */
5562
5563int
5564push_message ()
5565{
5566 Lisp_Object msg;
5567 msg = current_message ();
5568 Vmessage_stack = Fcons (msg, Vmessage_stack);
5569 return STRINGP (msg);
5570}
5571
5572
5573/* Restore message display from the top of Vmessage_stack. */
5574
5575void
5576restore_message ()
5577{
5578 Lisp_Object msg;
5579
5580 xassert (CONSP (Vmessage_stack));
5581 msg = XCAR (Vmessage_stack);
5582 if (STRINGP (msg))
5583 message3_nolog (msg, STRING_BYTES (XSTRING (msg)), STRING_MULTIBYTE (msg));
5584 else
5585 message3_nolog (msg, 0, 0);
5586}
5587
5588
5589/* Pop the top-most entry off Vmessage_stack. */
5590
5591void
5592pop_message ()
5593{
5594 xassert (CONSP (Vmessage_stack));
5595 Vmessage_stack = XCDR (Vmessage_stack);
5596}
5597
5598
5599/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
5600 exits. If the stack is not empty, we have a missing pop_message
5601 somewhere. */
5602
5603void
5604check_message_stack ()
5605{
5606 if (!NILP (Vmessage_stack))
5607 abort ();
5608}
5609
5610
5611/* Truncate to NCHARS what will be displayed in the echo area the next
5612 time we display it---but don't redisplay it now. */
5613
5614void
5615truncate_echo_area (nchars)
5616 int nchars;
5617{
5618 if (nchars == 0)
5619 echo_area_buffer[0] = Qnil;
5620 /* A null message buffer means that the frame hasn't really been
5621 initialized yet. Error messages get reported properly by
5622 cmd_error, so this must be just an informative message; toss it. */
5623 else if (!noninteractive
5624 && INTERACTIVE
c6e89d6c 5625 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
5626 {
5627 struct frame *sf = SELECTED_FRAME ();
5628 if (FRAME_MESSAGE_BUF (sf))
5629 with_echo_area_buffer (0, 0, (int (*) ()) truncate_message_1, nchars);
5630 }
c6e89d6c
GM
5631}
5632
5633
5634/* Helper function for truncate_echo_area. Truncate the current
5635 message to at most NCHARS characters. */
5636
5637static int
5638truncate_message_1 (nchars)
5639 int nchars;
5640{
5641 if (BEG + nchars < Z)
5642 del_range (BEG + nchars, Z);
5643 if (Z == BEG)
5644 echo_area_buffer[0] = Qnil;
5645 return 0;
5646}
5647
5648
5649/* Set the current message to a substring of S or STRING.
5650
5651 If STRING is a Lisp string, set the message to the first NBYTES
5652 bytes from STRING. NBYTES zero means use the whole string. If
5653 STRING is multibyte, the message will be displayed multibyte.
5654
5655 If S is not null, set the message to the first LEN bytes of S. LEN
5656 zero means use the whole string. MULTIBYTE_P non-zero means S is
5657 multibyte. Display the message multibyte in that case. */
5658
5659void
5660set_message (s, string, nbytes, multibyte_p)
5661 char *s;
5662 Lisp_Object string;
5663 int nbytes;
5664{
5665 message_enable_multibyte
5666 = ((s && multibyte_p)
5667 || (STRINGP (string) && STRING_MULTIBYTE (string)));
5668
5669 with_echo_area_buffer (0, -1, (int (*) ()) set_message_1,
5670 s, string, nbytes, multibyte_p);
5671 message_buf_print = 0;
5672}
5673
5674
5675/* Helper function for set_message. Arguments have the same meaning
5676 as there. This function is called with the echo area buffer being
5677 current. */
5678
5679static int
5680set_message_1 (s, string, nbytes, multibyte_p)
5681 char *s;
5682 Lisp_Object string;
5683 int nbytes, multibyte_p;
5684{
5685 xassert (BEG == Z);
5686
5687 /* Change multibyteness of the echo buffer appropriately. */
5688 if (message_enable_multibyte
5689 != !NILP (current_buffer->enable_multibyte_characters))
5690 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
5691
5692 /* Insert new message at BEG. */
5693 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5694
5695 if (STRINGP (string))
5696 {
5697 int nchars;
5698
5699 if (nbytes == 0)
5700 nbytes = XSTRING (string)->size_byte;
5701 nchars = string_byte_to_char (string, nbytes);
5702
5703 /* This function takes care of single/multibyte conversion. We
5704 just have to ensure that the echo area buffer has the right
5705 setting of enable_multibyte_characters. */
5706 insert_from_string (string, 0, 0, nchars, nbytes, 1);
5707 }
5708 else if (s)
5709 {
5710 if (nbytes == 0)
5711 nbytes = strlen (s);
5712
5713 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
5714 {
5715 /* Convert from multi-byte to single-byte. */
5716 int i, c, n;
5717 unsigned char work[1];
5718
5719 /* Convert a multibyte string to single-byte. */
5720 for (i = 0; i < nbytes; i += n)
5721 {
5722 c = string_char_and_length (s + i, nbytes - i, &n);
5723 work[0] = (SINGLE_BYTE_CHAR_P (c)
5724 ? c
5725 : multibyte_char_to_unibyte (c, Qnil));
5726 insert_1_both (work, 1, 1, 1, 0, 0);
5727 }
5728 }
5729 else if (!multibyte_p
5730 && !NILP (current_buffer->enable_multibyte_characters))
5731 {
5732 /* Convert from single-byte to multi-byte. */
5733 int i, c, n;
5734 unsigned char *msg = (unsigned char *) s;
5735 unsigned char *str, work[4];
5736
5737 /* Convert a single-byte string to multibyte. */
5738 for (i = 0; i < nbytes; i++)
5739 {
5740 c = unibyte_char_to_multibyte (msg[i]);
5741 n = CHAR_STRING (c, work, str);
5742 insert_1_both (work, 1, n, 1, 0, 0);
5743 }
5744 }
5745 else
5746 insert_1 (s, nbytes, 1, 0, 0);
5747 }
5748
5749 return 0;
5750}
5751
5752
5753/* Clear messages. CURRENT_P non-zero means clear the current
5754 message. LAST_DISPLAYED_P non-zero means clear the message
5755 last displayed. */
5756
5757void
5758clear_message (current_p, last_displayed_p)
5759 int current_p, last_displayed_p;
5760{
5761 if (current_p)
5762 echo_area_buffer[0] = Qnil;
5763
5764 if (last_displayed_p)
5765 echo_area_buffer[1] = Qnil;
5766
5767 message_buf_print = 0;
5768}
5769
5770/* Clear garbaged frames.
5771
5772 This function is used where the old redisplay called
5773 redraw_garbaged_frames which in turn called redraw_frame which in
5774 turn called clear_frame. The call to clear_frame was a source of
5775 flickering. I believe a clear_frame is not necessary. It should
5776 suffice in the new redisplay to invalidate all current matrices,
5777 and ensure a complete redisplay of all windows. */
5778
5779static void
5780clear_garbaged_frames ()
5781{
5f5c8ee5
GM
5782 if (frame_garbaged)
5783 {
5f5c8ee5
GM
5784 Lisp_Object tail, frame;
5785
5786 FOR_EACH_FRAME (tail, frame)
5787 {
5788 struct frame *f = XFRAME (frame);
5789
5790 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
5791 {
5792 clear_current_matrices (f);
5793 f->garbaged = 0;
5794 }
5795 }
5796
5797 frame_garbaged = 0;
5798 ++windows_or_buffers_changed;
5799 }
c6e89d6c 5800}
5f5c8ee5 5801
5f5c8ee5 5802
886bd6f2
GM
5803/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
5804 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 5805 mini-windows height has been changed. */
5f5c8ee5 5806
c6e89d6c
GM
5807static int
5808echo_area_display (update_frame_p)
5809 int update_frame_p;
5810{
5811 Lisp_Object mini_window;
5812 struct window *w;
5813 struct frame *f;
5814 int window_height_changed_p = 0;
886bd6f2 5815 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5816
886bd6f2 5817 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5818 w = XWINDOW (mini_window);
5819 f = XFRAME (WINDOW_FRAME (w));
5820
5821 /* Don't display if frame is invisible or not yet initialized. */
5822 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
5823 return 0;
5f5c8ee5 5824
c6e89d6c
GM
5825 /* When Emacs starts, selected_frame may be a visible terminal
5826 frame, even if we run under a window system. If we let this
5827 through, a message would be displayed on the terminal. */
5828#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 5829 if (!inhibit_window_system && !FRAME_WINDOW_P (sf))
c6e89d6c
GM
5830 return 0;
5831#endif /* HAVE_WINDOW_SYSTEM */
5832
5833 /* Redraw garbaged frames. */
5834 if (frame_garbaged)
5835 clear_garbaged_frames ();
5836
5837 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
5838 {
5839 echo_area_window = mini_window;
5840 window_height_changed_p = display_echo_area (w);
5f5c8ee5 5841 w->must_be_updated_p = 1;
c59c668a 5842
5f5c8ee5
GM
5843 if (update_frame_p)
5844 {
c59c668a
GM
5845 /* Not called from redisplay_internal. If we changed
5846 window configuration, we must redisplay thoroughly.
5847 Otherwise, we can do with updating what we displayed
5848 above. */
5849 if (window_height_changed_p)
5850 {
5851 ++windows_or_buffers_changed;
5852 ++update_mode_lines;
5853 redisplay_internal (0);
5854 }
5855 else if (FRAME_WINDOW_P (f))
5f5c8ee5
GM
5856 {
5857 update_single_window (w, 1);
5858 rif->flush_display (f);
5859 }
5860 else
5861 update_frame (f, 1, 1);
5862 }
5863 }
5864 else if (!EQ (mini_window, selected_window))
5865 windows_or_buffers_changed++;
c59c668a
GM
5866
5867 /* Last displayed message is now the current message. */
dd2eb166
GM
5868 echo_area_buffer[1] = echo_area_buffer[0];
5869
5f5c8ee5
GM
5870 /* Prevent redisplay optimization in redisplay_internal by resetting
5871 this_line_start_pos. This is done because the mini-buffer now
5872 displays the message instead of its buffer text. */
5873 if (EQ (mini_window, selected_window))
5874 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
5875
5876 return window_height_changed_p;
5f5c8ee5
GM
5877}
5878
5879
5880\f
5881/***********************************************************************
5882 Frame Titles
5883 ***********************************************************************/
5884
5885
5886#ifdef HAVE_WINDOW_SYSTEM
5887
5888/* A buffer for constructing frame titles in it; allocated from the
5889 heap in init_xdisp and resized as needed in store_frame_title_char. */
5890
5891static char *frame_title_buf;
5892
5893/* The buffer's end, and a current output position in it. */
5894
5895static char *frame_title_buf_end;
5896static char *frame_title_ptr;
5897
5898
5899/* Store a single character C for the frame title in frame_title_buf.
5900 Re-allocate frame_title_buf if necessary. */
5901
5902static void
5903store_frame_title_char (c)
5904 char c;
5905{
5906 /* If output position has reached the end of the allocated buffer,
5907 double the buffer's size. */
5908 if (frame_title_ptr == frame_title_buf_end)
5909 {
5910 int len = frame_title_ptr - frame_title_buf;
5911 int new_size = 2 * len * sizeof *frame_title_buf;
5912 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
5913 frame_title_buf_end = frame_title_buf + new_size;
5914 frame_title_ptr = frame_title_buf + len;
5915 }
5916
5917 *frame_title_ptr++ = c;
5918}
5919
5920
5921/* Store part of a frame title in frame_title_buf, beginning at
5922 frame_title_ptr. STR is the string to store. Do not copy more
5923 than PRECISION number of bytes from STR; PRECISION <= 0 means copy
5924 the whole string. Pad with spaces until FIELD_WIDTH number of
5925 characters have been copied; FIELD_WIDTH <= 0 means don't pad.
5926 Called from display_mode_element when it is used to build a frame
5927 title. */
5928
5929static int
5930store_frame_title (str, field_width, precision)
5931 unsigned char *str;
5932 int field_width, precision;
5933{
5934 int n = 0;
5935
5936 /* Copy at most PRECISION chars from STR. */
5937 while ((precision <= 0 || n < precision)
5938 && *str)
5939 {
5940 store_frame_title_char (*str++);
5941 ++n;
5942 }
5943
5944 /* Fill up with spaces until FIELD_WIDTH reached. */
5945 while (field_width > 0
5946 && n < field_width)
5947 {
5948 store_frame_title_char (' ');
5949 ++n;
5950 }
5951
5952 return n;
5953}
5954
5955
5956/* Set the title of FRAME, if it has changed. The title format is
5957 Vicon_title_format if FRAME is iconified, otherwise it is
5958 frame_title_format. */
5959
5960static void
5961x_consider_frame_title (frame)
5962 Lisp_Object frame;
5963{
5964 struct frame *f = XFRAME (frame);
5965
5966 if (FRAME_WINDOW_P (f)
5967 || FRAME_MINIBUF_ONLY_P (f)
5968 || f->explicit_name)
5969 {
5970 /* Do we have more than one visible frame on this X display? */
5971 Lisp_Object tail;
5972 Lisp_Object fmt;
5973 struct buffer *obuf;
5974 int len;
5975 struct it it;
5976
9472f927 5977 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 5978 {
9472f927 5979 struct frame *tf = XFRAME (XCAR (tail));
5f5c8ee5
GM
5980
5981 if (tf != f
5982 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
5983 && !FRAME_MINIBUF_ONLY_P (tf)
5984 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
5985 break;
5986 }
5987
5988 /* Set global variable indicating that multiple frames exist. */
5989 multiple_frames = CONSP (tail);
5990
5991 /* Switch to the buffer of selected window of the frame. Set up
5992 frame_title_ptr so that display_mode_element will output into it;
5993 then display the title. */
5994 obuf = current_buffer;
5995 Fset_buffer (XWINDOW (f->selected_window)->buffer);
5996 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
5997 frame_title_ptr = frame_title_buf;
5998 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
5999 NULL, DEFAULT_FACE_ID);
6000 len = display_mode_element (&it, 0, -1, -1, fmt);
6001 frame_title_ptr = NULL;
6002 set_buffer_internal (obuf);
6003
6004 /* Set the title only if it's changed. This avoids consing in
6005 the common case where it hasn't. (If it turns out that we've
6006 already wasted too much time by walking through the list with
6007 display_mode_element, then we might need to optimize at a
6008 higher level than this.) */
6009 if (! STRINGP (f->name)
6010 || STRING_BYTES (XSTRING (f->name)) != len
6011 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
6012 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
6013 }
6014}
6015
6016#else /* not HAVE_WINDOW_SYSTEM */
6017
6018#define frame_title_ptr ((char *)0)
6019#define store_frame_title(str, mincol, maxcol) 0
6020
6021#endif /* not HAVE_WINDOW_SYSTEM */
6022
6023
6024
6025\f
6026/***********************************************************************
6027 Menu Bars
6028 ***********************************************************************/
6029
6030
6031/* Prepare for redisplay by updating menu-bar item lists when
6032 appropriate. This can call eval. */
6033
6034void
6035prepare_menu_bars ()
6036{
6037 int all_windows;
6038 struct gcpro gcpro1, gcpro2;
6039 struct frame *f;
6040 struct frame *tooltip_frame;
6041
6042#ifdef HAVE_X_WINDOWS
6043 tooltip_frame = tip_frame;
6044#else
6045 tooltip_frame = NULL;
6046#endif
6047
6048 /* Update all frame titles based on their buffer names, etc. We do
6049 this before the menu bars so that the buffer-menu will show the
6050 up-to-date frame titles. */
6051#ifdef HAVE_WINDOW_SYSTEM
6052 if (windows_or_buffers_changed || update_mode_lines)
6053 {
6054 Lisp_Object tail, frame;
6055
6056 FOR_EACH_FRAME (tail, frame)
6057 {
6058 f = XFRAME (frame);
6059 if (f != tooltip_frame
6060 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
6061 x_consider_frame_title (frame);
6062 }
6063 }
6064#endif /* HAVE_WINDOW_SYSTEM */
6065
6066 /* Update the menu bar item lists, if appropriate. This has to be
6067 done before any actual redisplay or generation of display lines. */
6068 all_windows = (update_mode_lines
6069 || buffer_shared > 1
6070 || windows_or_buffers_changed);
6071 if (all_windows)
6072 {
6073 Lisp_Object tail, frame;
6074 int count = specpdl_ptr - specpdl;
6075
6076 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6077
6078 FOR_EACH_FRAME (tail, frame)
6079 {
6080 f = XFRAME (frame);
6081
6082 /* Ignore tooltip frame. */
6083 if (f == tooltip_frame)
6084 continue;
6085
6086 /* If a window on this frame changed size, report that to
6087 the user and clear the size-change flag. */
6088 if (FRAME_WINDOW_SIZES_CHANGED (f))
6089 {
6090 Lisp_Object functions;
6091
6092 /* Clear flag first in case we get an error below. */
6093 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
6094 functions = Vwindow_size_change_functions;
6095 GCPRO2 (tail, functions);
6096
6097 while (CONSP (functions))
6098 {
6099 call1 (XCAR (functions), frame);
6100 functions = XCDR (functions);
6101 }
6102 UNGCPRO;
6103 }
6104
6105 GCPRO1 (tail);
6106 update_menu_bar (f, 0);
6107#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 6108 update_tool_bar (f, 0);
5f5c8ee5
GM
6109#endif
6110 UNGCPRO;
6111 }
6112
6113 unbind_to (count, Qnil);
6114 }
6115 else
6116 {
886bd6f2
GM
6117 struct frame *sf = SELECTED_FRAME ();
6118 update_menu_bar (sf, 1);
5f5c8ee5 6119#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 6120 update_tool_bar (sf, 1);
5f5c8ee5
GM
6121#endif
6122 }
6123
6124 /* Motif needs this. See comment in xmenu.c. Turn it off when
6125 pending_menu_activation is not defined. */
6126#ifdef USE_X_TOOLKIT
6127 pending_menu_activation = 0;
6128#endif
6129}
6130
6131
6132/* Update the menu bar item list for frame F. This has to be done
6133 before we start to fill in any display lines, because it can call
6134 eval.
6135
6136 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
6137
6138static void
6139update_menu_bar (f, save_match_data)
6140 struct frame *f;
6141 int save_match_data;
6142{
6143 Lisp_Object window;
6144 register struct window *w;
6145
6146 window = FRAME_SELECTED_WINDOW (f);
6147 w = XWINDOW (window);
6148
6149 if (update_mode_lines)
6150 w->update_mode_line = Qt;
6151
6152 if (FRAME_WINDOW_P (f)
6153 ?
6154#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6155 FRAME_EXTERNAL_MENU_BAR (f)
6156#else
6157 FRAME_MENU_BAR_LINES (f) > 0
6158#endif
6159 : FRAME_MENU_BAR_LINES (f) > 0)
6160 {
6161 /* If the user has switched buffers or windows, we need to
6162 recompute to reflect the new bindings. But we'll
6163 recompute when update_mode_lines is set too; that means
6164 that people can use force-mode-line-update to request
6165 that the menu bar be recomputed. The adverse effect on
6166 the rest of the redisplay algorithm is about the same as
6167 windows_or_buffers_changed anyway. */
6168 if (windows_or_buffers_changed
6169 || !NILP (w->update_mode_line)
6170 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6171 < BUF_MODIFF (XBUFFER (w->buffer)))
6172 != !NILP (w->last_had_star))
6173 || ((!NILP (Vtransient_mark_mode)
6174 && !NILP (XBUFFER (w->buffer)->mark_active))
6175 != !NILP (w->region_showing)))
6176 {
6177 struct buffer *prev = current_buffer;
6178 int count = specpdl_ptr - specpdl;
6179
6180 set_buffer_internal_1 (XBUFFER (w->buffer));
6181 if (save_match_data)
6182 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6183 if (NILP (Voverriding_local_map_menu_flag))
6184 {
6185 specbind (Qoverriding_terminal_local_map, Qnil);
6186 specbind (Qoverriding_local_map, Qnil);
6187 }
6188
6189 /* Run the Lucid hook. */
6190 call1 (Vrun_hooks, Qactivate_menubar_hook);
6191
6192 /* If it has changed current-menubar from previous value,
6193 really recompute the menu-bar from the value. */
6194 if (! NILP (Vlucid_menu_bar_dirty_flag))
6195 call0 (Qrecompute_lucid_menubar);
6196
6197 safe_run_hooks (Qmenu_bar_update_hook);
6198 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
6199
6200 /* Redisplay the menu bar in case we changed it. */
6201#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6202 if (FRAME_WINDOW_P (f))
6203 set_frame_menubar (f, 0, 0);
6204 else
6205 /* On a terminal screen, the menu bar is an ordinary screen
6206 line, and this makes it get updated. */
6207 w->update_mode_line = Qt;
6208#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6209 /* In the non-toolkit version, the menu bar is an ordinary screen
6210 line, and this makes it get updated. */
6211 w->update_mode_line = Qt;
6212#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6213
6214 unbind_to (count, Qnil);
6215 set_buffer_internal_1 (prev);
6216 }
6217 }
6218}
6219
6220
6221\f
6222/***********************************************************************
e037b9ec 6223 Tool-bars
5f5c8ee5
GM
6224 ***********************************************************************/
6225
6226#ifdef HAVE_WINDOW_SYSTEM
6227
e037b9ec 6228/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
6229 before we start to fill in any display lines. Called from
6230 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
6231 and restore it here. */
6232
6233static void
e037b9ec 6234update_tool_bar (f, save_match_data)
5f5c8ee5
GM
6235 struct frame *f;
6236 int save_match_data;
6237{
e037b9ec
GM
6238 if (WINDOWP (f->tool_bar_window)
6239 && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
5f5c8ee5
GM
6240 {
6241 Lisp_Object window;
6242 struct window *w;
6243
6244 window = FRAME_SELECTED_WINDOW (f);
6245 w = XWINDOW (window);
6246
6247 /* If the user has switched buffers or windows, we need to
6248 recompute to reflect the new bindings. But we'll
6249 recompute when update_mode_lines is set too; that means
6250 that people can use force-mode-line-update to request
6251 that the menu bar be recomputed. The adverse effect on
6252 the rest of the redisplay algorithm is about the same as
6253 windows_or_buffers_changed anyway. */
6254 if (windows_or_buffers_changed
6255 || !NILP (w->update_mode_line)
6256 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6257 < BUF_MODIFF (XBUFFER (w->buffer)))
6258 != !NILP (w->last_had_star))
6259 || ((!NILP (Vtransient_mark_mode)
6260 && !NILP (XBUFFER (w->buffer)->mark_active))
6261 != !NILP (w->region_showing)))
6262 {
6263 struct buffer *prev = current_buffer;
6264 int count = specpdl_ptr - specpdl;
a2889657 6265
5f5c8ee5
GM
6266 /* Set current_buffer to the buffer of the selected
6267 window of the frame, so that we get the right local
6268 keymaps. */
6269 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 6270
5f5c8ee5
GM
6271 /* Save match data, if we must. */
6272 if (save_match_data)
6273 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6274
6275 /* Make sure that we don't accidentally use bogus keymaps. */
6276 if (NILP (Voverriding_local_map_menu_flag))
6277 {
6278 specbind (Qoverriding_terminal_local_map, Qnil);
6279 specbind (Qoverriding_local_map, Qnil);
1f40cad2 6280 }
1f40cad2 6281
e037b9ec
GM
6282 /* Build desired tool-bar items from keymaps. */
6283 f->desired_tool_bar_items
6284 = tool_bar_items (f->desired_tool_bar_items,
6285 &f->n_desired_tool_bar_items);
5f5c8ee5 6286
e037b9ec 6287 /* Redisplay the tool-bar in case we changed it. */
5f5c8ee5
GM
6288 w->update_mode_line = Qt;
6289
6290 unbind_to (count, Qnil);
6291 set_buffer_internal_1 (prev);
81d478f3 6292 }
a2889657
JB
6293 }
6294}
6295
6c4429a5 6296
e037b9ec
GM
6297/* Set F->desired_tool_bar_string to a Lisp string representing frame
6298 F's desired tool-bar contents. F->desired_tool_bar_items must have
5f5c8ee5
GM
6299 been set up previously by calling prepare_menu_bars. */
6300
a2889657 6301static void
e037b9ec 6302build_desired_tool_bar_string (f)
5f5c8ee5 6303 struct frame *f;
a2889657 6304{
5f5c8ee5
GM
6305 int i, size, size_needed, string_idx;
6306 struct gcpro gcpro1, gcpro2, gcpro3;
6307 Lisp_Object image, plist, props;
a2889657 6308
5f5c8ee5
GM
6309 image = plist = props = Qnil;
6310 GCPRO3 (image, plist, props);
a2889657 6311
e037b9ec 6312 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5
GM
6313 Otherwise, make a new string. */
6314
6315 /* The size of the string we might be able to reuse. */
e037b9ec
GM
6316 size = (STRINGP (f->desired_tool_bar_string)
6317 ? XSTRING (f->desired_tool_bar_string)->size
5f5c8ee5
GM
6318 : 0);
6319
6320 /* Each image in the string we build is preceded by a space,
6321 and there is a space at the end. */
e037b9ec 6322 size_needed = f->n_desired_tool_bar_items + 1;
5f5c8ee5 6323
e037b9ec 6324 /* Reuse f->desired_tool_bar_string, if possible. */
5f5c8ee5 6325 if (size < size_needed)
e037b9ec 6326 f->desired_tool_bar_string = Fmake_string (make_number (size_needed), ' ');
5f5c8ee5
GM
6327 else
6328 {
6329 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
6330 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 6331 props, f->desired_tool_bar_string);
5f5c8ee5 6332 }
a2889657 6333
5f5c8ee5 6334 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
6335 put a `menu_item' property on tool-bar items with a value that
6336 is the index of the item in F's tool-bar item vector. */
5f5c8ee5 6337 for (i = 0, string_idx = 0;
e037b9ec 6338 i < f->n_desired_tool_bar_items;
5f5c8ee5 6339 ++i, string_idx += 1)
a2889657 6340 {
5f5c8ee5 6341#define PROP(IDX) \
e037b9ec
GM
6342 (XVECTOR (f->desired_tool_bar_items) \
6343 ->contents[i * TOOL_BAR_ITEM_NSLOTS + (IDX)])
5f5c8ee5 6344
e037b9ec
GM
6345 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
6346 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
5f5c8ee5
GM
6347 int margin, relief;
6348 extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
6349 extern Lisp_Object Qlaplace;
6350
6351 /* If image is a vector, choose the image according to the
6352 button state. */
e037b9ec 6353 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
6354 if (VECTORP (image))
6355 {
e037b9ec 6356 enum tool_bar_item_image idx;
5f5c8ee5
GM
6357
6358 if (enabled_p)
6359 idx = (selected_p
e037b9ec
GM
6360 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6361 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
6362 else
6363 idx = (selected_p
e037b9ec
GM
6364 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6365 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
5f5c8ee5
GM
6366
6367 xassert (XVECTOR (image)->size >= idx);
6368 image = XVECTOR (image)->contents[idx];
6369 }
6370
6371 /* Ignore invalid image specifications. */
6372 if (!valid_image_p (image))
6373 continue;
6374
e037b9ec 6375 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
6376 plist = Fcopy_sequence (XCDR (image));
6377
6378 /* Compute margin and relief to draw. */
e037b9ec
GM
6379 relief = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
6380 margin = relief + max (0, tool_bar_button_margin);
5f5c8ee5 6381
e037b9ec 6382 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
6383 {
6384 /* Add a `:relief' property to the image spec if the item is
6385 selected. */
6386 if (selected_p)
6387 {
6388 plist = Fplist_put (plist, QCrelief, make_number (-relief));
6389 margin -= relief;
6390 }
6391 }
6392 else
6393 {
6394 /* If image is selected, display it pressed, i.e. with a
6395 negative relief. If it's not selected, display it with a
6396 raised relief. */
6397 plist = Fplist_put (plist, QCrelief,
6398 (selected_p
6399 ? make_number (-relief)
6400 : make_number (relief)));
6401 margin -= relief;
6402 }
6403
6404 /* Put a margin around the image. */
6405 if (margin)
6406 plist = Fplist_put (plist, QCmargin, make_number (margin));
6407
6408 /* If button is not enabled, make the image appear disabled by
6409 applying an appropriate algorithm to it. */
6410 if (!enabled_p)
6411 plist = Fplist_put (plist, QCalgorithm, Qlaplace);
6412
6413 /* Put a `display' text property on the string for the image to
6414 display. Put a `menu-item' property on the string that gives
e037b9ec 6415 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
6416 vector. */
6417 image = Fcons (Qimage, plist);
6418 props = list4 (Qdisplay, image,
e037b9ec 6419 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)),
5f5c8ee5
GM
6420 Fadd_text_properties (make_number (string_idx),
6421 make_number (string_idx + 1),
e037b9ec 6422 props, f->desired_tool_bar_string);
5f5c8ee5 6423#undef PROP
a2889657
JB
6424 }
6425
5f5c8ee5
GM
6426 UNGCPRO;
6427}
6428
6429
e037b9ec 6430/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
6431
6432static void
e037b9ec 6433display_tool_bar_line (it)
5f5c8ee5
GM
6434 struct it *it;
6435{
6436 struct glyph_row *row = it->glyph_row;
6437 int max_x = it->last_visible_x;
6438 struct glyph *last;
6439
6440 prepare_desired_row (row);
6441 row->y = it->current_y;
6442
6443 while (it->current_x < max_x)
a2889657 6444 {
5f5c8ee5 6445 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 6446
5f5c8ee5
GM
6447 /* Get the next display element. */
6448 if (!get_next_display_element (it))
6449 break;
73af359d 6450
5f5c8ee5
GM
6451 /* Produce glyphs. */
6452 x_before = it->current_x;
6453 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
6454 PRODUCE_GLYPHS (it);
daa37602 6455
5f5c8ee5
GM
6456 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
6457 i = 0;
6458 x = x_before;
6459 while (i < nglyphs)
6460 {
6461 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
6462
6463 if (x + glyph->pixel_width > max_x)
6464 {
6465 /* Glyph doesn't fit on line. */
6466 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
6467 it->current_x = x;
6468 goto out;
6469 }
daa37602 6470
5f5c8ee5
GM
6471 ++it->hpos;
6472 x += glyph->pixel_width;
6473 ++i;
6474 }
6475
6476 /* Stop at line ends. */
6477 if (ITERATOR_AT_END_OF_LINE_P (it))
6478 break;
6479
6480 set_iterator_to_next (it);
a2889657 6481 }
a2889657 6482
5f5c8ee5 6483 out:;
a2889657 6484
5f5c8ee5
GM
6485 row->displays_text_p = row->used[TEXT_AREA] != 0;
6486 extend_face_to_end_of_line (it);
6487 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
6488 last->right_box_line_p = 1;
6489 compute_line_metrics (it);
6490
e037b9ec 6491 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
6492 if (!row->displays_text_p)
6493 {
312246d1
GM
6494 row->height = row->phys_height = it->last_visible_y - row->y;
6495 row->ascent = row->phys_ascent = 0;
5f5c8ee5
GM
6496 }
6497
6498 row->full_width_p = 1;
6499 row->continued_p = 0;
6500 row->truncated_on_left_p = 0;
6501 row->truncated_on_right_p = 0;
6502
6503 it->current_x = it->hpos = 0;
6504 it->current_y += row->height;
6505 ++it->vpos;
6506 ++it->glyph_row;
a2889657 6507}
96a410bc 6508
5f5c8ee5 6509
e037b9ec 6510/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 6511 items of frame F visible. */
96a410bc 6512
d39b6696 6513static int
e037b9ec 6514tool_bar_lines_needed (f)
5f5c8ee5 6515 struct frame *f;
d39b6696 6516{
e037b9ec 6517 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5
GM
6518 struct it it;
6519
e037b9ec
GM
6520 /* Initialize an iterator for iteration over
6521 F->desired_tool_bar_string in the tool-bar window of frame F. */
6522 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
6523 it.first_visible_x = 0;
6524 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
e037b9ec 6525 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
6526
6527 while (!ITERATOR_AT_END_P (&it))
6528 {
6529 it.glyph_row = w->desired_matrix->rows;
6530 clear_glyph_row (it.glyph_row);
e037b9ec 6531 display_tool_bar_line (&it);
5f5c8ee5
GM
6532 }
6533
6534 return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
d39b6696 6535}
96a410bc 6536
5f5c8ee5 6537
e037b9ec 6538/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
6539 height should be changed. */
6540
6541static int
e037b9ec 6542redisplay_tool_bar (f)
5f5c8ee5 6543 struct frame *f;
96a410bc 6544{
5f5c8ee5
GM
6545 struct window *w;
6546 struct it it;
6547 struct glyph_row *row;
6548 int change_height_p = 0;
6549
e037b9ec
GM
6550 /* If frame hasn't a tool-bar window or if it is zero-height, don't
6551 do anything. This means you must start with tool-bar-lines
5f5c8ee5 6552 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
6553 can turn off tool-bars by specifying tool-bar-lines zero. */
6554 if (!WINDOWP (f->tool_bar_window)
6555 || (w = XWINDOW (f->tool_bar_window),
5f5c8ee5
GM
6556 XFASTINT (w->height) == 0))
6557 return 0;
96a410bc 6558
e037b9ec
GM
6559 /* Set up an iterator for the tool-bar window. */
6560 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
6561 it.first_visible_x = 0;
6562 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
6563 row = it.glyph_row;
3450d04c 6564
e037b9ec
GM
6565 /* Build a string that represents the contents of the tool-bar. */
6566 build_desired_tool_bar_string (f);
6567 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 6568
e037b9ec 6569 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 6570 while (it.current_y < it.last_visible_y)
e037b9ec 6571 display_tool_bar_line (&it);
3450d04c 6572
e037b9ec 6573 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
6574 window, so don't do it. */
6575 w->desired_matrix->no_scrolling_p = 1;
6576 w->must_be_updated_p = 1;
3450d04c 6577
e037b9ec 6578 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
6579 {
6580 int nlines;
6581
6582 /* If there are blank lines at the end, except for a partially
6583 visible blank line at the end that is smaller than
e037b9ec 6584 CANON_Y_UNIT, change the tool-bar's height. */
5f5c8ee5
GM
6585 row = it.glyph_row - 1;
6586 if (!row->displays_text_p
6587 && row->height >= CANON_Y_UNIT (f))
6588 change_height_p = 1;
6589
e037b9ec
GM
6590 /* If row displays tool-bar items, but is partially visible,
6591 change the tool-bar's height. */
5f5c8ee5
GM
6592 if (row->displays_text_p
6593 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
6594 change_height_p = 1;
6595
e037b9ec 6596 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
6597 frame parameter. */
6598 if (change_height_p
e037b9ec 6599 && (nlines = tool_bar_lines_needed (f),
5f5c8ee5
GM
6600 nlines != XFASTINT (w->height)))
6601 {
e037b9ec 6602 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5
GM
6603 Lisp_Object frame;
6604
6605 XSETFRAME (frame, f);
6606 clear_glyph_matrix (w->desired_matrix);
6607 Fmodify_frame_parameters (frame,
e037b9ec 6608 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
6609 make_number (nlines)),
6610 Qnil));
6611 fonts_changed_p = 1;
6612 }
6613 }
3450d04c 6614
5f5c8ee5 6615 return change_height_p;
96a410bc 6616}
90adcf20 6617
5f5c8ee5 6618
e037b9ec
GM
6619/* Get information about the tool-bar item which is displayed in GLYPH
6620 on frame F. Return in *PROP_IDX the index where tool-bar item
6621 properties start in F->current_tool_bar_items. Value is zero if
6622 GLYPH doesn't display a tool-bar item. */
5f5c8ee5
GM
6623
6624int
e037b9ec 6625tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
6626 struct frame *f;
6627 struct glyph *glyph;
6628 int *prop_idx;
90adcf20 6629{
5f5c8ee5
GM
6630 Lisp_Object prop;
6631 int success_p;
6632
6633 /* Get the text property `menu-item' at pos. The value of that
6634 property is the start index of this item's properties in
e037b9ec 6635 F->current_tool_bar_items. */
5f5c8ee5 6636 prop = Fget_text_property (make_number (glyph->charpos),
e037b9ec 6637 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
6638 if (INTEGERP (prop))
6639 {
6640 *prop_idx = XINT (prop);
6641 success_p = 1;
6642 }
6643 else
6644 success_p = 0;
90adcf20 6645
5f5c8ee5
GM
6646 return success_p;
6647}
6648
6649#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 6650
feb0c42f 6651
5f5c8ee5
GM
6652\f
6653/************************************************************************
6654 Horizontal scrolling
6655 ************************************************************************/
feb0c42f 6656
5f5c8ee5
GM
6657static int hscroll_window_tree P_ ((Lisp_Object));
6658static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 6659
5f5c8ee5
GM
6660/* For all leaf windows in the window tree rooted at WINDOW, set their
6661 hscroll value so that PT is (i) visible in the window, and (ii) so
6662 that it is not within a certain margin at the window's left and
6663 right border. Value is non-zero if any window's hscroll has been
6664 changed. */
6665
6666static int
6667hscroll_window_tree (window)
6668 Lisp_Object window;
6669{
6670 int hscrolled_p = 0;
6671
6672 while (WINDOWP (window))
90adcf20 6673 {
5f5c8ee5
GM
6674 struct window *w = XWINDOW (window);
6675
6676 if (WINDOWP (w->hchild))
6677 hscrolled_p |= hscroll_window_tree (w->hchild);
6678 else if (WINDOWP (w->vchild))
6679 hscrolled_p |= hscroll_window_tree (w->vchild);
6680 else if (w->cursor.vpos >= 0)
6681 {
6682 int hscroll_margin, text_area_x, text_area_y;
6683 int text_area_width, text_area_height;
92a90e89
GM
6684 struct glyph_row *current_cursor_row
6685 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
6686 struct glyph_row *desired_cursor_row
6687 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
6688 struct glyph_row *cursor_row
6689 = (desired_cursor_row->enabled_p
6690 ? desired_cursor_row
6691 : current_cursor_row);
a2725ab2 6692
5f5c8ee5
GM
6693 window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
6694 &text_area_width, &text_area_height);
90adcf20 6695
5f5c8ee5
GM
6696 /* Scroll when cursor is inside this scroll margin. */
6697 hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
6698
6699 if ((XFASTINT (w->hscroll)
6700 && w->cursor.x < hscroll_margin)
92a90e89
GM
6701 || (cursor_row->enabled_p
6702 && cursor_row->truncated_on_right_p
5f5c8ee5 6703 && (w->cursor.x > text_area_width - hscroll_margin)))
08b610e4 6704 {
5f5c8ee5
GM
6705 struct it it;
6706 int hscroll;
6707 struct buffer *saved_current_buffer;
6708 int pt;
6709
6710 /* Find point in a display of infinite width. */
6711 saved_current_buffer = current_buffer;
6712 current_buffer = XBUFFER (w->buffer);
6713
6714 if (w == XWINDOW (selected_window))
6715 pt = BUF_PT (current_buffer);
6716 else
08b610e4 6717 {
5f5c8ee5
GM
6718 pt = marker_position (w->pointm);
6719 pt = max (BEGV, pt);
6720 pt = min (ZV, pt);
6721 }
6722
6723 /* Move iterator to pt starting at cursor_row->start in
6724 a line with infinite width. */
6725 init_to_row_start (&it, w, cursor_row);
6726 it.last_visible_x = INFINITY;
6727 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
6728 current_buffer = saved_current_buffer;
6729
6730 /* Center cursor in window. */
6731 hscroll = (max (0, it.current_x - text_area_width / 2)
6732 / CANON_X_UNIT (it.f));
6733
6734 /* Don't call Fset_window_hscroll if value hasn't
6735 changed because it will prevent redisplay
6736 optimizations. */
6737 if (XFASTINT (w->hscroll) != hscroll)
6738 {
6739 Fset_window_hscroll (window, make_number (hscroll));
6740 hscrolled_p = 1;
08b610e4 6741 }
08b610e4 6742 }
08b610e4 6743 }
a2725ab2 6744
5f5c8ee5 6745 window = w->next;
90adcf20 6746 }
cd6dfed6 6747
5f5c8ee5
GM
6748 /* Value is non-zero if hscroll of any leaf window has been changed. */
6749 return hscrolled_p;
6750}
6751
6752
6753/* Set hscroll so that cursor is visible and not inside horizontal
6754 scroll margins for all windows in the tree rooted at WINDOW. See
6755 also hscroll_window_tree above. Value is non-zero if any window's
6756 hscroll has been changed. If it has, desired matrices on the frame
6757 of WINDOW are cleared. */
6758
6759static int
6760hscroll_windows (window)
6761 Lisp_Object window;
6762{
6763 int hscrolled_p = hscroll_window_tree (window);
6764 if (hscrolled_p)
6765 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
6766 return hscrolled_p;
90adcf20 6767}
5f5c8ee5
GM
6768
6769
90adcf20 6770\f
5f5c8ee5
GM
6771/************************************************************************
6772 Redisplay
6773 ************************************************************************/
6774
6775/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
6776 to a non-zero value. This is sometimes handy to have in a debugger
6777 session. */
6778
6779#if GLYPH_DEBUG
a2889657 6780
5f5c8ee5
GM
6781/* First and last unchanged row for try_window_id. */
6782
6783int debug_first_unchanged_at_end_vpos;
6784int debug_last_unchanged_at_beg_vpos;
6785
6786/* Delta vpos and y. */
6787
6788int debug_dvpos, debug_dy;
6789
6790/* Delta in characters and bytes for try_window_id. */
6791
6792int debug_delta, debug_delta_bytes;
6793
6794/* Values of window_end_pos and window_end_vpos at the end of
6795 try_window_id. */
6796
6797int debug_end_pos, debug_end_vpos;
6798
6799/* Append a string to W->desired_matrix->method. FMT is a printf
6800 format string. A1...A9 are a supplement for a variable-length
6801 argument list. If trace_redisplay_p is non-zero also printf the
6802 resulting string to stderr. */
6803
6804static void
6805debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
6806 struct window *w;
6807 char *fmt;
6808 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
6809{
6810 char buffer[512];
6811 char *method = w->desired_matrix->method;
6812 int len = strlen (method);
6813 int size = sizeof w->desired_matrix->method;
6814 int remaining = size - len - 1;
6815
6816 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
6817 if (len && remaining)
6818 {
6819 method[len] = '|';
6820 --remaining, ++len;
6821 }
6822
6823 strncpy (method + len, buffer, remaining);
6824
6825 if (trace_redisplay_p)
6826 fprintf (stderr, "%p (%s): %s\n",
6827 w,
6828 ((BUFFERP (w->buffer)
6829 && STRINGP (XBUFFER (w->buffer)->name))
6830 ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
6831 : "no buffer"),
6832 buffer);
6833}
a2889657 6834
5f5c8ee5 6835#endif /* GLYPH_DEBUG */
90adcf20 6836
a2889657 6837
5f5c8ee5
GM
6838/* This counter is used to clear the face cache every once in a while
6839 in redisplay_internal. It is incremented for each redisplay.
6840 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
6841 cleared. */
0d231165 6842
5f5c8ee5 6843#define CLEAR_FACE_CACHE_COUNT 10000
463f6b91
RS
6844static int clear_face_cache_count;
6845
20de20dc 6846/* Record the previous terminal frame we displayed. */
5f5c8ee5
GM
6847
6848static struct frame *previous_terminal_frame;
6849
6850/* Non-zero while redisplay_internal is in progress. */
6851
6852int redisplaying_p;
6853
6854
6855/* Value is non-zero if all changes in window W, which displays
6856 current_buffer, are in the text between START and END. START is a
6857 buffer position, END is given as a distance from Z. Used in
6858 redisplay_internal for display optimization. */
6859
6860static INLINE int
6861text_outside_line_unchanged_p (w, start, end)
6862 struct window *w;
6863 int start, end;
6864{
6865 int unchanged_p = 1;
6866
6867 /* If text or overlays have changed, see where. */
6868 if (XFASTINT (w->last_modified) < MODIFF
6869 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
6870 {
6871 /* Gap in the line? */
6872 if (GPT < start || Z - GPT < end)
6873 unchanged_p = 0;
6874
6875 /* Changes start in front of the line, or end after it? */
6876 if (unchanged_p
9142dd5b
GM
6877 && (BEG_UNCHANGED < start - 1
6878 || END_UNCHANGED < end))
5f5c8ee5
GM
6879 unchanged_p = 0;
6880
6881 /* If selective display, can't optimize if changes start at the
6882 beginning of the line. */
6883 if (unchanged_p
6884 && INTEGERP (current_buffer->selective_display)
6885 && XINT (current_buffer->selective_display) > 0
9142dd5b 6886 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5
GM
6887 unchanged_p = 0;
6888 }
6889
6890 return unchanged_p;
6891}
6892
6893
6894/* Do a frame update, taking possible shortcuts into account. This is
6895 the main external entry point for redisplay.
6896
6897 If the last redisplay displayed an echo area message and that message
6898 is no longer requested, we clear the echo area or bring back the
6899 mini-buffer if that is in use. */
20de20dc 6900
a2889657
JB
6901void
6902redisplay ()
e9874cee
RS
6903{
6904 redisplay_internal (0);
6905}
6906
5f5c8ee5 6907
9142dd5b
GM
6908/* Reconsider the setting of B->clip_changed which is displayed
6909 in window W. */
6910
6911static INLINE void
6912reconsider_clip_changes (w, b)
6913 struct window *w;
6914 struct buffer *b;
6915{
6916 if (b->prevent_redisplay_optimizations_p)
6917 b->clip_changed = 1;
6918 else if (b->clip_changed
6919 && !NILP (w->window_end_valid)
6920 && w->current_matrix->buffer == b
6921 && w->current_matrix->zv == BUF_ZV (b)
6922 && w->current_matrix->begv == BUF_BEGV (b))
6923 b->clip_changed = 0;
6924}
6925
6926
5f5c8ee5
GM
6927/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
6928 response to any user action; therefore, we should preserve the echo
6929 area. (Actually, our caller does that job.) Perhaps in the future
6930 avoid recentering windows if it is not necessary; currently that
6931 causes some problems. */
e9874cee
RS
6932
6933static void
6934redisplay_internal (preserve_echo_area)
6935 int preserve_echo_area;
a2889657 6936{
5f5c8ee5
GM
6937 struct window *w = XWINDOW (selected_window);
6938 struct frame *f = XFRAME (w->frame);
6939 int pause;
a2889657 6940 int must_finish = 0;
5f5c8ee5 6941 struct text_pos tlbufpos, tlendpos;
89819bdd 6942 int number_of_visible_frames;
28514cd9 6943 int count;
886bd6f2 6944 struct frame *sf = SELECTED_FRAME ();
a2889657 6945
5f5c8ee5
GM
6946 /* Non-zero means redisplay has to consider all windows on all
6947 frames. Zero means, only selected_window is considered. */
6948 int consider_all_windows_p;
6949
6950 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
6951
6952 /* No redisplay if running in batch mode or frame is not yet fully
6953 initialized, or redisplay is explicitly turned off by setting
6954 Vinhibit_redisplay. */
6955 if (noninteractive
6956 || !NILP (Vinhibit_redisplay)
6957 || !f->glyphs_initialized_p)
a2889657
JB
6958 return;
6959
5f5c8ee5
GM
6960 /* The flag redisplay_performed_directly_p is set by
6961 direct_output_for_insert when it already did the whole screen
6962 update necessary. */
6963 if (redisplay_performed_directly_p)
6964 {
6965 redisplay_performed_directly_p = 0;
6966 if (!hscroll_windows (selected_window))
6967 return;
6968 }
6969
15f0cf78
RS
6970#ifdef USE_X_TOOLKIT
6971 if (popup_activated ())
6972 return;
6973#endif
6974
28514cd9 6975 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 6976 if (redisplaying_p)
735c094c
KH
6977 return;
6978
28514cd9
GM
6979 /* Record a function that resets redisplaying_p to its old value
6980 when we leave this function. */
6981 count = specpdl_ptr - specpdl;
6982 record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
6983 ++redisplaying_p;
6984
8b32d885
RS
6985 retry:
6986
9142dd5b
GM
6987 reconsider_clip_changes (w, current_buffer);
6988
5f5c8ee5
GM
6989 /* If new fonts have been loaded that make a glyph matrix adjustment
6990 necessary, do it. */
6991 if (fonts_changed_p)
6992 {
6993 adjust_glyphs (NULL);
6994 ++windows_or_buffers_changed;
6995 fonts_changed_p = 0;
6996 }
6997
886bd6f2
GM
6998 if (! FRAME_WINDOW_P (sf)
6999 && previous_terminal_frame != sf)
20de20dc 7000 {
5f5c8ee5
GM
7001 /* Since frames on an ASCII terminal share the same display
7002 area, displaying a different frame means redisplay the whole
7003 thing. */
20de20dc 7004 windows_or_buffers_changed++;
886bd6f2
GM
7005 SET_FRAME_GARBAGED (sf);
7006 XSETFRAME (Vterminal_frame, sf);
20de20dc 7007 }
886bd6f2 7008 previous_terminal_frame = sf;
20de20dc 7009
5f5c8ee5
GM
7010 /* Set the visible flags for all frames. Do this before checking
7011 for resized or garbaged frames; they want to know if their frames
7012 are visible. See the comment in frame.h for
7013 FRAME_SAMPLE_VISIBILITY. */
d724d989 7014 {
35f56f96 7015 Lisp_Object tail, frame;
d724d989 7016
89819bdd
RS
7017 number_of_visible_frames = 0;
7018
35f56f96 7019 FOR_EACH_FRAME (tail, frame)
f82aff7c 7020 {
5f5c8ee5
GM
7021 struct frame *f = XFRAME (frame);
7022
7023 FRAME_SAMPLE_VISIBILITY (f);
7024 if (FRAME_VISIBLE_P (f))
7025 ++number_of_visible_frames;
7026 clear_desired_matrices (f);
f82aff7c 7027 }
d724d989
JB
7028 }
7029
44fa5b1e 7030 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 7031 do_pending_window_change (1);
a2889657 7032
5f5c8ee5 7033 /* Clear frames marked as garbaged. */
44fa5b1e 7034 if (frame_garbaged)
c6e89d6c 7035 clear_garbaged_frames ();
a2889657 7036
e037b9ec 7037 /* Build menubar and tool-bar items. */
f82aff7c
RS
7038 prepare_menu_bars ();
7039
28995e67 7040 if (windows_or_buffers_changed)
a2889657
JB
7041 update_mode_lines++;
7042
538f13d4
RS
7043 /* Detect case that we need to write or remove a star in the mode line. */
7044 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
7045 {
7046 w->update_mode_line = Qt;
7047 if (buffer_shared > 1)
7048 update_mode_lines++;
7049 }
7050
5f5c8ee5 7051 /* If %c is in the mode line, update it if needed. */
28995e67
RS
7052 if (!NILP (w->column_number_displayed)
7053 /* This alternative quickly identifies a common case
7054 where no change is needed. */
7055 && !(PT == XFASTINT (w->last_point)
8850a573
RS
7056 && XFASTINT (w->last_modified) >= MODIFF
7057 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
7058 && XFASTINT (w->column_number_displayed) != current_column ())
7059 w->update_mode_line = Qt;
7060
44fa5b1e 7061 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 7062
5f5c8ee5
GM
7063 /* The variable buffer_shared is set in redisplay_window and
7064 indicates that we redisplay a buffer in different windows. See
7065 there. */
7066 consider_all_windows_p = update_mode_lines || buffer_shared > 1;
a2889657
JB
7067
7068 /* If specs for an arrow have changed, do thorough redisplay
7069 to ensure we remove any arrow that should no longer exist. */
d45de95b 7070 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 7071 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 7072 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 7073
90adcf20
RS
7074 /* Normally the message* functions will have already displayed and
7075 updated the echo area, but the frame may have been trashed, or
7076 the update may have been preempted, so display the echo area
c6e89d6c
GM
7077 again here. Checking both message buffers captures the case that
7078 the echo area should be cleared. */
7079 if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
90adcf20 7080 {
c6e89d6c 7081 int window_height_changed_p = echo_area_display (0);
90adcf20 7082 must_finish = 1;
dd2eb166 7083
c6e89d6c
GM
7084 if (fonts_changed_p)
7085 goto retry;
7086 else if (window_height_changed_p)
7087 {
7088 consider_all_windows_p = 1;
7089 ++update_mode_lines;
7090 ++windows_or_buffers_changed;
9142dd5b
GM
7091
7092 /* If window configuration was changed, frames may have been
7093 marked garbaged. Clear them or we will experience
7094 surprises wrt scrolling. */
7095 if (frame_garbaged)
7096 clear_garbaged_frames ();
c6e89d6c 7097 }
90adcf20 7098 }
dd2eb166
GM
7099 else if (w == XWINDOW (minibuf_window)
7100 && (current_buffer->clip_changed
7101 || XFASTINT (w->last_modified) < MODIFF
7102 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 7103 && resize_mini_window (w, 0))
c6e89d6c
GM
7104 {
7105 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
7106 showing if its contents might have changed. */
7107 must_finish = 1;
7108 consider_all_windows_p = 1;
c6e89d6c 7109 ++windows_or_buffers_changed;
dd2eb166 7110 ++update_mode_lines;
9142dd5b
GM
7111
7112 /* If window configuration was changed, frames may have been
7113 marked garbaged. Clear them or we will experience
7114 surprises wrt scrolling. */
7115 if (frame_garbaged)
7116 clear_garbaged_frames ();
c6e89d6c
GM
7117 }
7118
90adcf20 7119
5f5c8ee5
GM
7120 /* If showing the region, and mark has changed, we must redisplay
7121 the whole window. The assignment to this_line_start_pos prevents
7122 the optimization directly below this if-statement. */
bd66d1ba
RS
7123 if (((!NILP (Vtransient_mark_mode)
7124 && !NILP (XBUFFER (w->buffer)->mark_active))
7125 != !NILP (w->region_showing))
82d04750
JB
7126 || (!NILP (w->region_showing)
7127 && !EQ (w->region_showing,
7128 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
7129 CHARPOS (this_line_start_pos) = 0;
7130
7131 /* Optimize the case that only the line containing the cursor in the
7132 selected window has changed. Variables starting with this_ are
7133 set in display_line and record information about the line
7134 containing the cursor. */
7135 tlbufpos = this_line_start_pos;
7136 tlendpos = this_line_end_pos;
7137 if (!consider_all_windows_p
7138 && CHARPOS (tlbufpos) > 0
7139 && NILP (w->update_mode_line)
73af359d 7140 && !current_buffer->clip_changed
44fa5b1e 7141 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 7142 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 7143 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
7144 && this_line_buffer == current_buffer
7145 && current_buffer == XBUFFER (w->buffer)
265a9e55 7146 && NILP (w->force_start)
5f5c8ee5
GM
7147 /* Point must be on the line that we have info recorded about. */
7148 && PT >= CHARPOS (tlbufpos)
7149 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
7150 /* All text outside that line, including its final newline,
7151 must be unchanged */
5f5c8ee5
GM
7152 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
7153 CHARPOS (tlendpos)))
7154 {
7155 if (CHARPOS (tlbufpos) > BEGV
7156 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
7157 && (CHARPOS (tlbufpos) == ZV
7158 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
7159 /* Former continuation line has disappeared by becoming empty */
7160 goto cancel;
7161 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 7162 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
7163 || MINI_WINDOW_P (w))
7164 {
1c9241f5
KH
7165 /* We have to handle the case of continuation around a
7166 wide-column character (See the comment in indent.c around
7167 line 885).
7168
7169 For instance, in the following case:
7170
7171 -------- Insert --------
7172 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
7173 J_I_ ==> J_I_ `^^' are cursors.
7174 ^^ ^^
7175 -------- --------
7176
7177 As we have to redraw the line above, we should goto cancel. */
7178
5f5c8ee5
GM
7179 struct it it;
7180 int line_height_before = this_line_pixel_height;
7181
7182 /* Note that start_display will handle the case that the
7183 line starting at tlbufpos is a continuation lines. */
7184 start_display (&it, w, tlbufpos);
7185
7186 /* Implementation note: It this still necessary? */
7187 if (it.current_x != this_line_start_x)
1c9241f5
KH
7188 goto cancel;
7189
5f5c8ee5
GM
7190 TRACE ((stderr, "trying display optimization 1\n"));
7191 w->cursor.vpos = -1;
a2889657 7192 overlay_arrow_seen = 0;
5f5c8ee5
GM
7193 it.vpos = this_line_vpos;
7194 it.current_y = this_line_y;
7195 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
7196 display_line (&it);
7197
a2889657 7198 /* If line contains point, is not continued,
5f5c8ee5
GM
7199 and ends at same distance from eob as before, we win */
7200 if (w->cursor.vpos >= 0
7201 /* Line is not continued, otherwise this_line_start_pos
7202 would have been set to 0 in display_line. */
7203 && CHARPOS (this_line_start_pos)
7204 /* Line ends as before. */
7205 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
7206 /* Line has same height as before. Otherwise other lines
7207 would have to be shifted up or down. */
7208 && this_line_pixel_height == line_height_before)
a2889657 7209 {
5f5c8ee5
GM
7210 /* If this is not the window's last line, we must adjust
7211 the charstarts of the lines below. */
7212 if (it.current_y < it.last_visible_y)
7213 {
7214 struct glyph_row *row
7215 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
7216 int delta, delta_bytes;
7217
7218 if (Z - CHARPOS (tlendpos) == ZV)
7219 {
7220 /* This line ends at end of (accessible part of)
7221 buffer. There is no newline to count. */
7222 delta = (Z
7223 - CHARPOS (tlendpos)
7224 - MATRIX_ROW_START_CHARPOS (row));
7225 delta_bytes = (Z_BYTE
7226 - BYTEPOS (tlendpos)
7227 - MATRIX_ROW_START_BYTEPOS (row));
7228 }
7229 else
7230 {
7231 /* This line ends in a newline. Must take
7232 account of the newline and the rest of the
7233 text that follows. */
7234 delta = (Z
7235 - CHARPOS (tlendpos)
7236 - MATRIX_ROW_START_CHARPOS (row));
7237 delta_bytes = (Z_BYTE
7238 - BYTEPOS (tlendpos)
7239 - MATRIX_ROW_START_BYTEPOS (row));
7240 }
7241
7242 increment_glyph_matrix_buffer_positions (w->current_matrix,
7243 this_line_vpos + 1,
7244 w->current_matrix->nrows,
7245 delta, delta_bytes);
85bcef6c 7246 }
46db8486 7247
5f5c8ee5
GM
7248 /* If this row displays text now but previously didn't,
7249 or vice versa, w->window_end_vpos may have to be
7250 adjusted. */
7251 if ((it.glyph_row - 1)->displays_text_p)
7252 {
7253 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
7254 XSETINT (w->window_end_vpos, this_line_vpos);
7255 }
7256 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
7257 && this_line_vpos > 0)
7258 XSETINT (w->window_end_vpos, this_line_vpos - 1);
7259 w->window_end_valid = Qnil;
7260
7261 /* Update hint: No need to try to scroll in update_window. */
7262 w->desired_matrix->no_scrolling_p = 1;
7263
7264#if GLYPH_DEBUG
7265 *w->desired_matrix->method = 0;
7266 debug_method_add (w, "optimization 1");
7267#endif
a2889657
JB
7268 goto update;
7269 }
7270 else
7271 goto cancel;
7272 }
5f5c8ee5
GM
7273 else if (/* Cursor position hasn't changed. */
7274 PT == XFASTINT (w->last_point)
b6f0fe04
RS
7275 /* Make sure the cursor was last displayed
7276 in this window. Otherwise we have to reposition it. */
5f5c8ee5
GM
7277 && 0 <= w->cursor.vpos
7278 && XINT (w->height) > w->cursor.vpos)
a2889657
JB
7279 {
7280 if (!must_finish)
7281 {
c6e89d6c 7282 do_pending_window_change (1);
5f5c8ee5
GM
7283
7284 /* We used to always goto end_of_redisplay here, but this
7285 isn't enough if we have a blinking cursor. */
7286 if (w->cursor_off_p == w->last_cursor_off_p)
7287 goto end_of_redisplay;
a2889657
JB
7288 }
7289 goto update;
7290 }
8b51f1e3
KH
7291 /* If highlighting the region, or if the cursor is in the echo area,
7292 then we can't just move the cursor. */
bd66d1ba
RS
7293 else if (! (!NILP (Vtransient_mark_mode)
7294 && !NILP (current_buffer->mark_active))
293a54ce
RS
7295 && (w == XWINDOW (current_buffer->last_selected_window)
7296 || highlight_nonselected_windows)
8b51f1e3 7297 && NILP (w->region_showing)
8f897821 7298 && NILP (Vshow_trailing_whitespace)
8b51f1e3 7299 && !cursor_in_echo_area)
a2889657 7300 {
5f5c8ee5
GM
7301 struct it it;
7302 struct glyph_row *row;
7303
7304 /* Skip from tlbufpos to PT and see where it is. Note that
7305 PT may be in invisible text. If so, we will end at the
7306 next visible position. */
7307 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
7308 NULL, DEFAULT_FACE_ID);
7309 it.current_x = this_line_start_x;
7310 it.current_y = this_line_y;
7311 it.vpos = this_line_vpos;
7312
7313 /* The call to move_it_to stops in front of PT, but
7314 moves over before-strings. */
7315 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
7316
7317 if (it.vpos == this_line_vpos
7318 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
7319 row->enabled_p))
a2889657 7320 {
5f5c8ee5
GM
7321 xassert (this_line_vpos == it.vpos);
7322 xassert (this_line_y == it.current_y);
7323 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
a2889657
JB
7324 goto update;
7325 }
7326 else
7327 goto cancel;
7328 }
5f5c8ee5 7329
a2889657 7330 cancel:
5f5c8ee5
GM
7331 /* Text changed drastically or point moved off of line. */
7332 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
7333 }
7334
5f5c8ee5
GM
7335 CHARPOS (this_line_start_pos) = 0;
7336 consider_all_windows_p |= buffer_shared > 1;
7337 ++clear_face_cache_count;
a2889657 7338
5f5c8ee5
GM
7339
7340 /* Build desired matrices. If consider_all_windows_p is non-zero,
7341 do it for all windows on all frames. Otherwise do it for
7342 selected_window, only. */
463f6b91 7343
5f5c8ee5 7344 if (consider_all_windows_p)
a2889657 7345 {
35f56f96 7346 Lisp_Object tail, frame;
a2889657 7347
5f5c8ee5
GM
7348 /* Clear the face cache eventually. */
7349 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 7350 {
5f5c8ee5 7351 clear_face_cache (0);
463f6b91
RS
7352 clear_face_cache_count = 0;
7353 }
31b24551 7354
5f5c8ee5
GM
7355 /* Recompute # windows showing selected buffer. This will be
7356 incremented each time such a window is displayed. */
a2889657
JB
7357 buffer_shared = 0;
7358
35f56f96 7359 FOR_EACH_FRAME (tail, frame)
30c566e4 7360 {
5f5c8ee5 7361 struct frame *f = XFRAME (frame);
886bd6f2 7362 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 7363 {
5f5c8ee5
GM
7364 /* Mark all the scroll bars to be removed; we'll redeem
7365 the ones we want when we redisplay their windows. */
9769686d
RS
7366 if (condemn_scroll_bars_hook)
7367 (*condemn_scroll_bars_hook) (f);
30c566e4 7368
f21ef775 7369 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 7370 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 7371
5f5c8ee5
GM
7372 /* Any scroll bars which redisplay_windows should have
7373 nuked should now go away. */
9769686d
RS
7374 if (judge_scroll_bars_hook)
7375 (*judge_scroll_bars_hook) (f);
7376 }
30c566e4 7377 }
a2889657 7378 }
886bd6f2
GM
7379 else if (FRAME_VISIBLE_P (sf)
7380 && !FRAME_OBSCURED_P (sf))
5f5c8ee5
GM
7381 redisplay_window (selected_window, 1);
7382
7383
7384 /* Compare desired and current matrices, perform output. */
7385
7386update:
7387
7388 /* If fonts changed, display again. */
7389 if (fonts_changed_p)
7390 goto retry;
a2889657 7391
a2889657
JB
7392 /* Prevent various kinds of signals during display update.
7393 stdio is not robust about handling signals,
7394 which can cause an apparent I/O error. */
7395 if (interrupt_input)
7396 unrequest_sigio ();
7397 stop_polling ();
7398
5f5c8ee5 7399 if (consider_all_windows_p)
a2889657
JB
7400 {
7401 Lisp_Object tail;
92a90e89
GM
7402 struct frame *f;
7403 int hscrolled_p;
a2889657
JB
7404
7405 pause = 0;
92a90e89 7406 hscrolled_p = 0;
a2889657 7407
92a90e89 7408 /* See if we have to hscroll. */
9472f927 7409 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
92a90e89
GM
7410 if (FRAMEP (XCAR (tail)))
7411 {
7412 f = XFRAME (XCAR (tail));
7413
7414 if ((FRAME_WINDOW_P (f)
886bd6f2 7415 || f == sf)
92a90e89
GM
7416 && FRAME_VISIBLE_P (f)
7417 && !FRAME_OBSCURED_P (f)
7418 && hscroll_windows (f->root_window))
7419 hscrolled_p = 1;
7420 }
7421
7422 if (hscrolled_p)
7423 goto retry;
a2889657 7424
92a90e89
GM
7425 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
7426 {
9472f927 7427 if (!FRAMEP (XCAR (tail)))
a2889657
JB
7428 continue;
7429
9472f927 7430 f = XFRAME (XCAR (tail));
1af9f229 7431
886bd6f2 7432 if ((FRAME_WINDOW_P (f) || f == sf)
f21ef775 7433 && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
a2889657 7434 {
5f5c8ee5
GM
7435 /* Mark all windows as to be updated. */
7436 set_window_update_flags (XWINDOW (f->root_window), 1);
44fa5b1e 7437 pause |= update_frame (f, 0, 0);
a2889657 7438 if (!pause)
efc63ef0
RS
7439 {
7440 mark_window_display_accurate (f->root_window, 1);
7441 if (frame_up_to_date_hook != 0)
7442 (*frame_up_to_date_hook) (f);
7443 }
a2889657
JB
7444 }
7445 }
7446 }
7447 else
6e8290aa 7448 {
886bd6f2
GM
7449 if (FRAME_VISIBLE_P (sf)
7450 && !FRAME_OBSCURED_P (sf))
5f5c8ee5 7451 {
92a90e89
GM
7452 if (hscroll_windows (selected_window))
7453 goto retry;
7454
5f5c8ee5 7455 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 7456 pause = update_frame (sf, 0, 0);
5f5c8ee5 7457 }
4d641a15
KH
7458 else
7459 pause = 0;
d724d989 7460
8de2d90b 7461 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
7462 function. If the echo area is on another frame, that may
7463 have put text on a frame other than the selected one, so the
7464 above call to update_frame would not have caught it. Catch
8de2d90b
JB
7465 it here. */
7466 {
84faf44c 7467 Lisp_Object mini_window;
5f5c8ee5 7468 struct frame *mini_frame;
84faf44c 7469
886bd6f2 7470 mini_window = FRAME_MINIBUF_WINDOW (sf);
84faf44c 7471 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
8de2d90b 7472
886bd6f2 7473 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
5f5c8ee5
GM
7474 {
7475 XWINDOW (mini_window)->must_be_updated_p = 1;
7476 pause |= update_frame (mini_frame, 0, 0);
7477 if (!pause && hscroll_windows (mini_window))
7478 goto retry;
7479 }
8de2d90b 7480 }
6e8290aa 7481 }
a2889657 7482
5f5c8ee5
GM
7483 /* If display was paused because of pending input, make sure we do a
7484 thorough update the next time. */
a2889657
JB
7485 if (pause)
7486 {
5f5c8ee5
GM
7487 /* Prevent the optimization at the beginning of
7488 redisplay_internal that tries a single-line update of the
7489 line containing the cursor in the selected window. */
7490 CHARPOS (this_line_start_pos) = 0;
7491
7492 /* Let the overlay arrow be updated the next time. */
265a9e55 7493 if (!NILP (last_arrow_position))
a2889657
JB
7494 {
7495 last_arrow_position = Qt;
7496 last_arrow_string = Qt;
7497 }
5f5c8ee5
GM
7498
7499 /* If we pause after scrolling, some rows in the current
7500 matrices of some windows are not valid. */
7501 if (!WINDOW_FULL_WIDTH_P (w)
7502 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
7503 update_mode_lines = 1;
7504 }
7505
5f5c8ee5
GM
7506 /* Now text on frame agrees with windows, so put info into the
7507 windows for partial redisplay to follow. */
a2889657
JB
7508 if (!pause)
7509 {
7510 register struct buffer *b = XBUFFER (w->buffer);
7511
9142dd5b
GM
7512 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
7513 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
7514 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
7515 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
a2889657 7516
5f5c8ee5 7517 if (consider_all_windows_p)
886bd6f2 7518 mark_window_display_accurate (FRAME_ROOT_WINDOW (sf), 1);
a2889657
JB
7519 else
7520 {
5f5c8ee5
GM
7521 XSETFASTINT (w->last_point, BUF_PT (b));
7522 w->last_cursor = w->cursor;
7523 w->last_cursor_off_p = w->cursor_off_p;
7524
28995e67 7525 b->clip_changed = 0;
9142dd5b 7526 b->prevent_redisplay_optimizations_p = 0;
a2889657 7527 w->update_mode_line = Qnil;
c2213350 7528 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
8850a573 7529 XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
538f13d4
RS
7530 w->last_had_star
7531 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
7532 ? Qt : Qnil);
3ee4159a
RS
7533
7534 /* Record if we are showing a region, so can make sure to
7535 update it fully at next redisplay. */
7536 w->region_showing = (!NILP (Vtransient_mark_mode)
293a54ce
RS
7537 && (w == XWINDOW (current_buffer->last_selected_window)
7538 || highlight_nonselected_windows)
3ee4159a
RS
7539 && !NILP (XBUFFER (w->buffer)->mark_active)
7540 ? Fmarker_position (XBUFFER (w->buffer)->mark)
7541 : Qnil);
7542
d2f84654 7543 w->window_end_valid = w->buffer;
d45de95b 7544 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657 7545 last_arrow_string = Voverlay_arrow_string;
efc63ef0 7546 if (frame_up_to_date_hook != 0)
886bd6f2 7547 (*frame_up_to_date_hook) (sf);
9142dd5b
GM
7548
7549 w->current_matrix->buffer = b;
7550 w->current_matrix->begv = BUF_BEGV (b);
7551 w->current_matrix->zv = BUF_ZV (b);
a2889657 7552 }
5f5c8ee5 7553
a2889657
JB
7554 update_mode_lines = 0;
7555 windows_or_buffers_changed = 0;
7556 }
7557
5f5c8ee5
GM
7558 /* Start SIGIO interrupts coming again. Having them off during the
7559 code above makes it less likely one will discard output, but not
7560 impossible, since there might be stuff in the system buffer here.
a2889657 7561 But it is much hairier to try to do anything about that. */
a2889657
JB
7562 if (interrupt_input)
7563 request_sigio ();
7564 start_polling ();
7565
5f5c8ee5
GM
7566 /* If a frame has become visible which was not before, redisplay
7567 again, so that we display it. Expose events for such a frame
7568 (which it gets when becoming visible) don't call the parts of
7569 redisplay constructing glyphs, so simply exposing a frame won't
7570 display anything in this case. So, we have to display these
7571 frames here explicitly. */
11c52c4f
RS
7572 if (!pause)
7573 {
7574 Lisp_Object tail, frame;
7575 int new_count = 0;
7576
7577 FOR_EACH_FRAME (tail, frame)
7578 {
7579 int this_is_visible = 0;
8e83f802
RS
7580
7581 if (XFRAME (frame)->visible)
7582 this_is_visible = 1;
7583 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
7584 if (XFRAME (frame)->visible)
7585 this_is_visible = 1;
11c52c4f
RS
7586
7587 if (this_is_visible)
7588 new_count++;
7589 }
7590
89819bdd 7591 if (new_count != number_of_visible_frames)
11c52c4f
RS
7592 windows_or_buffers_changed++;
7593 }
7594
44fa5b1e 7595 /* Change frame size now if a change is pending. */
c6e89d6c 7596 do_pending_window_change (1);
d8e242fd 7597
8b32d885
RS
7598 /* If we just did a pending size change, or have additional
7599 visible frames, redisplay again. */
3c8c72e0 7600 if (windows_or_buffers_changed && !pause)
8b32d885 7601 goto retry;
5f5c8ee5
GM
7602
7603 end_of_redisplay:;
c6e89d6c 7604
28514cd9 7605 unbind_to (count, Qnil);
a2889657
JB
7606}
7607
5f5c8ee5
GM
7608
7609/* Redisplay, but leave alone any recent echo area message unless
7610 another message has been requested in its place.
a2889657
JB
7611
7612 This is useful in situations where you need to redisplay but no
7613 user action has occurred, making it inappropriate for the message
7614 area to be cleared. See tracking_off and
7615 wait_reading_process_input for examples of these situations. */
7616
8991bb31 7617void
a2889657
JB
7618redisplay_preserve_echo_area ()
7619{
c6e89d6c 7620 if (!NILP (echo_area_buffer[1]))
a2889657 7621 {
c6e89d6c
GM
7622 /* We have a previously displayed message, but no current
7623 message. Redisplay the previous message. */
7624 display_last_displayed_message_p = 1;
e9874cee 7625 redisplay_internal (1);
c6e89d6c 7626 display_last_displayed_message_p = 0;
a2889657
JB
7627 }
7628 else
e9874cee 7629 redisplay_internal (1);
a2889657
JB
7630}
7631
5f5c8ee5 7632
28514cd9
GM
7633/* Function registered with record_unwind_protect in
7634 redisplay_internal. Clears the flag indicating that a redisplay is
7635 in progress. */
7636
7637static Lisp_Object
7638unwind_redisplay (old_redisplaying_p)
7639 Lisp_Object old_redisplaying_p;
7640{
7641 redisplaying_p = XFASTINT (old_redisplaying_p);
c6e89d6c 7642 return Qnil;
28514cd9
GM
7643}
7644
7645
5f5c8ee5
GM
7646/* Mark the display of windows in the window tree rooted at WINDOW as
7647 accurate or inaccurate. If FLAG is non-zero mark display of WINDOW
7648 as accurate. If FLAG is zero arrange for WINDOW to be redisplayed
7649 the next time redisplay_internal is called. */
7650
a2889657 7651void
5f5c8ee5 7652mark_window_display_accurate (window, accurate_p)
a2889657 7653 Lisp_Object window;
5f5c8ee5 7654 int accurate_p;
a2889657 7655{
5f5c8ee5
GM
7656 struct window *w;
7657
7658 for (; !NILP (window); window = w->next)
a2889657
JB
7659 {
7660 w = XWINDOW (window);
7661
5f5c8ee5 7662 if (BUFFERP (w->buffer))
bd66d1ba 7663 {
5f5c8ee5
GM
7664 struct buffer *b = XBUFFER (w->buffer);
7665
c2213350 7666 XSETFASTINT (w->last_modified,
5f5c8ee5 7667 accurate_p ? BUF_MODIFF (b) : 0);
8850a573 7668 XSETFASTINT (w->last_overlay_modified,
5f5c8ee5
GM
7669 accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
7670 w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)
7671 ? Qt : Qnil);
bd66d1ba 7672
5f5c8ee5
GM
7673#if 0 /* I don't think this is necessary because display_line does it.
7674 Let's check it. */
bd66d1ba
RS
7675 /* Record if we are showing a region, so can make sure to
7676 update it fully at next redisplay. */
5f5c8ee5
GM
7677 w->region_showing
7678 = (!NILP (Vtransient_mark_mode)
7679 && (w == XWINDOW (current_buffer->last_selected_window)
7680 || highlight_nonselected_windows)
7681 && (!NILP (b->mark_active)
7682 ? Fmarker_position (b->mark)
7683 : Qnil));
7684#endif
7685
7686 if (accurate_p)
7687 {
7688 b->clip_changed = 0;
9142dd5b
GM
7689 b->prevent_redisplay_optimizations_p = 0;
7690 w->current_matrix->buffer = b;
7691 w->current_matrix->begv = BUF_BEGV (b);
7692 w->current_matrix->zv = BUF_ZV (b);
5f5c8ee5
GM
7693 w->last_cursor = w->cursor;
7694 w->last_cursor_off_p = w->cursor_off_p;
7695 if (w == XWINDOW (selected_window))
7696 w->last_point = BUF_PT (b);
7697 else
7698 w->last_point = XMARKER (w->pointm)->charpos;
7699 }
bd66d1ba
RS
7700 }
7701
d2f84654 7702 w->window_end_valid = w->buffer;
a2889657
JB
7703 w->update_mode_line = Qnil;
7704
265a9e55 7705 if (!NILP (w->vchild))
5f5c8ee5 7706 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 7707 if (!NILP (w->hchild))
5f5c8ee5 7708 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
7709 }
7710
5f5c8ee5 7711 if (accurate_p)
a2889657 7712 {
d45de95b 7713 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
7714 last_arrow_string = Voverlay_arrow_string;
7715 }
7716 else
7717 {
5f5c8ee5
GM
7718 /* Force a thorough redisplay the next time by setting
7719 last_arrow_position and last_arrow_string to t, which is
7720 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
7721 last_arrow_position = Qt;
7722 last_arrow_string = Qt;
7723 }
7724}
5f5c8ee5
GM
7725
7726
7727/* Return value in display table DP (Lisp_Char_Table *) for character
7728 C. Since a display table doesn't have any parent, we don't have to
7729 follow parent. Do not call this function directly but use the
7730 macro DISP_CHAR_VECTOR. */
7731
7732Lisp_Object
7733disp_char_vector (dp, c)
7734 struct Lisp_Char_Table *dp;
7735 int c;
7736{
7737 int code[4], i;
7738 Lisp_Object val;
7739
7740 if (SINGLE_BYTE_CHAR_P (c))
7741 return (dp->contents[c]);
7742
7743 SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
7744 if (code[0] != CHARSET_COMPOSITION)
7745 {
7746 if (code[1] < 32)
7747 code[1] = -1;
7748 else if (code[2] < 32)
7749 code[2] = -1;
7750 }
7751
7752 /* Here, the possible range of code[0] (== charset ID) is
7753 128..max_charset. Since the top level char table contains data
7754 for multibyte characters after 256th element, we must increment
7755 code[0] by 128 to get a correct index. */
7756 code[0] += 128;
7757 code[3] = -1; /* anchor */
7758
7759 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
7760 {
7761 val = dp->contents[code[i]];
7762 if (!SUB_CHAR_TABLE_P (val))
7763 return (NILP (val) ? dp->defalt : val);
7764 }
7765
7766 /* Here, val is a sub char table. We return the default value of
7767 it. */
7768 return (dp->defalt);
7769}
7770
7771
a2889657 7772\f
5f5c8ee5
GM
7773/***********************************************************************
7774 Window Redisplay
7775 ***********************************************************************/
a2725ab2 7776
5f5c8ee5 7777/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
7778
7779static void
5f5c8ee5
GM
7780redisplay_windows (window)
7781 Lisp_Object window;
90adcf20 7782{
5f5c8ee5
GM
7783 while (!NILP (window))
7784 {
7785 struct window *w = XWINDOW (window);
7786
7787 if (!NILP (w->hchild))
7788 redisplay_windows (w->hchild);
7789 else if (!NILP (w->vchild))
7790 redisplay_windows (w->vchild);
7791 else
7792 redisplay_window (window, 0);
a2725ab2 7793
5f5c8ee5
GM
7794 window = w->next;
7795 }
7796}
7797
7798
7799/* Set cursor position of W. PT is assumed to be displayed in ROW.
7800 DELTA is the number of bytes by which positions recorded in ROW
7801 differ from current buffer positions. */
7802
7803void
7804set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
7805 struct window *w;
7806 struct glyph_row *row;
7807 struct glyph_matrix *matrix;
7808 int delta, delta_bytes, dy, dvpos;
7809{
7810 struct glyph *glyph = row->glyphs[TEXT_AREA];
7811 struct glyph *end = glyph + row->used[TEXT_AREA];
7812 int x = row->x;
7813 int pt_old = PT - delta;
7814
7815 /* Skip over glyphs not having an object at the start of the row.
7816 These are special glyphs like truncation marks on terminal
7817 frames. */
7818 if (row->displays_text_p)
7819 while (glyph < end
7820 && !glyph->object
7821 && glyph->charpos < 0)
7822 {
7823 x += glyph->pixel_width;
7824 ++glyph;
7825 }
7826
7827 while (glyph < end
7828 && glyph->object
7829 && (!BUFFERP (glyph->object)
7830 || glyph->charpos < pt_old))
7831 {
7832 x += glyph->pixel_width;
7833 ++glyph;
7834 }
7835
7836 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
7837 w->cursor.x = x;
7838 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
7839 w->cursor.y = row->y + dy;
7840
7841 if (w == XWINDOW (selected_window))
7842 {
7843 if (!row->continued_p
7844 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
7845 && row->x == 0)
7846 {
7847 this_line_buffer = XBUFFER (w->buffer);
7848
7849 CHARPOS (this_line_start_pos)
7850 = MATRIX_ROW_START_CHARPOS (row) + delta;
7851 BYTEPOS (this_line_start_pos)
7852 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
7853
7854 CHARPOS (this_line_end_pos)
7855 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
7856 BYTEPOS (this_line_end_pos)
7857 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
7858
7859 this_line_y = w->cursor.y;
7860 this_line_pixel_height = row->height;
7861 this_line_vpos = w->cursor.vpos;
7862 this_line_start_x = row->x;
7863 }
7864 else
7865 CHARPOS (this_line_start_pos) = 0;
7866 }
7867}
7868
7869
7870/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
7871 start STARTP. Sets the window start of WINDOW to that position.
7872
7873 We assume that the window's buffer is really current. */
5f5c8ee5
GM
7874
7875static INLINE struct text_pos
7876run_window_scroll_functions (window, startp)
7877 Lisp_Object window;
7878 struct text_pos startp;
7879{
7880 struct window *w = XWINDOW (window);
7881 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
7882
7883 if (current_buffer != XBUFFER (w->buffer))
7884 abort ();
7885
5f5c8ee5
GM
7886 if (!NILP (Vwindow_scroll_functions))
7887 {
7888 run_hook_with_args_2 (Qwindow_scroll_functions, window,
7889 make_number (CHARPOS (startp)));
7890 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
7891 /* In case the hook functions switch buffers. */
7892 if (current_buffer != XBUFFER (w->buffer))
7893 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 7894 }
90adcf20 7895
5f5c8ee5
GM
7896 return startp;
7897}
7898
7899
7900/* Modify the desired matrix of window W and W->vscroll so that the
7901 line containing the cursor is fully visible. */
7902
7903static void
7904make_cursor_line_fully_visible (w)
7905 struct window *w;
7906{
7907 struct glyph_matrix *matrix;
7908 struct glyph_row *row;
045dee35 7909 int header_line_height;
5f5c8ee5
GM
7910
7911 /* It's not always possible to find the cursor, e.g, when a window
7912 is full of overlay strings. Don't do anything in that case. */
7913 if (w->cursor.vpos < 0)
7914 return;
7915
7916 matrix = w->desired_matrix;
7917 row = MATRIX_ROW (matrix, w->cursor.vpos);
7918
7919 /* If row->y == top y of window display area, the window isn't tall
7920 enough to display a single line. There is nothing we can do
7921 about it. */
045dee35
GM
7922 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
7923 if (row->y == header_line_height)
5f5c8ee5
GM
7924 return;
7925
7926 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
7927 {
7928 int dy = row->height - row->visible_height;
7929 w->vscroll = 0;
7930 w->cursor.y += dy;
7931 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
7932 }
7933 else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
7934 {
7935 int dy = - (row->height - row->visible_height);
7936 w->vscroll = dy;
7937 w->cursor.y += dy;
7938 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
7939 }
7940
7941 /* When we change the cursor y-position of the selected window,
7942 change this_line_y as well so that the display optimization for
7943 the cursor line of the selected window in redisplay_internal uses
7944 the correct y-position. */
7945 if (w == XWINDOW (selected_window))
7946 this_line_y = w->cursor.y;
7947}
7948
7949
7950/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
7951 non-zero means only WINDOW is redisplayed in redisplay_internal.
7952 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
7953 in redisplay_window to bring a partially visible line into view in
7954 the case that only the cursor has moved.
7955
7956 Value is
7957
7958 1 if scrolling succeeded
7959
7960 0 if scrolling didn't find point.
7961
7962 -1 if new fonts have been loaded so that we must interrupt
7963 redisplay, adjust glyph matrices, and try again. */
7964
7965static int
7966try_scrolling (window, just_this_one_p, scroll_conservatively,
7967 scroll_step, temp_scroll_step)
7968 Lisp_Object window;
7969 int just_this_one_p;
7970 int scroll_conservatively, scroll_step;
7971 int temp_scroll_step;
7972{
7973 struct window *w = XWINDOW (window);
7974 struct frame *f = XFRAME (w->frame);
7975 struct text_pos scroll_margin_pos;
7976 struct text_pos pos;
7977 struct text_pos startp;
7978 struct it it;
7979 Lisp_Object window_end;
7980 int this_scroll_margin;
7981 int dy = 0;
7982 int scroll_max;
7983 int line_height, rc;
7984 int amount_to_scroll = 0;
7985 Lisp_Object aggressive;
7986 int height;
7987
7988#if GLYPH_DEBUG
7989 debug_method_add (w, "try_scrolling");
78614721 7990#endif
5f5c8ee5
GM
7991
7992 SET_TEXT_POS_FROM_MARKER (startp, w->start);
7993
7994 /* Compute scroll margin height in pixels. We scroll when point is
7995 within this distance from the top or bottom of the window. */
7996 if (scroll_margin > 0)
90adcf20 7997 {
5f5c8ee5
GM
7998 this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
7999 this_scroll_margin *= CANON_Y_UNIT (f);
8000 }
8001 else
8002 this_scroll_margin = 0;
8003
8004 /* Compute how much we should try to scroll maximally to bring point
8005 into view. */
8006 if (scroll_step)
8007 scroll_max = scroll_step;
8008 else if (scroll_conservatively)
8009 scroll_max = scroll_conservatively;
8010 else if (temp_scroll_step)
8011 scroll_max = temp_scroll_step;
8012 else if (NUMBERP (current_buffer->scroll_down_aggressively)
8013 || NUMBERP (current_buffer->scroll_up_aggressively))
8014 /* We're trying to scroll because of aggressive scrolling
8015 but no scroll_step is set. Choose an arbitrary one. Maybe
8016 there should be a variable for this. */
8017 scroll_max = 10;
8018 else
8019 scroll_max = 0;
8020 scroll_max *= CANON_Y_UNIT (f);
8021
8022 /* Decide whether we have to scroll down. Start at the window end
8023 and move this_scroll_margin up to find the position of the scroll
8024 margin. */
8025 window_end = Fwindow_end (window, Qt);
8026 CHARPOS (scroll_margin_pos) = XINT (window_end);
8027 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
8028 if (this_scroll_margin)
8029 {
8030 start_display (&it, w, scroll_margin_pos);
8031 move_it_vertically (&it, - this_scroll_margin);
8032 scroll_margin_pos = it.current.pos;
8033 }
8034
8035 if (PT >= CHARPOS (scroll_margin_pos))
8036 {
8037 int y0;
8038
8039 /* Point is in the scroll margin at the bottom of the window, or
8040 below. Compute a new window start that makes point visible. */
8041
8042 /* Compute the distance from the scroll margin to PT.
8043 Give up if the distance is greater than scroll_max. */
8044 start_display (&it, w, scroll_margin_pos);
8045 y0 = it.current_y;
8046 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8047 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8048 line_height = (it.max_ascent + it.max_descent
8049 ? it.max_ascent + it.max_descent
8050 : last_height);
8051 dy = it.current_y + line_height - y0;
8052 if (dy > scroll_max)
8053 return 0;
8054
8055 /* Move the window start down. If scrolling conservatively,
8056 move it just enough down to make point visible. If
8057 scroll_step is set, move it down by scroll_step. */
8058 start_display (&it, w, startp);
8059
8060 if (scroll_conservatively)
8061 amount_to_scroll = dy;
8062 else if (scroll_step || temp_scroll_step)
8063 amount_to_scroll = scroll_max;
8064 else
90adcf20 8065 {
5f5c8ee5
GM
8066 aggressive = current_buffer->scroll_down_aggressively;
8067 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8068 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8069 if (NUMBERP (aggressive))
8070 amount_to_scroll = XFLOATINT (aggressive) * height;
8071 }
a2725ab2 8072
5f5c8ee5
GM
8073 if (amount_to_scroll <= 0)
8074 return 0;
a2725ab2 8075
5f5c8ee5
GM
8076 move_it_vertically (&it, amount_to_scroll);
8077 startp = it.current.pos;
8078 }
8079 else
8080 {
8081 /* See if point is inside the scroll margin at the top of the
8082 window. */
8083 scroll_margin_pos = startp;
8084 if (this_scroll_margin)
8085 {
8086 start_display (&it, w, startp);
8087 move_it_vertically (&it, this_scroll_margin);
8088 scroll_margin_pos = it.current.pos;
8089 }
8090
8091 if (PT < CHARPOS (scroll_margin_pos))
8092 {
8093 /* Point is in the scroll margin at the top of the window or
8094 above what is displayed in the window. */
8095 int y0;
8096
8097 /* Compute the vertical distance from PT to the scroll
8098 margin position. Give up if distance is greater than
8099 scroll_max. */
8100 SET_TEXT_POS (pos, PT, PT_BYTE);
8101 start_display (&it, w, pos);
8102 y0 = it.current_y;
8103 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
8104 it.last_visible_y, -1,
8105 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8106 dy = it.current_y - y0;
8107 if (dy > scroll_max)
8108 return 0;
8109
8110 /* Compute new window start. */
8111 start_display (&it, w, startp);
8112
8113 if (scroll_conservatively)
8114 amount_to_scroll = dy;
8115 else if (scroll_step || temp_scroll_step)
8116 amount_to_scroll = scroll_max;
538f13d4 8117 else
5f5c8ee5
GM
8118 {
8119 aggressive = current_buffer->scroll_up_aggressively;
8120 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8121 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8122 if (NUMBERP (aggressive))
8123 amount_to_scroll = XFLOATINT (aggressive) * height;
8124 }
a2725ab2 8125
5f5c8ee5
GM
8126 if (amount_to_scroll <= 0)
8127 return 0;
8128
8129 move_it_vertically (&it, - amount_to_scroll);
8130 startp = it.current.pos;
90adcf20
RS
8131 }
8132 }
a2889657 8133
5f5c8ee5
GM
8134 /* Run window scroll functions. */
8135 startp = run_window_scroll_functions (window, startp);
90adcf20 8136
5f5c8ee5
GM
8137 /* Display the window. Give up if new fonts are loaded, or if point
8138 doesn't appear. */
8139 if (!try_window (window, startp))
8140 rc = -1;
8141 else if (w->cursor.vpos < 0)
8142 {
8143 clear_glyph_matrix (w->desired_matrix);
8144 rc = 0;
8145 }
8146 else
8147 {
8148 /* Maybe forget recorded base line for line number display. */
8149 if (!just_this_one_p
8150 || current_buffer->clip_changed
9142dd5b 8151 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5
GM
8152 w->base_line_number = Qnil;
8153
8154 /* If cursor ends up on a partially visible line, shift display
8155 lines up or down. */
8156 make_cursor_line_fully_visible (w);
8157 rc = 1;
8158 }
8159
8160 return rc;
a2889657
JB
8161}
8162
5f5c8ee5
GM
8163
8164/* Compute a suitable window start for window W if display of W starts
8165 on a continuation line. Value is non-zero if a new window start
8166 was computed.
8167
8168 The new window start will be computed, based on W's width, starting
8169 from the start of the continued line. It is the start of the
8170 screen line with the minimum distance from the old start W->start. */
8171
8172static int
8173compute_window_start_on_continuation_line (w)
8174 struct window *w;
1f1ff51d 8175{
5f5c8ee5
GM
8176 struct text_pos pos, start_pos;
8177 int window_start_changed_p = 0;
1f1ff51d 8178
5f5c8ee5 8179 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 8180
5f5c8ee5
GM
8181 /* If window start is on a continuation line... Window start may be
8182 < BEGV in case there's invisible text at the start of the
8183 buffer (M-x rmail, for example). */
8184 if (CHARPOS (start_pos) > BEGV
8185 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 8186 {
5f5c8ee5
GM
8187 struct it it;
8188 struct glyph_row *row;
8189
8190 /* Find the start of the continued line. This should be fast
8191 because scan_buffer is fast (newline cache). */
045dee35 8192 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
8193 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
8194 row, DEFAULT_FACE_ID);
8195 reseat_at_previous_visible_line_start (&it);
8196
8197 /* If the line start is "too far" away from the window start,
8198 say it takes too much time to compute a new window start. */
8199 if (CHARPOS (start_pos) - IT_CHARPOS (it)
8200 < XFASTINT (w->height) * XFASTINT (w->width))
8201 {
8202 int min_distance, distance;
8203
8204 /* Move forward by display lines to find the new window
8205 start. If window width was enlarged, the new start can
8206 be expected to be > the old start. If window width was
8207 decreased, the new window start will be < the old start.
8208 So, we're looking for the display line start with the
8209 minimum distance from the old window start. */
8210 pos = it.current.pos;
8211 min_distance = INFINITY;
8212 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
8213 distance < min_distance)
8214 {
8215 min_distance = distance;
8216 pos = it.current.pos;
8217 move_it_by_lines (&it, 1, 0);
8218 }
8219
8220 /* Set the window start there. */
8221 SET_MARKER_FROM_TEXT_POS (w->start, pos);
8222 window_start_changed_p = 1;
8223 }
1f1ff51d 8224 }
5f5c8ee5
GM
8225
8226 return window_start_changed_p;
1f1ff51d
KH
8227}
8228
5f5c8ee5
GM
8229
8230/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
8231 selected_window is redisplayed. */
90adcf20 8232
a2889657 8233static void
5f5c8ee5 8234redisplay_window (window, just_this_one_p)
a2889657 8235 Lisp_Object window;
5f5c8ee5 8236 int just_this_one_p;
a2889657 8237{
5f5c8ee5
GM
8238 struct window *w = XWINDOW (window);
8239 struct frame *f = XFRAME (w->frame);
8240 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 8241 struct buffer *old = current_buffer;
5f5c8ee5 8242 struct text_pos lpoint, opoint, startp;
e481f960 8243 int update_mode_line;
5f5c8ee5
GM
8244 int tem;
8245 struct it it;
8246 /* Record it now because it's overwritten. */
8247 int current_matrix_up_to_date_p = 0;
5ba50c51 8248 int really_switched_buffer = 0;
5f5c8ee5 8249 int temp_scroll_step = 0;
2e54982e 8250 int count = specpdl_ptr - specpdl;
a2889657 8251
5f5c8ee5
GM
8252 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8253 opoint = lpoint;
a2889657 8254
5f5c8ee5
GM
8255 /* W must be a leaf window here. */
8256 xassert (!NILP (w->buffer));
8257#if GLYPH_DEBUG
8258 *w->desired_matrix->method = 0;
8259#endif
2e54982e
RS
8260
8261 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
8262
8263 reconsider_clip_changes (w, buffer);
8264
5f5c8ee5
GM
8265 /* Has the mode line to be updated? */
8266 update_mode_line = (!NILP (w->update_mode_line)
8267 || update_mode_lines
8268 || buffer->clip_changed);
8de2d90b
JB
8269
8270 if (MINI_WINDOW_P (w))
8271 {
5f5c8ee5 8272 if (w == XWINDOW (echo_area_window)
c6e89d6c 8273 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
8274 {
8275 if (update_mode_line)
8276 /* We may have to update a tty frame's menu bar or a
e037b9ec 8277 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
8278 goto finish_menu_bars;
8279 else
8280 /* We've already displayed the echo area glyphs in this window. */
8281 goto finish_scroll_bars;
8282 }
73af359d 8283 else if (w != XWINDOW (minibuf_window))
8de2d90b 8284 {
5f5c8ee5
GM
8285 /* W is a mini-buffer window, but it's not the currently
8286 active one, so clear it. */
8287 int yb = window_text_bottom_y (w);
8288 struct glyph_row *row;
8289 int y;
8290
8291 for (y = 0, row = w->desired_matrix->rows;
8292 y < yb;
8293 y += row->height, ++row)
8294 blank_row (w, row, y);
88f22aff 8295 goto finish_scroll_bars;
8de2d90b
JB
8296 }
8297 }
a2889657 8298
5f5c8ee5
GM
8299 /* Otherwise set up data on this window; select its buffer and point
8300 value. */
e481f960 8301 if (update_mode_line)
5ba50c51 8302 {
5f5c8ee5
GM
8303 /* Really select the buffer, for the sake of buffer-local
8304 variables. */
5ba50c51
RS
8305 set_buffer_internal_1 (XBUFFER (w->buffer));
8306 really_switched_buffer = 1;
8307 }
e481f960
RS
8308 else
8309 set_buffer_temp (XBUFFER (w->buffer));
5f5c8ee5
GM
8310 SET_TEXT_POS (opoint, PT, PT_BYTE);
8311
8312 current_matrix_up_to_date_p
8313 = (!NILP (w->window_end_valid)
8314 && !current_buffer->clip_changed
8315 && XFASTINT (w->last_modified) >= MODIFF
8316 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 8317
5f5c8ee5
GM
8318 /* When windows_or_buffers_changed is non-zero, we can't rely on
8319 the window end being valid, so set it to nil there. */
8320 if (windows_or_buffers_changed)
8321 {
8322 /* If window starts on a continuation line, maybe adjust the
8323 window start in case the window's width changed. */
8324 if (XMARKER (w->start)->buffer == current_buffer)
8325 compute_window_start_on_continuation_line (w);
8326
8327 w->window_end_valid = Qnil;
8328 }
12adba34 8329
5f5c8ee5
GM
8330 /* Some sanity checks. */
8331 CHECK_WINDOW_END (w);
8332 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 8333 abort ();
5f5c8ee5 8334 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 8335 abort ();
a2889657 8336
28995e67
RS
8337 /* If %c is in mode line, update it if needed. */
8338 if (!NILP (w->column_number_displayed)
8339 /* This alternative quickly identifies a common case
8340 where no change is needed. */
8341 && !(PT == XFASTINT (w->last_point)
8850a573
RS
8342 && XFASTINT (w->last_modified) >= MODIFF
8343 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
8344 && XFASTINT (w->column_number_displayed) != current_column ())
8345 update_mode_line = 1;
8346
5f5c8ee5
GM
8347 /* Count number of windows showing the selected buffer. An indirect
8348 buffer counts as its base buffer. */
8349 if (!just_this_one_p)
42640f83
RS
8350 {
8351 struct buffer *current_base, *window_base;
8352 current_base = current_buffer;
8353 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
8354 if (current_base->base_buffer)
8355 current_base = current_base->base_buffer;
8356 if (window_base->base_buffer)
8357 window_base = window_base->base_buffer;
8358 if (current_base == window_base)
8359 buffer_shared++;
8360 }
a2889657 8361
5f5c8ee5
GM
8362 /* Point refers normally to the selected window. For any other
8363 window, set up appropriate value. */
a2889657
JB
8364 if (!EQ (window, selected_window))
8365 {
12adba34
RS
8366 int new_pt = XMARKER (w->pointm)->charpos;
8367 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 8368 if (new_pt < BEGV)
a2889657 8369 {
f67a0f51 8370 new_pt = BEGV;
12adba34
RS
8371 new_pt_byte = BEGV_BYTE;
8372 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 8373 }
f67a0f51 8374 else if (new_pt > (ZV - 1))
a2889657 8375 {
f67a0f51 8376 new_pt = ZV;
12adba34
RS
8377 new_pt_byte = ZV_BYTE;
8378 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 8379 }
5f5c8ee5 8380
f67a0f51 8381 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 8382 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
8383 }
8384
f4faa47c 8385 /* If any of the character widths specified in the display table
5f5c8ee5
GM
8386 have changed, invalidate the width run cache. It's true that
8387 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
8388 redisplay goes (non-fatally) haywire when the display table is
8389 changed, so why should we worry about doing any better? */
8390 if (current_buffer->width_run_cache)
8391 {
f908610f 8392 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
8393
8394 if (! disptab_matches_widthtab (disptab,
8395 XVECTOR (current_buffer->width_table)))
8396 {
8397 invalidate_region_cache (current_buffer,
8398 current_buffer->width_run_cache,
8399 BEG, Z);
8400 recompute_width_table (current_buffer, disptab);
8401 }
8402 }
8403
a2889657 8404 /* If window-start is screwed up, choose a new one. */
a2889657
JB
8405 if (XMARKER (w->start)->buffer != current_buffer)
8406 goto recenter;
8407
5f5c8ee5 8408 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 8409
cf0df6ab
RS
8410 /* If someone specified a new starting point but did not insist,
8411 check whether it can be used. */
5f5c8ee5 8412 if (!NILP (w->optional_new_start))
cf0df6ab
RS
8413 {
8414 w->optional_new_start = Qnil;
5f5c8ee5
GM
8415 /* This takes a mini-buffer prompt into account. */
8416 start_display (&it, w, startp);
8417 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8418 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8419 if (IT_CHARPOS (it) == PT)
cf0df6ab
RS
8420 w->force_start = Qt;
8421 }
8422
8de2d90b 8423 /* Handle case where place to start displaying has been specified,
aa6d10fa 8424 unless the specified location is outside the accessible range. */
9472f927
GM
8425 if (!NILP (w->force_start)
8426 || w->frozen_window_start_p)
a2889657 8427 {
e63574d7 8428 w->force_start = Qnil;
5f5c8ee5 8429 w->vscroll = 0;
b5174a51 8430 w->window_end_valid = Qnil;
5f5c8ee5
GM
8431
8432 /* Forget any recorded base line for line number display. */
8433 if (!current_matrix_up_to_date_p
8434 || current_buffer->clip_changed)
8435 w->base_line_number = Qnil;
8436
75c43375
RS
8437 /* Redisplay the mode line. Select the buffer properly for that.
8438 Also, run the hook window-scroll-functions
8439 because we have scrolled. */
e63574d7
RS
8440 /* Note, we do this after clearing force_start because
8441 if there's an error, it is better to forget about force_start
8442 than to get into an infinite loop calling the hook functions
8443 and having them get more errors. */
75c43375
RS
8444 if (!update_mode_line
8445 || ! NILP (Vwindow_scroll_functions))
e481f960 8446 {
5ba50c51
RS
8447 if (!really_switched_buffer)
8448 {
8449 set_buffer_temp (old);
8450 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8451 really_switched_buffer = 1;
5ba50c51 8452 }
5f5c8ee5 8453
e481f960
RS
8454 update_mode_line = 1;
8455 w->update_mode_line = Qt;
5f5c8ee5 8456 startp = run_window_scroll_functions (window, startp);
e481f960 8457 }
5f5c8ee5 8458
c2213350 8459 XSETFASTINT (w->last_modified, 0);
8850a573 8460 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5
GM
8461 if (CHARPOS (startp) < BEGV)
8462 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
8463 else if (CHARPOS (startp) > ZV)
8464 SET_TEXT_POS (startp, ZV, ZV_BYTE);
8465
8466 /* Redisplay, then check if cursor has been set during the
8467 redisplay. Give up if new fonts were loaded. */
8468 if (!try_window (window, startp))
8469 {
8470 w->force_start = Qt;
8471 clear_glyph_matrix (w->desired_matrix);
8472 goto restore_buffers;
8473 }
8474
9472f927 8475 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5
GM
8476 {
8477 /* If point does not appear, or on a line that is not fully
8478 visible, move point so it does appear. The desired
8479 matrix has been built above, so we can use it. */
8480 int height = window_box_height (w) / 2;
8481 struct glyph_row *row = MATRIX_ROW (w->desired_matrix, 0);
8482
8483 while (row->y < height)
8484 ++row;
8485
8486 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
8487 MATRIX_ROW_START_BYTEPOS (row));
8488
90adcf20 8489 if (w != XWINDOW (selected_window))
12adba34 8490 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
8491 else if (current_buffer == old)
8492 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8493
8494 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
8495
8496 /* If we are highlighting the region, then we just changed
8497 the region, so redisplay to show it. */
df0b5ea1
RS
8498 if (!NILP (Vtransient_mark_mode)
8499 && !NILP (current_buffer->mark_active))
6f27fa9b 8500 {
5f5c8ee5
GM
8501 clear_glyph_matrix (w->desired_matrix);
8502 if (!try_window (window, startp))
8503 goto restore_buffers;
6f27fa9b 8504 }
a2889657 8505 }
5f5c8ee5
GM
8506
8507 make_cursor_line_fully_visible (w);
8508#if GLYPH_DEBUG
8509 debug_method_add (w, "forced window start");
8510#endif
a2889657
JB
8511 goto done;
8512 }
8513
5f5c8ee5
GM
8514 /* Handle case where text has not changed, only point, and it has
8515 not moved off the frame. */
8516 if (current_matrix_up_to_date_p
8517 /* Point may be in this window. */
8518 && PT >= CHARPOS (startp)
8519 /* If we don't check this, we are called to move the cursor in a
8520 horizontally split window with a current matrix that doesn't
8521 fit the display. */
8522 && !windows_or_buffers_changed
8523 /* Selective display hasn't changed. */
8524 && !current_buffer->clip_changed
b1aa6cb3
RS
8525 /* If force-mode-line-update was called, really redisplay;
8526 that's how redisplay is forced after e.g. changing
8527 buffer-invisibility-spec. */
632ab665 8528 && NILP (w->update_mode_line)
5f5c8ee5
GM
8529 /* Can't use this case if highlighting a region. When a
8530 region exists, cursor movement has to do more than just
8531 set the cursor. */
8532 && !(!NILP (Vtransient_mark_mode)
8533 && !NILP (current_buffer->mark_active))
bd66d1ba 8534 && NILP (w->region_showing)
8f897821 8535 && NILP (Vshow_trailing_whitespace)
5f5c8ee5
GM
8536 /* Right after splitting windows, last_point may be nil. */
8537 && INTEGERP (w->last_point)
8538 /* This code is not used for mini-buffer for the sake of the case
8539 of redisplaying to replace an echo area message; since in
8540 that case the mini-buffer contents per se are usually
8541 unchanged. This code is of no real use in the mini-buffer
8542 since the handling of this_line_start_pos, etc., in redisplay
8543 handles the same cases. */
d45de95b 8544 && !EQ (window, minibuf_window)
5f5c8ee5
GM
8545 /* When splitting windows or for new windows, it happens that
8546 redisplay is called with a nil window_end_vpos or one being
8547 larger than the window. This should really be fixed in
8548 window.c. I don't have this on my list, now, so we do
8549 approximately the same as the old redisplay code. --gerd. */
8550 && INTEGERP (w->window_end_vpos)
8551 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
8552 && (FRAME_WINDOW_P (f)
8553 || !MARKERP (Voverlay_arrow_position)
377dbd97 8554 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
a2889657 8555 {
5f5c8ee5
GM
8556 int this_scroll_margin;
8557 struct glyph_row *row;
8558 int scroll_p;
a2889657 8559
5f5c8ee5
GM
8560#if GLYPH_DEBUG
8561 debug_method_add (w, "cursor movement");
8562#endif
9afd2168 8563
5f5c8ee5
GM
8564 /* Scroll if point within this distance from the top or bottom
8565 of the window. This is a pixel value. */
8566 this_scroll_margin = max (0, scroll_margin);
8567 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
8568 this_scroll_margin *= CANON_Y_UNIT (f);
8569
8570 /* Start with the row the cursor was displayed during the last
8571 not paused redisplay. Give up if that row is not valid. */
8572 if (w->last_cursor.vpos >= w->current_matrix->nrows)
8573 goto try_to_scroll;
8574 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
8575 if (row->mode_line_p)
8576 ++row;
8577 if (!row->enabled_p)
8578 goto try_to_scroll;
8579
8580 scroll_p = 0;
8581 if (PT > XFASTINT (w->last_point))
8582 {
8583 /* Point has moved forward. */
8584 int last_y = window_text_bottom_y (w) - this_scroll_margin;
8585
8586 while ((MATRIX_ROW_END_CHARPOS (row) < PT
8587 /* The end position of a row equals the start
8588 position of the next row. If PT is there, we
8589 would rather display it in the next line, except
8590 when this line ends in ZV. */
8591 || (MATRIX_ROW_END_CHARPOS (row) == PT
8592 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
8593 || !row->ends_at_zv_p)))
8594 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
8595 {
8596 xassert (row->enabled_p);
8597 ++row;
8598 }
9afd2168 8599
5f5c8ee5
GM
8600 /* If within the scroll margin, scroll. Note that
8601 MATRIX_ROW_BOTTOM_Y gives the pixel position at which the
8602 next line would be drawn, and that this_scroll_margin can
8603 be zero. */
8604 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
8605 || PT > MATRIX_ROW_END_CHARPOS (row)
8606 /* Line is completely visible last line in window and PT
8607 is to be set in the next line. */
8608 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
8609 && PT == MATRIX_ROW_END_CHARPOS (row)
8610 && !row->ends_at_zv_p
8611 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
8612 scroll_p = 1;
8613 }
8614 else if (PT < XFASTINT (w->last_point))
a2889657 8615 {
5f5c8ee5
GM
8616 /* Cursor has to be moved backward. Note that PT >=
8617 CHARPOS (startp) because of the outer if-statement. */
8618 while (!row->mode_line_p
8619 && (MATRIX_ROW_START_CHARPOS (row) > PT
8620 || (MATRIX_ROW_START_CHARPOS (row) == PT
8621 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
8622 && (row->y > this_scroll_margin
8623 || CHARPOS (startp) == BEGV))
a2889657 8624 {
5f5c8ee5
GM
8625 xassert (row->enabled_p);
8626 --row;
a2889657 8627 }
abb4c08f 8628
5f5c8ee5
GM
8629 /* Consider the following case: Window starts at BEGV, there
8630 is invisible, intangible text at BEGV, so that display
8631 starts at some point START > BEGV. It can happen that
8632 we are called with PT somewhere between BEGV and START.
8633 Try to handle that case. */
8634 if (row < w->current_matrix->rows
8635 || row->mode_line_p)
8636 {
8637 row = w->current_matrix->rows;
8638 if (row->mode_line_p)
8639 ++row;
8640 }
8641
8642 /* Due to newlines in overlay strings, we may have to skip
8643 forward over overlay strings. */
8644 while (MATRIX_ROW_END_CHARPOS (row) == PT
8645 && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row)
8646 && !row->ends_at_zv_p)
8647 ++row;
8648
8649 /* If within the scroll margin, scroll. */
8650 if (row->y < this_scroll_margin
8651 && CHARPOS (startp) != BEGV)
8652 scroll_p = 1;
8653 }
8654
8655 /* if PT is not in the glyph row, give up. */
8656 if (PT < MATRIX_ROW_START_CHARPOS (row)
8657 || PT > MATRIX_ROW_END_CHARPOS (row))
8658 goto try_to_scroll;
8659
8660 /* If we end up in a partially visible line, let's make it fully
8661 visible. This can be done most easily by using the existing
8662 scrolling code. */
8663 if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
8664 {
8665 temp_scroll_step = 1;
8666 goto try_to_scroll;
a2889657 8667 }
5f5c8ee5
GM
8668 else if (scroll_p)
8669 goto try_to_scroll;
8670
8671 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
8672 goto done;
a2889657 8673 }
5f5c8ee5 8674
a2889657
JB
8675 /* If current starting point was originally the beginning of a line
8676 but no longer is, find a new starting point. */
265a9e55 8677 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
8678 && !(CHARPOS (startp) <= BEGV
8679 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 8680 {
5f5c8ee5
GM
8681#if GLYPH_DEBUG
8682 debug_method_add (w, "recenter 1");
8683#endif
a2889657
JB
8684 goto recenter;
8685 }
5f5c8ee5
GM
8686
8687 /* Try scrolling with try_window_id. */
9142dd5b
GM
8688 else if (/* Windows and buffers haven't changed. */
8689 !windows_or_buffers_changed
5f5c8ee5
GM
8690 /* Window must be either use window-based redisplay or
8691 be full width. */
8692 && (FRAME_WINDOW_P (f)
c59c668a 8693 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)))
5f5c8ee5
GM
8694 && !MINI_WINDOW_P (w)
8695 /* Point is not known NOT to appear in window. */
8696 && PT >= CHARPOS (startp)
a2889657 8697 && XFASTINT (w->last_modified)
5f5c8ee5
GM
8698 /* Window is not hscrolled. */
8699 && XFASTINT (w->hscroll) == 0
8700 /* Selective display has not changed. */
8701 && !current_buffer->clip_changed
8702 /* Current matrix is up to date. */
8703 && !NILP (w->window_end_valid)
8704 /* Can't use this case if highlighting a region because
8705 a cursor movement will do more than just set the cursor. */
bd66d1ba
RS
8706 && !(!NILP (Vtransient_mark_mode)
8707 && !NILP (current_buffer->mark_active))
8708 && NILP (w->region_showing)
8f897821 8709 && NILP (Vshow_trailing_whitespace)
5f5c8ee5 8710 /* Overlay arrow position and string not changed. */
d45de95b 8711 && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
a2889657 8712 && EQ (last_arrow_string, Voverlay_arrow_string)
5f5c8ee5
GM
8713 /* Value is > 0 if update has been done, it is -1 if we
8714 know that the same window start will not work. It is 0
8715 if unsuccessful for some other reason. */
8716 && (tem = try_window_id (w)) != 0)
a2889657 8717 {
5f5c8ee5
GM
8718#if GLYPH_DEBUG
8719 debug_method_add (w, "try_window_id");
8720#endif
8721
8722 if (fonts_changed_p)
8723 goto restore_buffers;
a2889657
JB
8724 if (tem > 0)
8725 goto done;
5f5c8ee5
GM
8726 /* Otherwise try_window_id has returned -1 which means that we
8727 don't want the alternative below this comment to execute. */
a2889657 8728 }
5f5c8ee5
GM
8729 else if (CHARPOS (startp) >= BEGV
8730 && CHARPOS (startp) <= ZV
8731 && PT >= CHARPOS (startp)
8732 && (CHARPOS (startp) < ZV
e9874cee 8733 /* Avoid starting at end of buffer. */
5f5c8ee5 8734 || CHARPOS (startp) == BEGV
8850a573
RS
8735 || (XFASTINT (w->last_modified) >= MODIFF
8736 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 8737 {
5f5c8ee5
GM
8738#if GLYPH_DEBUG
8739 debug_method_add (w, "same window start");
8740#endif
8741
8742 /* Try to redisplay starting at same place as before.
8743 If point has not moved off frame, accept the results. */
8744 if (!current_matrix_up_to_date_p
8745 /* Don't use try_window_reusing_current_matrix in this case
8746 because it can have changed the buffer. */
8747 || !NILP (Vwindow_scroll_functions)
8748 || MINI_WINDOW_P (w)
8749 || !try_window_reusing_current_matrix (w))
8750 {
8751 IF_DEBUG (debug_method_add (w, "1"));
8752 try_window (window, startp);
8753 }
8754
8755 if (fonts_changed_p)
8756 goto restore_buffers;
8757
8758 if (w->cursor.vpos >= 0)
aa6d10fa 8759 {
5f5c8ee5
GM
8760 if (!just_this_one_p
8761 || current_buffer->clip_changed
9142dd5b 8762 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
8763 /* Forget any recorded base line for line number display. */
8764 w->base_line_number = Qnil;
5f5c8ee5
GM
8765
8766 make_cursor_line_fully_visible (w);
aa6d10fa
RS
8767 goto done;
8768 }
a2889657 8769 else
5f5c8ee5 8770 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
8771 }
8772
5f5c8ee5
GM
8773 try_to_scroll:
8774
c2213350 8775 XSETFASTINT (w->last_modified, 0);
8850a573 8776 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5 8777
e481f960
RS
8778 /* Redisplay the mode line. Select the buffer properly for that. */
8779 if (!update_mode_line)
8780 {
5ba50c51
RS
8781 if (!really_switched_buffer)
8782 {
8783 set_buffer_temp (old);
8784 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8785 really_switched_buffer = 1;
5ba50c51 8786 }
e481f960
RS
8787 update_mode_line = 1;
8788 w->update_mode_line = Qt;
8789 }
a2889657 8790
5f5c8ee5
GM
8791 /* Try to scroll by specified few lines. */
8792 if ((scroll_conservatively
8793 || scroll_step
8794 || temp_scroll_step
8795 || NUMBERP (current_buffer->scroll_up_aggressively)
8796 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 8797 && !current_buffer->clip_changed
5f5c8ee5
GM
8798 && CHARPOS (startp) >= BEGV
8799 && CHARPOS (startp) <= ZV)
0789adb2 8800 {
5f5c8ee5
GM
8801 /* The function returns -1 if new fonts were loaded, 1 if
8802 successful, 0 if not successful. */
8803 int rc = try_scrolling (window, just_this_one_p,
8804 scroll_conservatively,
8805 scroll_step,
8806 temp_scroll_step);
8807 if (rc > 0)
8808 goto done;
8809 else if (rc < 0)
8810 goto restore_buffers;
8811 }
f9c8af06 8812
5f5c8ee5 8813 /* Finally, just choose place to start which centers point */
5936754e 8814
5f5c8ee5 8815 recenter:
44173109 8816
5f5c8ee5
GM
8817#if GLYPH_DEBUG
8818 debug_method_add (w, "recenter");
8819#endif
0789adb2 8820
5f5c8ee5 8821 /* w->vscroll = 0; */
0789adb2 8822
5f5c8ee5
GM
8823 /* Forget any previously recorded base line for line number display. */
8824 if (!current_matrix_up_to_date_p
8825 || current_buffer->clip_changed)
8826 w->base_line_number = Qnil;
8827
8828 /* Move backward half the height of the window. */
8829 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
8830 it.current_y = it.last_visible_y;
8831 move_it_vertically_backward (&it, it.last_visible_y / 2);
8832 xassert (IT_CHARPOS (it) >= BEGV);
8833
8834 /* The function move_it_vertically_backward may move over more
8835 than the specified y-distance. If it->w is small, e.g. a
8836 mini-buffer window, we may end up in front of the window's
8837 display area. Start displaying at the start of the line
8838 containing PT in this case. */
8839 if (it.current_y <= 0)
8840 {
8841 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
8842 move_it_vertically (&it, 0);
8843 xassert (IT_CHARPOS (it) <= PT);
8844 it.current_y = 0;
0789adb2
RS
8845 }
8846
5f5c8ee5
GM
8847 it.current_x = it.hpos = 0;
8848
8849 /* Set startp here explicitly in case that helps avoid an infinite loop
8850 in case the window-scroll-functions functions get errors. */
8851 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
8852
8853 /* Run scroll hooks. */
8854 startp = run_window_scroll_functions (window, it.current.pos);
8855
8856 /* Redisplay the window. */
8857 if (!current_matrix_up_to_date_p
8858 || windows_or_buffers_changed
8859 /* Don't use try_window_reusing_current_matrix in this case
8860 because it can have changed the buffer. */
8861 || !NILP (Vwindow_scroll_functions)
8862 || !just_this_one_p
8863 || MINI_WINDOW_P (w)
8864 || !try_window_reusing_current_matrix (w))
8865 try_window (window, startp);
8866
8867 /* If new fonts have been loaded (due to fontsets), give up. We
8868 have to start a new redisplay since we need to re-adjust glyph
8869 matrices. */
8870 if (fonts_changed_p)
8871 goto restore_buffers;
8872
8873 /* If cursor did not appear assume that the middle of the window is
8874 in the first line of the window. Do it again with the next line.
8875 (Imagine a window of height 100, displaying two lines of height
8876 60. Moving back 50 from it->last_visible_y will end in the first
8877 line.) */
8878 if (w->cursor.vpos < 0)
a2889657 8879 {
5f5c8ee5
GM
8880 if (!NILP (w->window_end_valid)
8881 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 8882 {
5f5c8ee5
GM
8883 clear_glyph_matrix (w->desired_matrix);
8884 move_it_by_lines (&it, 1, 0);
8885 try_window (window, it.current.pos);
a2889657 8886 }
5f5c8ee5 8887 else if (PT < IT_CHARPOS (it))
a2889657 8888 {
5f5c8ee5
GM
8889 clear_glyph_matrix (w->desired_matrix);
8890 move_it_by_lines (&it, -1, 0);
8891 try_window (window, it.current.pos);
8892 }
8893 else
8894 {
8895 /* Not much we can do about it. */
a2889657 8896 }
a2889657 8897 }
010494d0 8898
5f5c8ee5
GM
8899 /* Consider the following case: Window starts at BEGV, there is
8900 invisible, intangible text at BEGV, so that display starts at
8901 some point START > BEGV. It can happen that we are called with
8902 PT somewhere between BEGV and START. Try to handle that case. */
8903 if (w->cursor.vpos < 0)
835766b6 8904 {
5f5c8ee5
GM
8905 struct glyph_row *row = w->current_matrix->rows;
8906 if (row->mode_line_p)
8907 ++row;
8908 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 8909 }
5f5c8ee5
GM
8910
8911 make_cursor_line_fully_visible (w);
b5174a51 8912
5f5c8ee5
GM
8913 SET_TEXT_POS_FROM_MARKER (startp, w->start);
8914 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
8915 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
8916 ? Qt : Qnil);
a2889657 8917
5f5c8ee5 8918 done:
a2889657 8919
5f5c8ee5 8920 /* Display the mode line, if we must. */
e481f960 8921 if ((update_mode_line
aa6d10fa 8922 /* If window not full width, must redo its mode line
5f5c8ee5
GM
8923 if (a) the window to its side is being redone and
8924 (b) we do a frame-based redisplay. This is a consequence
8925 of how inverted lines are drawn in frame-based redisplay. */
8926 || (!just_this_one_p
8927 && !FRAME_WINDOW_P (f)
8928 && !WINDOW_FULL_WIDTH_P (w))
8929 /* Line number to display. */
155ef550 8930 || INTEGERP (w->base_line_pos)
5f5c8ee5 8931 /* Column number is displayed and different from the one displayed. */
155ef550
KH
8932 || (!NILP (w->column_number_displayed)
8933 && XFASTINT (w->column_number_displayed) != current_column ()))
5f5c8ee5
GM
8934 /* This means that the window has a mode line. */
8935 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 8936 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 8937 {
5f5c8ee5
GM
8938 display_mode_lines (w);
8939
8940 /* If mode line height has changed, arrange for a thorough
8941 immediate redisplay using the correct mode line height. */
8942 if (WINDOW_WANTS_MODELINE_P (w)
8943 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 8944 {
5f5c8ee5
GM
8945 fonts_changed_p = 1;
8946 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
8947 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 8948 }
5f5c8ee5
GM
8949
8950 /* If top line height has changed, arrange for a thorough
8951 immediate redisplay using the correct mode line height. */
045dee35
GM
8952 if (WINDOW_WANTS_HEADER_LINE_P (w)
8953 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
8954 {
8955 fonts_changed_p = 1;
045dee35
GM
8956 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
8957 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
8958 }
8959
8960 if (fonts_changed_p)
8961 goto restore_buffers;
5ba50c51 8962 }
5f5c8ee5
GM
8963
8964 if (!line_number_displayed
8965 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
8966 {
8967 w->base_line_pos = Qnil;
8968 w->base_line_number = Qnil;
8969 }
a2889657 8970
5f5c8ee5
GM
8971 finish_menu_bars:
8972
7ce2c095 8973 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 8974 if (update_mode_line
5f5c8ee5
GM
8975 && EQ (FRAME_SELECTED_WINDOW (f), window))
8976 {
8977 int redisplay_menu_p = 0;
8978
8979 if (FRAME_WINDOW_P (f))
8980 {
dc937613 8981#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
5f5c8ee5 8982 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 8983#else
5f5c8ee5 8984 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 8985#endif
5f5c8ee5
GM
8986 }
8987 else
8988 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
8989
8990 if (redisplay_menu_p)
8991 display_menu_bar (w);
8992
8993#ifdef HAVE_WINDOW_SYSTEM
e037b9ec
GM
8994 if (WINDOWP (f->tool_bar_window)
8995 && (FRAME_TOOL_BAR_LINES (f) > 0
8996 || auto_resize_tool_bars_p))
8997 redisplay_tool_bar (f);
5f5c8ee5
GM
8998#endif
8999 }
7ce2c095 9000
88f22aff 9001 finish_scroll_bars:
5f5c8ee5 9002
88f22aff 9003 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 9004 {
b1d1124b 9005 int start, end, whole;
30c566e4 9006
b1d1124b 9007 /* Calculate the start and end positions for the current window.
3505ea70
JB
9008 At some point, it would be nice to choose between scrollbars
9009 which reflect the whole buffer size, with special markers
9010 indicating narrowing, and scrollbars which reflect only the
9011 visible region.
9012
5f5c8ee5 9013 Note that mini-buffers sometimes aren't displaying any text. */
c6e89d6c 9014 if (!MINI_WINDOW_P (w)
5f5c8ee5 9015 || (w == XWINDOW (minibuf_window)
c6e89d6c 9016 && NILP (echo_area_buffer[0])))
b1d1124b 9017 {
8a9311d7 9018 whole = ZV - BEGV;
4d641a15 9019 start = marker_position (w->start) - BEGV;
b1d1124b
JB
9020 /* I don't think this is guaranteed to be right. For the
9021 moment, we'll pretend it is. */
5f5c8ee5 9022 end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
3505ea70 9023
5f5c8ee5
GM
9024 if (end < start)
9025 end = start;
9026 if (whole < (end - start))
9027 whole = end - start;
b1d1124b
JB
9028 }
9029 else
9030 start = end = whole = 0;
30c566e4 9031
88f22aff 9032 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 9033 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 9034
5f5c8ee5
GM
9035 /* Note that we actually used the scroll bar attached to this
9036 window, so it shouldn't be deleted at the end of redisplay. */
88f22aff 9037 (*redeem_scroll_bar_hook) (w);
30c566e4 9038 }
b1d1124b 9039
5f5c8ee5
GM
9040 restore_buffers:
9041
9042 /* Restore current_buffer and value of point in it. */
9043 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
5ba50c51 9044 if (really_switched_buffer)
f72df6ac 9045 set_buffer_internal_1 (old);
e481f960
RS
9046 else
9047 set_buffer_temp (old);
5f5c8ee5 9048 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
9049
9050 unbind_to (count, Qnil);
a2889657 9051}
a2889657 9052
5f5c8ee5
GM
9053
9054/* Build the complete desired matrix of WINDOW with a window start
9055 buffer position POS. Value is non-zero if successful. It is zero
9056 if fonts were loaded during redisplay which makes re-adjusting
9057 glyph matrices necessary. */
9058
9059int
a2889657
JB
9060try_window (window, pos)
9061 Lisp_Object window;
5f5c8ee5
GM
9062 struct text_pos pos;
9063{
9064 struct window *w = XWINDOW (window);
9065 struct it it;
9066 struct glyph_row *last_text_row = NULL;
9cbab4ff 9067
5f5c8ee5
GM
9068 /* Make POS the new window start. */
9069 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 9070
5f5c8ee5
GM
9071 /* Mark cursor position as unknown. No overlay arrow seen. */
9072 w->cursor.vpos = -1;
a2889657 9073 overlay_arrow_seen = 0;
642eefc6 9074
5f5c8ee5
GM
9075 /* Initialize iterator and info to start at POS. */
9076 start_display (&it, w, pos);
a2889657 9077
5f5c8ee5
GM
9078 /* Display all lines of W. */
9079 while (it.current_y < it.last_visible_y)
9080 {
9081 if (display_line (&it))
9082 last_text_row = it.glyph_row - 1;
9083 if (fonts_changed_p)
9084 return 0;
9085 }
a2889657 9086
5f5c8ee5
GM
9087 /* If bottom moved off end of frame, change mode line percentage. */
9088 if (XFASTINT (w->window_end_pos) <= 0
9089 && Z != IT_CHARPOS (it))
a2889657
JB
9090 w->update_mode_line = Qt;
9091
5f5c8ee5
GM
9092 /* Set window_end_pos to the offset of the last character displayed
9093 on the window from the end of current_buffer. Set
9094 window_end_vpos to its row number. */
9095 if (last_text_row)
9096 {
9097 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
9098 w->window_end_bytepos
9099 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9100 XSETFASTINT (w->window_end_pos,
9101 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9102 XSETFASTINT (w->window_end_vpos,
9103 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9104 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
9105 ->displays_text_p);
9106 }
9107 else
9108 {
9109 w->window_end_bytepos = 0;
9110 XSETFASTINT (w->window_end_pos, 0);
9111 XSETFASTINT (w->window_end_vpos, 0);
9112 }
9113
a2889657
JB
9114 /* But that is not valid info until redisplay finishes. */
9115 w->window_end_valid = Qnil;
5f5c8ee5 9116 return 1;
a2889657 9117}
5f5c8ee5
GM
9118
9119
a2889657 9120\f
5f5c8ee5
GM
9121/************************************************************************
9122 Window redisplay reusing current matrix when buffer has not changed
9123 ************************************************************************/
9124
9125/* Try redisplay of window W showing an unchanged buffer with a
9126 different window start than the last time it was displayed by
9127 reusing its current matrix. Value is non-zero if successful.
9128 W->start is the new window start. */
a2889657
JB
9129
9130static int
5f5c8ee5
GM
9131try_window_reusing_current_matrix (w)
9132 struct window *w;
a2889657 9133{
5f5c8ee5
GM
9134 struct frame *f = XFRAME (w->frame);
9135 struct glyph_row *row, *bottom_row;
9136 struct it it;
9137 struct run run;
9138 struct text_pos start, new_start;
9139 int nrows_scrolled, i;
9140 struct glyph_row *last_text_row;
9141 struct glyph_row *last_reused_text_row;
9142 struct glyph_row *start_row;
9143 int start_vpos, min_y, max_y;
9144
9145 /* Right now this function doesn't handle terminal frames. */
9146 if (!FRAME_WINDOW_P (f))
9147 return 0;
a2889657 9148
5f5c8ee5
GM
9149 /* Can't do this if region may have changed. */
9150 if ((!NILP (Vtransient_mark_mode)
9151 && !NILP (current_buffer->mark_active))
8f897821
GM
9152 || !NILP (w->region_showing)
9153 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 9154 return 0;
a2889657 9155
5f5c8ee5 9156 /* If top-line visibility has changed, give up. */
045dee35
GM
9157 if (WINDOW_WANTS_HEADER_LINE_P (w)
9158 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
9159 return 0;
9160
9161 /* Give up if old or new display is scrolled vertically. We could
9162 make this function handle this, but right now it doesn't. */
9163 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9164 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
9165 return 0;
9166
9167 /* The variable new_start now holds the new window start. The old
9168 start `start' can be determined from the current matrix. */
9169 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
9170 start = start_row->start.pos;
9171 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 9172
5f5c8ee5
GM
9173 /* Clear the desired matrix for the display below. */
9174 clear_glyph_matrix (w->desired_matrix);
9175
9176 if (CHARPOS (new_start) <= CHARPOS (start))
9177 {
9178 int first_row_y;
9179
9180 IF_DEBUG (debug_method_add (w, "twu1"));
9181
9182 /* Display up to a row that can be reused. The variable
9183 last_text_row is set to the last row displayed that displays
9184 text. */
9185 start_display (&it, w, new_start);
9186 first_row_y = it.current_y;
9187 w->cursor.vpos = -1;
9188 last_text_row = last_reused_text_row = NULL;
9189 while (it.current_y < it.last_visible_y
9190 && IT_CHARPOS (it) < CHARPOS (start)
9191 && !fonts_changed_p)
9192 if (display_line (&it))
9193 last_text_row = it.glyph_row - 1;
9194
9195 /* A value of current_y < last_visible_y means that we stopped
9196 at the previous window start, which in turn means that we
9197 have at least one reusable row. */
9198 if (it.current_y < it.last_visible_y)
a2889657 9199 {
5f5c8ee5
GM
9200 nrows_scrolled = it.vpos;
9201
9202 /* Find PT if not already found in the lines displayed. */
9203 if (w->cursor.vpos < 0)
a2889657 9204 {
5f5c8ee5
GM
9205 int dy = it.current_y - first_row_y;
9206
9207 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9208 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9209 {
9210 if (PT >= MATRIX_ROW_START_CHARPOS (row)
9211 && PT < MATRIX_ROW_END_CHARPOS (row))
9212 {
9213 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
9214 dy, nrows_scrolled);
9215 break;
9216 }
9217
9218 if (MATRIX_ROW_BOTTOM_Y (row) + dy >= it.last_visible_y)
9219 break;
9220
9221 ++row;
9222 }
9223
9224 /* Give up if point was not found. This shouldn't
9225 happen often; not more often than with try_window
9226 itself. */
9227 if (w->cursor.vpos < 0)
9228 {
9229 clear_glyph_matrix (w->desired_matrix);
9230 return 0;
9231 }
a2889657 9232 }
5f5c8ee5
GM
9233
9234 /* Scroll the display. Do it before the current matrix is
9235 changed. The problem here is that update has not yet
9236 run, i.e. part of the current matrix is not up to date.
9237 scroll_run_hook will clear the cursor, and use the
9238 current matrix to get the height of the row the cursor is
9239 in. */
9240 run.current_y = first_row_y;
9241 run.desired_y = it.current_y;
9242 run.height = it.last_visible_y - it.current_y;
9243 if (run.height > 0)
a2889657 9244 {
5f5c8ee5
GM
9245 update_begin (f);
9246 rif->update_window_begin_hook (w);
9247 rif->scroll_run_hook (w, &run);
9248 rif->update_window_end_hook (w, 0);
9249 update_end (f);
a2889657 9250 }
5f5c8ee5
GM
9251
9252 /* Shift current matrix down by nrows_scrolled lines. */
9253 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9254 rotate_matrix (w->current_matrix,
9255 start_vpos,
9256 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
9257 nrows_scrolled);
9258
9259 /* Disable lines not reused. */
9260 for (i = 0; i < it.vpos; ++i)
9261 MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
9262
9263 /* Re-compute Y positions. */
9264 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix) + nrows_scrolled;
045dee35 9265 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9266 max_y = it.last_visible_y;
9267 while (row < bottom_row)
d2f84654 9268 {
5f5c8ee5
GM
9269 row->y = it.current_y;
9270
9271 if (row->y < min_y)
9272 row->visible_height = row->height - (min_y - row->y);
9273 else if (row->y + row->height > max_y)
9274 row->visible_height
9275 = row->height - (row->y + row->height - max_y);
9276 else
9277 row->visible_height = row->height;
9278
9279 it.current_y += row->height;
9280 ++it.vpos;
9281
9282 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9283 last_reused_text_row = row;
9284 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
9285 break;
9286 ++row;
d2f84654 9287 }
a2889657 9288 }
5f5c8ee5
GM
9289
9290 /* Update window_end_pos etc.; last_reused_text_row is the last
9291 reused row from the current matrix containing text, if any.
9292 The value of last_text_row is the last displayed line
9293 containing text. */
9294 if (last_reused_text_row)
a2889657 9295 {
5f5c8ee5
GM
9296 w->window_end_bytepos
9297 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
9298 XSETFASTINT (w->window_end_pos,
9299 Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
9300 XSETFASTINT (w->window_end_vpos,
9301 MATRIX_ROW_VPOS (last_reused_text_row,
9302 w->current_matrix));
a2889657 9303 }
5f5c8ee5
GM
9304 else if (last_text_row)
9305 {
9306 w->window_end_bytepos
9307 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9308 XSETFASTINT (w->window_end_pos,
9309 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9310 XSETFASTINT (w->window_end_vpos,
9311 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9312 }
9313 else
9314 {
9315 /* This window must be completely empty. */
9316 w->window_end_bytepos = 0;
9317 XSETFASTINT (w->window_end_pos, 0);
9318 XSETFASTINT (w->window_end_vpos, 0);
9319 }
9320 w->window_end_valid = Qnil;
a2889657 9321
5f5c8ee5
GM
9322 /* Update hint: don't try scrolling again in update_window. */
9323 w->desired_matrix->no_scrolling_p = 1;
9324
9325#if GLYPH_DEBUG
9326 debug_method_add (w, "try_window_reusing_current_matrix 1");
9327#endif
9328 return 1;
a2889657 9329 }
5f5c8ee5
GM
9330 else if (CHARPOS (new_start) > CHARPOS (start))
9331 {
9332 struct glyph_row *pt_row, *row;
9333 struct glyph_row *first_reusable_row;
9334 struct glyph_row *first_row_to_display;
9335 int dy;
9336 int yb = window_text_bottom_y (w);
9337
9338 IF_DEBUG (debug_method_add (w, "twu2"));
9339
9340 /* Find the row starting at new_start, if there is one. Don't
9341 reuse a partially visible line at the end. */
9342 first_reusable_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9343 while (first_reusable_row->enabled_p
9344 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
9345 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9346 < CHARPOS (new_start)))
9347 ++first_reusable_row;
9348
9349 /* Give up if there is no row to reuse. */
9350 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
9351 || !first_reusable_row->enabled_p
9352 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9353 != CHARPOS (new_start)))
5f5c8ee5
GM
9354 return 0;
9355
5f5c8ee5
GM
9356 /* We can reuse fully visible rows beginning with
9357 first_reusable_row to the end of the window. Set
9358 first_row_to_display to the first row that cannot be reused.
9359 Set pt_row to the row containing point, if there is any. */
9360 first_row_to_display = first_reusable_row;
9361 pt_row = NULL;
9362 while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb)
9363 {
9364 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
9365 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
9366 pt_row = first_row_to_display;
a2889657 9367
5f5c8ee5
GM
9368 ++first_row_to_display;
9369 }
a2889657 9370
5f5c8ee5
GM
9371 /* Start displaying at the start of first_row_to_display. */
9372 xassert (first_row_to_display->y < yb);
9373 init_to_row_start (&it, w, first_row_to_display);
9374 nrows_scrolled = MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix);
9375 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
9376 - nrows_scrolled);
9377 it.current_y = first_row_to_display->y - first_reusable_row->y;
9378
9379 /* Display lines beginning with first_row_to_display in the
9380 desired matrix. Set last_text_row to the last row displayed
9381 that displays text. */
9382 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
9383 if (pt_row == NULL)
9384 w->cursor.vpos = -1;
9385 last_text_row = NULL;
9386 while (it.current_y < it.last_visible_y && !fonts_changed_p)
9387 if (display_line (&it))
9388 last_text_row = it.glyph_row - 1;
9389
9390 /* Give up If point isn't in a row displayed or reused. */
9391 if (w->cursor.vpos < 0)
9392 {
9393 clear_glyph_matrix (w->desired_matrix);
9394 return 0;
9395 }
12adba34 9396
5f5c8ee5
GM
9397 /* If point is in a reused row, adjust y and vpos of the cursor
9398 position. */
9399 if (pt_row)
9400 {
9401 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
9402 w->current_matrix);
9403 w->cursor.y -= first_reusable_row->y;
a2889657
JB
9404 }
9405
5f5c8ee5
GM
9406 /* Scroll the display. */
9407 run.current_y = first_reusable_row->y;
045dee35 9408 run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9409 run.height = it.last_visible_y - run.current_y;
9410 if (run.height)
9411 {
9412 struct frame *f = XFRAME (WINDOW_FRAME (w));
9413 update_begin (f);
9414 rif->update_window_begin_hook (w);
9415 rif->scroll_run_hook (w, &run);
9416 rif->update_window_end_hook (w, 0);
9417 update_end (f);
9418 }
a2889657 9419
5f5c8ee5
GM
9420 /* Adjust Y positions of reused rows. */
9421 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9422 row = first_reusable_row;
9423 dy = first_reusable_row->y;
045dee35 9424 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9425 max_y = it.last_visible_y;
9426 while (row < first_row_to_display)
9427 {
9428 row->y -= dy;
9429 if (row->y < min_y)
9430 row->visible_height = row->height - (min_y - row->y);
9431 else if (row->y + row->height > max_y)
9432 row->visible_height
9433 = row->height - (row->y + row->height - max_y);
9434 else
9435 row->visible_height = row->height;
9436 ++row;
9437 }
a2889657 9438
5f5c8ee5
GM
9439 /* Disable rows not reused. */
9440 while (row < bottom_row)
9441 {
9442 row->enabled_p = 0;
9443 ++row;
9444 }
9445
9446 /* Scroll the current matrix. */
9447 xassert (nrows_scrolled > 0);
9448 rotate_matrix (w->current_matrix,
9449 start_vpos,
9450 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
9451 -nrows_scrolled);
9452
9453 /* Adjust window end. A null value of last_text_row means that
9454 the window end is in reused rows which in turn means that
9455 only its vpos can have changed. */
9456 if (last_text_row)
9457 {
9458 w->window_end_bytepos
9459 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9460 XSETFASTINT (w->window_end_pos,
9461 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9462 XSETFASTINT (w->window_end_vpos,
9463 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9464 }
9465 else
a2889657 9466 {
e8e536a9 9467 XSETFASTINT (w->window_end_vpos,
5f5c8ee5 9468 XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 9469 }
5f5c8ee5
GM
9470
9471 w->window_end_valid = Qnil;
9472 w->desired_matrix->no_scrolling_p = 1;
9473
9474#if GLYPH_DEBUG
9475 debug_method_add (w, "try_window_reusing_current_matrix 2");
9476#endif
9477 return 1;
a2889657 9478 }
5f5c8ee5
GM
9479
9480 return 0;
9481}
a2889657 9482
a2889657 9483
5f5c8ee5
GM
9484\f
9485/************************************************************************
9486 Window redisplay reusing current matrix when buffer has changed
9487 ************************************************************************/
9488
9489static struct glyph_row *get_last_unchanged_at_beg_row P_ ((struct window *));
9490static struct glyph_row *get_first_unchanged_at_end_row P_ ((struct window *,
9491 int *, int *));
9492static struct glyph_row *
9493find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
9494 struct glyph_row *));
9495
9496
9497/* Return the last row in MATRIX displaying text. If row START is
9498 non-null, start searching with that row. IT gives the dimensions
9499 of the display. Value is null if matrix is empty; otherwise it is
9500 a pointer to the row found. */
9501
9502static struct glyph_row *
9503find_last_row_displaying_text (matrix, it, start)
9504 struct glyph_matrix *matrix;
9505 struct it *it;
9506 struct glyph_row *start;
9507{
9508 struct glyph_row *row, *row_found;
9509
9510 /* Set row_found to the last row in IT->w's current matrix
9511 displaying text. The loop looks funny but think of partially
9512 visible lines. */
9513 row_found = NULL;
9514 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
9515 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9516 {
9517 xassert (row->enabled_p);
9518 row_found = row;
9519 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
9520 break;
9521 ++row;
a2889657 9522 }
5f5c8ee5
GM
9523
9524 return row_found;
9525}
9526
a2889657 9527
5f5c8ee5
GM
9528/* Return the last row in the current matrix of W that is not affected
9529 by changes at the start of current_buffer that occurred since the
9530 last time W was redisplayed. Value is null if no such row exists.
a2889657 9531
5f5c8ee5
GM
9532 The global variable beg_unchanged has to contain the number of
9533 bytes unchanged at the start of current_buffer. BEG +
9534 beg_unchanged is the buffer position of the first changed byte in
9535 current_buffer. Characters at positions < BEG + beg_unchanged are
9536 at the same buffer positions as they were when the current matrix
9537 was built. */
9538
9539static struct glyph_row *
9540get_last_unchanged_at_beg_row (w)
9541 struct window *w;
9542{
9142dd5b 9543 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
9544 struct glyph_row *row;
9545 struct glyph_row *row_found = NULL;
9546 int yb = window_text_bottom_y (w);
9547
9548 /* Find the last row displaying unchanged text. */
9549 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9550 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
9551 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 9552 {
5f5c8ee5
GM
9553 if (/* If row ends before first_changed_pos, it is unchanged,
9554 except in some case. */
9555 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
9556 /* When row ends in ZV and we write at ZV it is not
9557 unchanged. */
9558 && !row->ends_at_zv_p
9559 /* When first_changed_pos is the end of a continued line,
9560 row is not unchanged because it may be no longer
9561 continued. */
9562 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
9563 && row->continued_p))
9564 row_found = row;
9565
9566 /* Stop if last visible row. */
9567 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
9568 break;
9569
9570 ++row;
a2889657
JB
9571 }
9572
5f5c8ee5 9573 return row_found;
a2889657 9574}
5f5c8ee5
GM
9575
9576
9577/* Find the first glyph row in the current matrix of W that is not
9578 affected by changes at the end of current_buffer since the last
9579 time the window was redisplayed. Return in *DELTA the number of
c59c668a
GM
9580 chars by which buffer positions in unchanged text at the end of
9581 current_buffer must be adjusted. Return in *DELTA_BYTES the
9582 corresponding number of bytes. Value is null if no such row
9583 exists, i.e. all rows are affected by changes. */
5f5c8ee5
GM
9584
9585static struct glyph_row *
9586get_first_unchanged_at_end_row (w, delta, delta_bytes)
9587 struct window *w;
9588 int *delta, *delta_bytes;
a2889657 9589{
5f5c8ee5
GM
9590 struct glyph_row *row;
9591 struct glyph_row *row_found = NULL;
c581d710 9592
5f5c8ee5 9593 *delta = *delta_bytes = 0;
b2a76982 9594
5f5c8ee5
GM
9595 /* A value of window_end_pos >= end_unchanged means that the window
9596 end is in the range of changed text. If so, there is no
9597 unchanged row at the end of W's current matrix. */
9598 xassert (!NILP (w->window_end_valid));
9142dd5b 9599 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
9600 return NULL;
9601
9602 /* Set row to the last row in W's current matrix displaying text. */
9603 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
9604
5f5c8ee5
GM
9605 /* If matrix is entirely empty, no unchanged row exists. */
9606 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9607 {
9608 /* The value of row is the last glyph row in the matrix having a
9609 meaningful buffer position in it. The end position of row
9610 corresponds to window_end_pos. This allows us to translate
9611 buffer positions in the current matrix to current buffer
9612 positions for characters not in changed text. */
9613 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
9614 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
9615 int last_unchanged_pos, last_unchanged_pos_old;
9616 struct glyph_row *first_text_row
9617 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9618
9619 *delta = Z - Z_old;
9620 *delta_bytes = Z_BYTE - Z_BYTE_old;
9621
9622 /* Set last_unchanged_pos to the buffer position of the last
9623 character in the buffer that has not been changed. Z is the
9624 index + 1 of the last byte in current_buffer, i.e. by
9625 subtracting end_unchanged we get the index of the last
9626 unchanged character, and we have to add BEG to get its buffer
9627 position. */
9142dd5b 9628 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5
GM
9629 last_unchanged_pos_old = last_unchanged_pos - *delta;
9630
9631 /* Search backward from ROW for a row displaying a line that
9632 starts at a minimum position >= last_unchanged_pos_old. */
9633 while (row >= first_text_row)
9634 {
9635 xassert (row->enabled_p);
9636 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row));
9637
9638 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
9639 row_found = row;
9640 --row;
9641 }
9642 }
9643
9644 xassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
9645 return row_found;
c581d710
RS
9646}
9647
c581d710 9648
5f5c8ee5
GM
9649/* Make sure that glyph rows in the current matrix of window W
9650 reference the same glyph memory as corresponding rows in the
9651 frame's frame matrix. This function is called after scrolling W's
9652 current matrix on a terminal frame in try_window_id and
9653 try_window_reusing_current_matrix. */
9654
9655static void
9656sync_frame_with_window_matrix_rows (w)
9657 struct window *w;
c581d710 9658{
5f5c8ee5
GM
9659 struct frame *f = XFRAME (w->frame);
9660 struct glyph_row *window_row, *window_row_end, *frame_row;
9661
9662 /* Preconditions: W must be a leaf window and full-width. Its frame
9663 must have a frame matrix. */
9664 xassert (NILP (w->hchild) && NILP (w->vchild));
9665 xassert (WINDOW_FULL_WIDTH_P (w));
9666 xassert (!FRAME_WINDOW_P (f));
9667
9668 /* If W is a full-width window, glyph pointers in W's current matrix
9669 have, by definition, to be the same as glyph pointers in the
9670 corresponding frame matrix. */
9671 window_row = w->current_matrix->rows;
9672 window_row_end = window_row + w->current_matrix->nrows;
9673 frame_row = f->current_matrix->rows + XFASTINT (w->top);
9674 while (window_row < window_row_end)
659a218f 9675 {
5f5c8ee5
GM
9676 int area;
9677 for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
9678 frame_row->glyphs[area] = window_row->glyphs[area];
9679 ++window_row, ++frame_row;
659a218f 9680 }
a2889657 9681}
5f5c8ee5
GM
9682
9683
e037b9ec
GM
9684/* Find the glyph row in window W containing CHARPOS. Consider all
9685 rows between START and END (not inclusive). END null means search
9686 all rows to the end of the display area of W. Value is the row
9687 containing CHARPOS or null. */
9688
9689static struct glyph_row *
9690row_containing_pos (w, charpos, start, end)
9691 struct window *w;
9692 int charpos;
9693 struct glyph_row *start, *end;
9694{
9695 struct glyph_row *row = start;
9696 int last_y;
9697
9698 /* If we happen to start on a header-line, skip that. */
9699 if (row->mode_line_p)
9700 ++row;
9701
9702 if ((end && row >= end) || !row->enabled_p)
9703 return NULL;
9704
9705 last_y = window_text_bottom_y (w);
9706
9707 while ((end == NULL || row < end)
9708 && (MATRIX_ROW_END_CHARPOS (row) < charpos
9709 /* The end position of a row equals the start
9710 position of the next row. If CHARPOS is there, we
9711 would rather display it in the next line, except
9712 when this line ends in ZV. */
9713 || (MATRIX_ROW_END_CHARPOS (row) == charpos
9714 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
9715 || !row->ends_at_zv_p)))
9716 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
9717 ++row;
9718
9719 /* Give up if CHARPOS not found. */
9720 if ((end && row >= end)
9721 || charpos < MATRIX_ROW_START_CHARPOS (row)
9722 || charpos > MATRIX_ROW_END_CHARPOS (row))
9723 row = NULL;
9724
9725 return row;
9726}
9727
9728
5f5c8ee5
GM
9729/* Try to redisplay window W by reusing its existing display. W's
9730 current matrix must be up to date when this function is called,
9731 i.e. window_end_valid must not be nil.
9732
9733 Value is
9734
9735 1 if display has been updated
9736 0 if otherwise unsuccessful
9737 -1 if redisplay with same window start is known not to succeed
9738
9739 The following steps are performed:
9740
9741 1. Find the last row in the current matrix of W that is not
9742 affected by changes at the start of current_buffer. If no such row
9743 is found, give up.
9744
9745 2. Find the first row in W's current matrix that is not affected by
9746 changes at the end of current_buffer. Maybe there is no such row.
9747
9748 3. Display lines beginning with the row + 1 found in step 1 to the
9749 row found in step 2 or, if step 2 didn't find a row, to the end of
9750 the window.
9751
9752 4. If cursor is not known to appear on the window, give up.
9753
9754 5. If display stopped at the row found in step 2, scroll the
9755 display and current matrix as needed.
9756
9757 6. Maybe display some lines at the end of W, if we must. This can
9758 happen under various circumstances, like a partially visible line
9759 becoming fully visible, or because newly displayed lines are displayed
9760 in smaller font sizes.
9761
9762 7. Update W's window end information. */
9763
9764 /* Check that window end is what we expect it to be. */
12adba34
RS
9765
9766static int
5f5c8ee5 9767try_window_id (w)
12adba34 9768 struct window *w;
12adba34 9769{
5f5c8ee5
GM
9770 struct frame *f = XFRAME (w->frame);
9771 struct glyph_matrix *current_matrix = w->current_matrix;
9772 struct glyph_matrix *desired_matrix = w->desired_matrix;
9773 struct glyph_row *last_unchanged_at_beg_row;
9774 struct glyph_row *first_unchanged_at_end_row;
9775 struct glyph_row *row;
9776 struct glyph_row *bottom_row;
9777 int bottom_vpos;
9778 struct it it;
9779 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
9780 struct text_pos start_pos;
9781 struct run run;
9782 int first_unchanged_at_end_vpos = 0;
9783 struct glyph_row *last_text_row, *last_text_row_at_end;
9784 struct text_pos start;
9785
9786 SET_TEXT_POS_FROM_MARKER (start, w->start);
9787
9788 /* Check pre-conditions. Window end must be valid, otherwise
9789 the current matrix would not be up to date. */
9790 xassert (!NILP (w->window_end_valid));
9791 xassert (FRAME_WINDOW_P (XFRAME (w->frame))
9792 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)));
9793
9794 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
9795 only if buffer has really changed. The reason is that the gap is
9796 initially at Z for freshly visited files. The code below would
9797 set end_unchanged to 0 in that case. */
9798 if (MODIFF > SAVE_MODIFF)
9799 {
9142dd5b
GM
9800 if (GPT - BEG < BEG_UNCHANGED)
9801 BEG_UNCHANGED = GPT - BEG;
9802 if (Z - GPT < END_UNCHANGED)
9803 END_UNCHANGED = Z - GPT;
5f5c8ee5
GM
9804 }
9805
9806 /* If window starts after a line end, and the last change is in
9807 front of that newline, then changes don't affect the display.
9808 This case happens with stealth-fontification. */
9809 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
9810 if (CHARPOS (start) > BEGV
9142dd5b 9811 && Z - END_UNCHANGED < CHARPOS (start) - 1
5f5c8ee5
GM
9812 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
9813 && PT < MATRIX_ROW_END_CHARPOS (row))
9814 {
9815 /* We have to update window end positions because the buffer's
9816 size has changed. */
9817 w->window_end_pos
9818 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
9819 w->window_end_bytepos
9820 = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
9821 return 1;
9822 }
9823
9824 /* Return quickly if changes are all below what is displayed in the
9825 window, and if PT is in the window. */
9142dd5b 9826 if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row)
5f5c8ee5
GM
9827 && PT < MATRIX_ROW_END_CHARPOS (row))
9828 {
9829 /* We have to update window end positions because the buffer's
9830 size has changed. */
9831 w->window_end_pos
9832 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
9833 w->window_end_bytepos
9834 = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
9835 return 1;
9836 }
9837
9838 /* Check that window start agrees with the start of the first glyph
9839 row in its current matrix. Check this after we know the window
9840 start is not in changed text, otherwise positions would not be
9841 comparable. */
9842 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9843 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
9844 return 0;
9845
5f5c8ee5
GM
9846 /* Compute the position at which we have to start displaying new
9847 lines. Some of the lines at the top of the window might be
9848 reusable because they are not displaying changed text. Find the
9849 last row in W's current matrix not affected by changes at the
9850 start of current_buffer. Value is null if changes start in the
9851 first line of window. */
9852 last_unchanged_at_beg_row = get_last_unchanged_at_beg_row (w);
9853 if (last_unchanged_at_beg_row)
9854 {
9855 init_to_row_end (&it, w, last_unchanged_at_beg_row);
9856 start_pos = it.current.pos;
9857
9858 /* Start displaying new lines in the desired matrix at the same
9859 vpos we would use in the current matrix, i.e. below
9860 last_unchanged_at_beg_row. */
9861 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
9862 current_matrix);
9863 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
9864 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
9865
9866 xassert (it.hpos == 0 && it.current_x == 0);
9867 }
9868 else
9869 {
9870 /* There are no reusable lines at the start of the window.
9871 Start displaying in the first line. */
9872 start_display (&it, w, start);
9873 start_pos = it.current.pos;
9874 }
9875
5f5c8ee5
GM
9876 /* Find the first row that is not affected by changes at the end of
9877 the buffer. Value will be null if there is no unchanged row, in
9878 which case we must redisplay to the end of the window. delta
9879 will be set to the value by which buffer positions beginning with
9880 first_unchanged_at_end_row have to be adjusted due to text
9881 changes. */
9882 first_unchanged_at_end_row
9883 = get_first_unchanged_at_end_row (w, &delta, &delta_bytes);
9884 IF_DEBUG (debug_delta = delta);
9885 IF_DEBUG (debug_delta_bytes = delta_bytes);
9886
9887 /* Set stop_pos to the buffer position up to which we will have to
9888 display new lines. If first_unchanged_at_end_row != NULL, this
9889 is the buffer position of the start of the line displayed in that
9890 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
9891 that we don't stop at a buffer position. */
9892 stop_pos = 0;
9893 if (first_unchanged_at_end_row)
9894 {
9895 xassert (last_unchanged_at_beg_row == NULL
9896 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
9897
9898 /* If this is a continuation line, move forward to the next one
9899 that isn't. Changes in lines above affect this line.
9900 Caution: this may move first_unchanged_at_end_row to a row
9901 not displaying text. */
9902 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
9903 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
9904 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
9905 < it.last_visible_y))
9906 ++first_unchanged_at_end_row;
9907
9908 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
9909 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
9910 >= it.last_visible_y))
9911 first_unchanged_at_end_row = NULL;
9912 else
9913 {
9914 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
9915 + delta);
9916 first_unchanged_at_end_vpos
9917 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 9918 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
9919 }
9920 }
9921 else if (last_unchanged_at_beg_row == NULL)
9922 return 0;
9923
9924
9925#if GLYPH_DEBUG
9926
9927 /* Either there is no unchanged row at the end, or the one we have
9928 now displays text. This is a necessary condition for the window
9929 end pos calculation at the end of this function. */
9930 xassert (first_unchanged_at_end_row == NULL
9931 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
9932
9933 debug_last_unchanged_at_beg_vpos
9934 = (last_unchanged_at_beg_row
9935 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
9936 : -1);
9937 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
9938
9939#endif /* GLYPH_DEBUG != 0 */
9940
9941
9942 /* Display new lines. Set last_text_row to the last new line
9943 displayed which has text on it, i.e. might end up as being the
9944 line where the window_end_vpos is. */
9945 w->cursor.vpos = -1;
9946 last_text_row = NULL;
9947 overlay_arrow_seen = 0;
9948 while (it.current_y < it.last_visible_y
9949 && !fonts_changed_p
9950 && (first_unchanged_at_end_row == NULL
9951 || IT_CHARPOS (it) < stop_pos))
9952 {
9953 if (display_line (&it))
9954 last_text_row = it.glyph_row - 1;
9955 }
9956
9957 if (fonts_changed_p)
9958 return -1;
9959
9960
9961 /* Compute differences in buffer positions, y-positions etc. for
9962 lines reused at the bottom of the window. Compute what we can
9963 scroll. */
ca42b2e8
GM
9964 if (first_unchanged_at_end_row
9965 /* No lines reused because we displayed everything up to the
9966 bottom of the window. */
9967 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
9968 {
9969 dvpos = (it.vpos
9970 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
9971 current_matrix));
9972 dy = it.current_y - first_unchanged_at_end_row->y;
9973 run.current_y = first_unchanged_at_end_row->y;
9974 run.desired_y = run.current_y + dy;
9975 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
9976 }
9977 else
ca42b2e8
GM
9978 {
9979 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
9980 first_unchanged_at_end_row = NULL;
9981 }
5f5c8ee5
GM
9982 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
9983
8f8ba186 9984
5f5c8ee5
GM
9985 /* Find the cursor if not already found. We have to decide whether
9986 PT will appear on this window (it sometimes doesn't, but this is
9987 not a very frequent case.) This decision has to be made before
9988 the current matrix is altered. A value of cursor.vpos < 0 means
9989 that PT is either in one of the lines beginning at
9990 first_unchanged_at_end_row or below the window. Don't care for
9991 lines that might be displayed later at the window end; as
9992 mentioned, this is not a frequent case. */
9993 if (w->cursor.vpos < 0)
9994 {
9995 int last_y = min (it.last_visible_y, it.last_visible_y + dy);
9996
9997 /* Cursor in unchanged rows at the top? */
9998 if (PT < CHARPOS (start_pos)
9999 && last_unchanged_at_beg_row)
10000 {
e037b9ec
GM
10001 row = row_containing_pos (w, PT,
10002 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
10003 last_unchanged_at_beg_row + 1);
10004 xassert (row && row <= last_unchanged_at_beg_row);
5f5c8ee5
GM
10005 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
10006 }
10007
10008 /* Start from first_unchanged_at_end_row looking for PT. */
10009 else if (first_unchanged_at_end_row)
10010 {
e037b9ec
GM
10011 row = row_containing_pos (w, PT - delta,
10012 first_unchanged_at_end_row, NULL);
10013 if (row)
468155d7
GM
10014 set_cursor_from_row (w, row, w->current_matrix, delta,
10015 delta_bytes, dy, dvpos);
5f5c8ee5
GM
10016 }
10017
10018 /* Give up if cursor was not found. */
10019 if (w->cursor.vpos < 0)
10020 {
10021 clear_glyph_matrix (w->desired_matrix);
10022 return -1;
10023 }
10024 }
10025
10026 /* Don't let the cursor end in the scroll margins. */
10027 {
10028 int this_scroll_margin, cursor_height;
10029
10030 this_scroll_margin = max (0, scroll_margin);
10031 this_scroll_margin = min (this_scroll_margin,
10032 XFASTINT (w->height) / 4);
10033 this_scroll_margin *= CANON_Y_UNIT (it.f);
10034 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
10035
10036 if ((w->cursor.y < this_scroll_margin
10037 && CHARPOS (start) > BEGV)
10038 /* Don't take scroll margin into account at the bottom because
10039 old redisplay didn't do it either. */
10040 || w->cursor.y + cursor_height > it.last_visible_y)
10041 {
10042 w->cursor.vpos = -1;
10043 clear_glyph_matrix (w->desired_matrix);
10044 return -1;
10045 }
10046 }
10047
10048 /* Scroll the display. Do it before changing the current matrix so
10049 that xterm.c doesn't get confused about where the cursor glyph is
10050 found. */
10051 if (dy)
10052 {
10053 update_begin (f);
10054
10055 if (FRAME_WINDOW_P (f))
10056 {
10057 rif->update_window_begin_hook (w);
10058 rif->scroll_run_hook (w, &run);
10059 rif->update_window_end_hook (w, 0);
10060 }
10061 else
10062 {
10063 /* Terminal frame. In this case, dvpos gives the number of
10064 lines to scroll by; dvpos < 0 means scroll up. */
10065 int first_unchanged_at_end_vpos
10066 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
10067 int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
10068 int end = XFASTINT (w->top) + window_internal_height (w);
10069
10070 /* Perform the operation on the screen. */
10071 if (dvpos > 0)
10072 {
10073 /* Scroll last_unchanged_at_beg_row to the end of the
10074 window down dvpos lines. */
10075 set_terminal_window (end);
10076
10077 /* On dumb terminals delete dvpos lines at the end
10078 before inserting dvpos empty lines. */
10079 if (!scroll_region_ok)
10080 ins_del_lines (end - dvpos, -dvpos);
10081
10082 /* Insert dvpos empty lines in front of
10083 last_unchanged_at_beg_row. */
10084 ins_del_lines (from, dvpos);
10085 }
10086 else if (dvpos < 0)
10087 {
10088 /* Scroll up last_unchanged_at_beg_vpos to the end of
10089 the window to last_unchanged_at_beg_vpos - |dvpos|. */
10090 set_terminal_window (end);
10091
10092 /* Delete dvpos lines in front of
10093 last_unchanged_at_beg_vpos. ins_del_lines will set
10094 the cursor to the given vpos and emit |dvpos| delete
10095 line sequences. */
10096 ins_del_lines (from + dvpos, dvpos);
10097
10098 /* On a dumb terminal insert dvpos empty lines at the
10099 end. */
10100 if (!scroll_region_ok)
10101 ins_del_lines (end + dvpos, -dvpos);
10102 }
10103
10104 set_terminal_window (0);
10105 }
10106
10107 update_end (f);
10108 }
10109
ca42b2e8
GM
10110 /* Shift reused rows of the current matrix to the right position.
10111 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
10112 text. */
10113 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
10114 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
10115 if (dvpos < 0)
10116 {
10117 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
10118 bottom_vpos, dvpos);
10119 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
10120 bottom_vpos, 0);
10121 }
10122 else if (dvpos > 0)
10123 {
10124 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
10125 bottom_vpos, dvpos);
10126 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
10127 first_unchanged_at_end_vpos + dvpos, 0);
10128 }
10129
10130 /* For frame-based redisplay, make sure that current frame and window
10131 matrix are in sync with respect to glyph memory. */
10132 if (!FRAME_WINDOW_P (f))
10133 sync_frame_with_window_matrix_rows (w);
10134
10135 /* Adjust buffer positions in reused rows. */
10136 if (delta)
10137 increment_glyph_matrix_buffer_positions (current_matrix,
10138 first_unchanged_at_end_vpos + dvpos,
10139 bottom_vpos, delta, delta_bytes);
10140
10141 /* Adjust Y positions. */
10142 if (dy)
10143 shift_glyph_matrix (w, current_matrix,
10144 first_unchanged_at_end_vpos + dvpos,
10145 bottom_vpos, dy);
10146
10147 if (first_unchanged_at_end_row)
10148 first_unchanged_at_end_row += dvpos;
10149
10150 /* If scrolling up, there may be some lines to display at the end of
10151 the window. */
10152 last_text_row_at_end = NULL;
10153 if (dy < 0)
10154 {
10155 /* Set last_row to the glyph row in the current matrix where the
10156 window end line is found. It has been moved up or down in
10157 the matrix by dvpos. */
10158 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
10159 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
10160
10161 /* If last_row is the window end line, it should display text. */
10162 xassert (last_row->displays_text_p);
10163
10164 /* If window end line was partially visible before, begin
10165 displaying at that line. Otherwise begin displaying with the
10166 line following it. */
10167 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
10168 {
10169 init_to_row_start (&it, w, last_row);
10170 it.vpos = last_vpos;
10171 it.current_y = last_row->y;
10172 }
10173 else
10174 {
10175 init_to_row_end (&it, w, last_row);
10176 it.vpos = 1 + last_vpos;
10177 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
10178 ++last_row;
10179 }
12adba34 10180
5f5c8ee5
GM
10181 /* We may start in a continuation line. If so, we have to get
10182 the right continuation_lines_width and current_x. */
10183 it.continuation_lines_width = last_row->continuation_lines_width;
10184 it.hpos = it.current_x = 0;
10185
10186 /* Display the rest of the lines at the window end. */
10187 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10188 while (it.current_y < it.last_visible_y
10189 && !fonts_changed_p)
10190 {
10191 /* Is it always sure that the display agrees with lines in
10192 the current matrix? I don't think so, so we mark rows
10193 displayed invalid in the current matrix by setting their
10194 enabled_p flag to zero. */
10195 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
10196 if (display_line (&it))
10197 last_text_row_at_end = it.glyph_row - 1;
10198 }
10199 }
12adba34 10200
5f5c8ee5
GM
10201 /* Update window_end_pos and window_end_vpos. */
10202 if (first_unchanged_at_end_row
10203 && first_unchanged_at_end_row->y < it.last_visible_y
10204 && !last_text_row_at_end)
10205 {
10206 /* Window end line if one of the preserved rows from the current
10207 matrix. Set row to the last row displaying text in current
10208 matrix starting at first_unchanged_at_end_row, after
10209 scrolling. */
10210 xassert (first_unchanged_at_end_row->displays_text_p);
10211 row = find_last_row_displaying_text (w->current_matrix, &it,
10212 first_unchanged_at_end_row);
10213 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
10214
10215 XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row));
10216 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
10217 XSETFASTINT (w->window_end_vpos,
10218 MATRIX_ROW_VPOS (row, w->current_matrix));
10219 }
10220 else if (last_text_row_at_end)
10221 {
10222 XSETFASTINT (w->window_end_pos,
10223 Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
10224 w->window_end_bytepos
10225 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
10226 XSETFASTINT (w->window_end_vpos,
10227 MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
10228 }
10229 else if (last_text_row)
10230 {
10231 /* We have displayed either to the end of the window or at the
10232 end of the window, i.e. the last row with text is to be found
10233 in the desired matrix. */
10234 XSETFASTINT (w->window_end_pos,
10235 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10236 w->window_end_bytepos
10237 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
10238 XSETFASTINT (w->window_end_vpos,
10239 MATRIX_ROW_VPOS (last_text_row, desired_matrix));
10240 }
10241 else if (first_unchanged_at_end_row == NULL
10242 && last_text_row == NULL
10243 && last_text_row_at_end == NULL)
10244 {
10245 /* Displayed to end of window, but no line containing text was
10246 displayed. Lines were deleted at the end of the window. */
10247 int vpos;
045dee35 10248 int header_line_p = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
10249
10250 for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
045dee35
GM
10251 if ((w->desired_matrix->rows[vpos + header_line_p].enabled_p
10252 && w->desired_matrix->rows[vpos + header_line_p].displays_text_p)
10253 || (!w->desired_matrix->rows[vpos + header_line_p].enabled_p
10254 && w->current_matrix->rows[vpos + header_line_p].displays_text_p))
5f5c8ee5 10255 break;
12adba34 10256
5f5c8ee5
GM
10257 w->window_end_vpos = make_number (vpos);
10258 }
10259 else
10260 abort ();
10261
10262 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
10263 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 10264
5f5c8ee5
GM
10265 /* Record that display has not been completed. */
10266 w->window_end_valid = Qnil;
10267 w->desired_matrix->no_scrolling_p = 1;
10268 return 1;
12adba34 10269}
0f9c0ff0 10270
a2889657 10271
5f5c8ee5
GM
10272\f
10273/***********************************************************************
10274 More debugging support
10275 ***********************************************************************/
a2889657 10276
5f5c8ee5 10277#if GLYPH_DEBUG
a2889657 10278
5f5c8ee5
GM
10279 void dump_glyph_row P_ ((struct glyph_matrix *, int, int));
10280static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
1c9241f5 10281
31b24551 10282
5f5c8ee5
GM
10283/* Dump the contents of glyph matrix MATRIX on stderr. If
10284 WITH_GLYPHS_P is non-zero, dump glyph contents as well. */
ca26e1c8 10285
5f5c8ee5
GM
10286void
10287dump_glyph_matrix (matrix, with_glyphs_p)
10288 struct glyph_matrix *matrix;
10289 int with_glyphs_p;
10290{
efc63ef0 10291 int i;
5f5c8ee5
GM
10292 for (i = 0; i < matrix->nrows; ++i)
10293 dump_glyph_row (matrix, i, with_glyphs_p);
10294}
31b24551 10295
68a37fa8 10296
5f5c8ee5
GM
10297/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
10298 WITH_GLYPH_SP non-zero means dump glyph contents, too. */
a2889657 10299
5f5c8ee5
GM
10300void
10301dump_glyph_row (matrix, vpos, with_glyphs_p)
10302 struct glyph_matrix *matrix;
10303 int vpos, with_glyphs_p;
10304{
10305 struct glyph_row *row;
10306
10307 if (vpos < 0 || vpos >= matrix->nrows)
10308 return;
10309
10310 row = MATRIX_ROW (matrix, vpos);
10311
10312 fprintf (stderr, "Row Start End Used oEI><O\\CTZF X Y W\n");
10313 fprintf (stderr, "=============================================\n");
10314
10315 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",
10316 row - matrix->rows,
10317 MATRIX_ROW_START_CHARPOS (row),
10318 MATRIX_ROW_END_CHARPOS (row),
10319 row->used[TEXT_AREA],
10320 row->contains_overlapping_glyphs_p,
10321 row->enabled_p,
10322 row->inverse_p,
10323 row->truncated_on_left_p,
10324 row->truncated_on_right_p,
10325 row->overlay_arrow_p,
10326 row->continued_p,
10327 MATRIX_ROW_CONTINUATION_LINE_P (row),
10328 row->displays_text_p,
10329 row->ends_at_zv_p,
10330 row->fill_line_p,
10331 row->x,
10332 row->y,
10333 row->pixel_width);
10334 fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
10335 row->end.overlay_string_index);
10336 fprintf (stderr, "%9d %5d\n",
10337 CHARPOS (row->start.string_pos),
10338 CHARPOS (row->end.string_pos));
10339 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
10340 row->end.dpvec_index);
10341
10342 if (with_glyphs_p)
bd66d1ba 10343 {
5f5c8ee5
GM
10344 struct glyph *glyph, *glyph_end;
10345 int prev_had_glyphs_p;
10346
10347 glyph = row->glyphs[TEXT_AREA];
10348 glyph_end = glyph + row->used[TEXT_AREA];
10349
10350 /* Glyph for a line end in text. */
10351 if (glyph == glyph_end && glyph->charpos > 0)
10352 ++glyph_end;
10353
10354 if (glyph < glyph_end)
bd66d1ba 10355 {
5f5c8ee5
GM
10356 fprintf (stderr, " Glyph Type Pos W Code C Face LR\n");
10357 prev_had_glyphs_p = 1;
bd66d1ba
RS
10358 }
10359 else
5f5c8ee5
GM
10360 prev_had_glyphs_p = 0;
10361
10362 while (glyph < glyph_end)
f7b4b63a 10363 {
5f5c8ee5
GM
10364 if (glyph->type == CHAR_GLYPH)
10365 {
10366 fprintf (stderr,
10367 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10368 glyph - row->glyphs[TEXT_AREA],
10369 'C',
10370 glyph->charpos,
10371 glyph->pixel_width,
10372 glyph->u.ch.code,
10373 (glyph->u.ch.code < 0x80 && glyph->u.ch.code >= ' '
10374 ? glyph->u.ch.code
10375 : '.'),
10376 glyph->u.ch.face_id,
10377 glyph->left_box_line_p,
10378 glyph->right_box_line_p);
10379 }
10380 else if (glyph->type == STRETCH_GLYPH)
10381 {
10382 fprintf (stderr,
10383 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10384 glyph - row->glyphs[TEXT_AREA],
10385 'S',
10386 glyph->charpos,
10387 glyph->pixel_width,
10388 0,
10389 '.',
10390 glyph->u.stretch.face_id,
10391 glyph->left_box_line_p,
10392 glyph->right_box_line_p);
10393 }
10394 else if (glyph->type == IMAGE_GLYPH)
10395 {
10396 fprintf (stderr,
10397 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10398 glyph - row->glyphs[TEXT_AREA],
10399 'I',
10400 glyph->charpos,
10401 glyph->pixel_width,
10402 glyph->u.img.id,
10403 '.',
10404 glyph->u.img.face_id,
10405 glyph->left_box_line_p,
10406 glyph->right_box_line_p);
10407 }
10408 ++glyph;
f7b4b63a 10409 }
f4faa47c 10410 }
5f5c8ee5 10411}
f4faa47c 10412
a2889657 10413
5f5c8ee5
GM
10414DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
10415 Sdump_glyph_matrix, 0, 1, "p",
10416 "Dump the current matrix of the selected window to stderr.\n\
10417Shows contents of glyph row structures. With non-nil optional\n\
10418parameter WITH-GLYPHS-P, dump glyphs as well.")
10419 (with_glyphs_p)
10420{
10421 struct window *w = XWINDOW (selected_window);
10422 struct buffer *buffer = XBUFFER (w->buffer);
10423
10424 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
10425 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
10426 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
10427 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
10428 fprintf (stderr, "=============================================\n");
10429 dump_glyph_matrix (w->current_matrix, !NILP (with_glyphs_p));
10430 return Qnil;
10431}
1c2250c2 10432
1fca3fae 10433
5f5c8ee5
GM
10434DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "",
10435 "Dump glyph row ROW to stderr.")
10436 (row)
10437 Lisp_Object row;
10438{
10439 CHECK_NUMBER (row, 0);
10440 dump_glyph_row (XWINDOW (selected_window)->current_matrix, XINT (row), 1);
10441 return Qnil;
10442}
1fca3fae 10443
67481ae5 10444
e037b9ec 10445DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row,
5f5c8ee5
GM
10446 0, 0, "", "")
10447 ()
10448{
886bd6f2
GM
10449 struct frame *sf = SELECTED_FRAME ();
10450 struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)
5f5c8ee5
GM
10451 ->current_matrix);
10452 dump_glyph_row (m, 0, 1);
10453 return Qnil;
10454}
ca26e1c8 10455
0f9c0ff0 10456
5f5c8ee5
GM
10457DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
10458 Strace_redisplay_toggle, 0, 0, "",
10459 "Toggle tracing of redisplay.")
10460 ()
10461{
10462 trace_redisplay_p = !trace_redisplay_p;
10463 return Qnil;
10464}
10465
10466
10467#endif /* GLYPH_DEBUG */
ca26e1c8 10468
ca26e1c8 10469
5f5c8ee5
GM
10470\f
10471/***********************************************************************
10472 Building Desired Matrix Rows
10473 ***********************************************************************/
a2889657 10474
5f5c8ee5
GM
10475/* Return a temporary glyph row holding the glyphs of an overlay
10476 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 10477
5f5c8ee5
GM
10478static struct glyph_row *
10479get_overlay_arrow_glyph_row (w)
10480 struct window *w;
10481{
10482 struct frame *f = XFRAME (WINDOW_FRAME (w));
10483 struct buffer *buffer = XBUFFER (w->buffer);
10484 struct buffer *old = current_buffer;
10485 unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data;
10486 int arrow_len = XSTRING (Voverlay_arrow_string)->size;
10487 unsigned char *arrow_end = arrow_string + arrow_len;
10488 unsigned char *p;
10489 struct it it;
10490 int multibyte_p;
10491 int n_glyphs_before;
10492
10493 set_buffer_temp (buffer);
10494 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
10495 it.glyph_row->used[TEXT_AREA] = 0;
10496 SET_TEXT_POS (it.position, 0, 0);
10497
10498 multibyte_p = !NILP (buffer->enable_multibyte_characters);
10499 p = arrow_string;
10500 while (p < arrow_end)
10501 {
10502 Lisp_Object face, ilisp;
10503
10504 /* Get the next character. */
10505 if (multibyte_p)
4fdb80f2 10506 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
10507 else
10508 it.c = *p, it.len = 1;
10509 p += it.len;
10510
10511 /* Get its face. */
10512 XSETFASTINT (ilisp, p - arrow_string);
10513 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
10514 it.face_id = compute_char_face (f, it.c, face);
10515
10516 /* Compute its width, get its glyphs. */
10517 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 10518 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
10519 PRODUCE_GLYPHS (&it);
10520
10521 /* If this character doesn't fit any more in the line, we have
10522 to remove some glyphs. */
10523 if (it.current_x > it.last_visible_x)
10524 {
10525 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
10526 break;
10527 }
10528 }
10529
10530 set_buffer_temp (old);
10531 return it.glyph_row;
10532}
ca26e1c8 10533
b0a0fbda 10534
5f5c8ee5
GM
10535/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
10536 glyphs are only inserted for terminal frames since we can't really
10537 win with truncation glyphs when partially visible glyphs are
10538 involved. Which glyphs to insert is determined by
10539 produce_special_glyphs. */
67481ae5 10540
5f5c8ee5
GM
10541static void
10542insert_left_trunc_glyphs (it)
10543 struct it *it;
10544{
10545 struct it truncate_it;
10546 struct glyph *from, *end, *to, *toend;
10547
10548 xassert (!FRAME_WINDOW_P (it->f));
10549
10550 /* Get the truncation glyphs. */
10551 truncate_it = *it;
10552 truncate_it.charset = -1;
10553 truncate_it.current_x = 0;
10554 truncate_it.face_id = DEFAULT_FACE_ID;
10555 truncate_it.glyph_row = &scratch_glyph_row;
10556 truncate_it.glyph_row->used[TEXT_AREA] = 0;
10557 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
10558 truncate_it.object = 0;
10559 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
10560
10561 /* Overwrite glyphs from IT with truncation glyphs. */
10562 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
10563 end = from + truncate_it.glyph_row->used[TEXT_AREA];
10564 to = it->glyph_row->glyphs[TEXT_AREA];
10565 toend = to + it->glyph_row->used[TEXT_AREA];
10566
10567 while (from < end)
10568 *to++ = *from++;
10569
10570 /* There may be padding glyphs left over. Remove them. */
10571 from = to;
10572 while (from < toend && CHAR_GLYPH_PADDING_P (*from))
10573 ++from;
10574 while (from < toend)
10575 *to++ = *from++;
10576
10577 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
10578}
e0bfbde6 10579
e0bfbde6 10580
5f5c8ee5 10581/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 10582
5f5c8ee5
GM
10583 Most of the time, ascent and height of a display line will be equal
10584 to the max_ascent and max_height values of the display iterator
10585 structure. This is not the case if
67481ae5 10586
5f5c8ee5
GM
10587 1. We hit ZV without displaying anything. In this case, max_ascent
10588 and max_height will be zero.
1c9241f5 10589
5f5c8ee5
GM
10590 2. We have some glyphs that don't contribute to the line height.
10591 (The glyph row flag contributes_to_line_height_p is for future
10592 pixmap extensions).
f6fd109b 10593
5f5c8ee5
GM
10594 The first case is easily covered by using default values because in
10595 these cases, the line height does not really matter, except that it
10596 must not be zero. */
67481ae5 10597
5f5c8ee5
GM
10598static void
10599compute_line_metrics (it)
10600 struct it *it;
10601{
10602 struct glyph_row *row = it->glyph_row;
10603 int area, i;
1c2250c2 10604
5f5c8ee5
GM
10605 if (FRAME_WINDOW_P (it->f))
10606 {
045dee35 10607 int i, header_line_height;
1c2250c2 10608
5f5c8ee5
GM
10609 /* The line may consist of one space only, that was added to
10610 place the cursor on it. If so, the row's height hasn't been
10611 computed yet. */
10612 if (row->height == 0)
10613 {
10614 if (it->max_ascent + it->max_descent == 0)
312246d1 10615 it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
5f5c8ee5
GM
10616 row->ascent = it->max_ascent;
10617 row->height = it->max_ascent + it->max_descent;
312246d1
GM
10618 row->phys_ascent = it->max_phys_ascent;
10619 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
10620 }
10621
10622 /* Compute the width of this line. */
10623 row->pixel_width = row->x;
10624 for (i = 0; i < row->used[TEXT_AREA]; ++i)
10625 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
10626
10627 xassert (row->pixel_width >= 0);
10628 xassert (row->ascent >= 0 && row->height > 0);
10629
312246d1
GM
10630 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
10631 || MATRIX_ROW_OVERLAPS_PRED_P (row));
10632
10633 /* If first line's physical ascent is larger than its logical
10634 ascent, use the physical ascent, and make the row taller.
10635 This makes accented characters fully visible. */
10636 if (row == it->w->desired_matrix->rows
10637 && row->phys_ascent > row->ascent)
10638 {
10639 row->height += row->phys_ascent - row->ascent;
10640 row->ascent = row->phys_ascent;
10641 }
10642
5f5c8ee5
GM
10643 /* Compute how much of the line is visible. */
10644 row->visible_height = row->height;
10645
045dee35
GM
10646 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
10647 if (row->y < header_line_height)
10648 row->visible_height -= header_line_height - row->y;
5f5c8ee5
GM
10649 else
10650 {
10651 int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
10652 if (row->y + row->height > max_y)
10653 row->visible_height -= row->y + row->height - max_y;
10654 }
10655 }
10656 else
10657 {
10658 row->pixel_width = row->used[TEXT_AREA];
312246d1
GM
10659 row->ascent = row->phys_ascent = 0;
10660 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 10661 }
67481ae5 10662
5f5c8ee5
GM
10663 /* Compute a hash code for this row. */
10664 row->hash = 0;
10665 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
10666 for (i = 0; i < row->used[area]; ++i)
10667 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
10668 + row->glyphs[area][i].u.val
10669 + (row->glyphs[area][i].type << 2));
a2889657 10670
5f5c8ee5 10671 it->max_ascent = it->max_descent = 0;
312246d1 10672 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 10673}
12adba34 10674
ca26e1c8 10675
5f5c8ee5
GM
10676/* Append one space to the glyph row of iterator IT if doing a
10677 window-based redisplay. DEFAULT_FACE_P non-zero means let the
10678 space have the default face, otherwise let it have the same face as
c6e89d6c
GM
10679 IT->face_id.
10680
10681 This function is called to make sure that there is always one glyph
10682 at the end of a glyph row that the cursor can be set on under
10683 window-systems. (If there weren't such a glyph we would not know
10684 how wide and tall a box cursor should be displayed).
10685
10686 At the same time this space let's a nicely handle clearing to the
10687 end of the line if the row ends in italic text. */
ca26e1c8 10688
5f5c8ee5
GM
10689static void
10690append_space (it, default_face_p)
10691 struct it *it;
10692 int default_face_p;
10693{
10694 if (FRAME_WINDOW_P (it->f))
10695 {
10696 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 10697
5f5c8ee5
GM
10698 if (it->glyph_row->glyphs[TEXT_AREA] + n
10699 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 10700 {
5f5c8ee5
GM
10701 /* Save some values that must not be changed. */
10702 int saved_x = it->current_x;
10703 struct text_pos saved_pos;
10704 int saved_what = it->what;
10705 int saved_face_id = it->face_id;
10706 int saved_charset = it->charset;
10707 Lisp_Object saved_object;
10708
10709 saved_object = it->object;
10710 saved_pos = it->position;
10711
10712 it->what = IT_CHARACTER;
10713 bzero (&it->position, sizeof it->position);
10714 it->object = 0;
10715 it->c = ' ';
10716 it->len = 1;
10717 it->charset = CHARSET_ASCII;
10718
10719 if (default_face_p)
10720 it->face_id = DEFAULT_FACE_ID;
10721 if (it->multibyte_p)
10722 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, CHARSET_ASCII);
10723 else
10724 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, -1);
1842fc1a 10725
5f5c8ee5
GM
10726 PRODUCE_GLYPHS (it);
10727
10728 it->current_x = saved_x;
10729 it->object = saved_object;
10730 it->position = saved_pos;
10731 it->what = saved_what;
10732 it->face_id = saved_face_id;
10733 it->charset = saved_charset;
10734 }
10735 }
10736}
12adba34 10737
1842fc1a 10738
5f5c8ee5
GM
10739/* Extend the face of the last glyph in the text area of IT->glyph_row
10740 to the end of the display line. Called from display_line.
10741 If the glyph row is empty, add a space glyph to it so that we
10742 know the face to draw. Set the glyph row flag fill_line_p. */
10743
10744static void
10745extend_face_to_end_of_line (it)
10746 struct it *it;
10747{
10748 struct face *face;
10749 struct frame *f = it->f;
1842fc1a 10750
5f5c8ee5
GM
10751 /* If line is already filled, do nothing. */
10752 if (it->current_x >= it->last_visible_x)
10753 return;
10754
10755 /* Face extension extends the background and box of IT->face_id
10756 to the end of the line. If the background equals the background
10757 of the frame, we haven't to do anything. */
10758 face = FACE_FROM_ID (f, it->face_id);
10759 if (FRAME_WINDOW_P (f)
10760 && face->box == FACE_NO_BOX
10761 && face->background == FRAME_BACKGROUND_PIXEL (f)
10762 && !face->stipple)
10763 return;
1842fc1a 10764
5f5c8ee5
GM
10765 /* Set the glyph row flag indicating that the face of the last glyph
10766 in the text area has to be drawn to the end of the text area. */
10767 it->glyph_row->fill_line_p = 1;
545e04f6 10768
5f5c8ee5
GM
10769 /* If current charset of IT is not ASCII, make sure we have the
10770 ASCII face. This will be automatically undone the next time
10771 get_next_display_element returns a character from a different
10772 charset. Note that the charset will always be ASCII in unibyte
10773 text. */
10774 if (it->charset != CHARSET_ASCII)
10775 {
10776 it->charset = CHARSET_ASCII;
10777 it->face_id = FACE_FOR_CHARSET (f, it->face_id, CHARSET_ASCII);
10778 }
545e04f6 10779
5f5c8ee5
GM
10780 if (FRAME_WINDOW_P (f))
10781 {
10782 /* If the row is empty, add a space with the current face of IT,
10783 so that we know which face to draw. */
10784 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 10785 {
5f5c8ee5
GM
10786 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
10787 it->glyph_row->glyphs[TEXT_AREA][0].u.ch.face_id = it->face_id;
10788 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 10789 }
5f5c8ee5
GM
10790 }
10791 else
10792 {
10793 /* Save some values that must not be changed. */
10794 int saved_x = it->current_x;
10795 struct text_pos saved_pos;
10796 Lisp_Object saved_object;
10797 int saved_what = it->what;
10798
10799 saved_object = it->object;
10800 saved_pos = it->position;
10801
10802 it->what = IT_CHARACTER;
10803 bzero (&it->position, sizeof it->position);
10804 it->object = 0;
10805 it->c = ' ';
10806 it->len = 1;
10807
10808 PRODUCE_GLYPHS (it);
10809
10810 while (it->current_x <= it->last_visible_x)
10811 PRODUCE_GLYPHS (it);
10812
10813 /* Don't count these blanks really. It would let us insert a left
10814 truncation glyph below and make us set the cursor on them, maybe. */
10815 it->current_x = saved_x;
10816 it->object = saved_object;
10817 it->position = saved_pos;
10818 it->what = saved_what;
10819 }
10820}
12adba34 10821
545e04f6 10822
5f5c8ee5
GM
10823/* Value is non-zero if text starting at CHARPOS in current_buffer is
10824 trailing whitespace. */
1c9241f5 10825
5f5c8ee5
GM
10826static int
10827trailing_whitespace_p (charpos)
10828 int charpos;
10829{
10830 int bytepos = CHAR_TO_BYTE (charpos);
10831 int c = 0;
7bbe686f 10832
5f5c8ee5
GM
10833 while (bytepos < ZV_BYTE
10834 && (c = FETCH_CHAR (bytepos),
10835 c == ' ' || c == '\t'))
10836 ++bytepos;
0d09d1e6 10837
8f897821
GM
10838 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
10839 {
10840 if (bytepos != PT_BYTE)
10841 return 1;
10842 }
10843 return 0;
5f5c8ee5 10844}
31b24551 10845
545e04f6 10846
5f5c8ee5 10847/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 10848
5f5c8ee5
GM
10849void
10850highlight_trailing_whitespace (f, row)
10851 struct frame *f;
10852 struct glyph_row *row;
10853{
10854 int used = row->used[TEXT_AREA];
10855
10856 if (used)
10857 {
10858 struct glyph *start = row->glyphs[TEXT_AREA];
10859 struct glyph *glyph = start + used - 1;
10860
10861 /* Skip over the space glyph inserted to display the
10862 cursor at the end of a line. */
10863 if (glyph->type == CHAR_GLYPH
10864 && glyph->u.ch.code == ' '
10865 && glyph->object == 0)
10866 --glyph;
10867
10868 /* If last glyph is a space or stretch, and it's trailing
10869 whitespace, set the face of all trailing whitespace glyphs in
10870 IT->glyph_row to `trailing-whitespace'. */
10871 if (glyph >= start
10872 && BUFFERP (glyph->object)
10873 && (glyph->type == STRETCH_GLYPH
10874 || (glyph->type == CHAR_GLYPH
10875 && glyph->u.ch.code == ' '))
10876 && trailing_whitespace_p (glyph->charpos))
545e04f6 10877 {
5f5c8ee5
GM
10878 int face_id = lookup_named_face (f, Qtrailing_whitespace,
10879 CHARSET_ASCII);
10880
10881 while (glyph >= start
10882 && BUFFERP (glyph->object)
10883 && (glyph->type == STRETCH_GLYPH
10884 || (glyph->type == CHAR_GLYPH
10885 && glyph->u.ch.code == ' ')))
545e04f6 10886 {
5f5c8ee5
GM
10887 if (glyph->type == STRETCH_GLYPH)
10888 glyph->u.stretch.face_id = face_id;
10889 else
10890 glyph->u.ch.face_id = face_id;
10891 --glyph;
545e04f6
KH
10892 }
10893 }
a2889657 10894 }
5f5c8ee5 10895}
a2889657 10896
5fcbb24d 10897
5f5c8ee5
GM
10898/* Construct the glyph row IT->glyph_row in the desired matrix of
10899 IT->w from text at the current position of IT. See dispextern.h
10900 for an overview of struct it. Value is non-zero if
10901 IT->glyph_row displays text, as opposed to a line displaying ZV
10902 only. */
10903
10904static int
10905display_line (it)
10906 struct it *it;
10907{
10908 struct glyph_row *row = it->glyph_row;
10909
10910 /* We always start displaying at hpos zero even if hscrolled. */
10911 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 10912
5f5c8ee5
GM
10913 /* We must not display in a row that's not a text row. */
10914 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
10915 < it->w->desired_matrix->nrows);
12adba34 10916
5f5c8ee5
GM
10917 /* Is IT->w showing the region? */
10918 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 10919
5f5c8ee5
GM
10920 /* Clear the result glyph row and enable it. */
10921 prepare_desired_row (row);
12adba34 10922
5f5c8ee5
GM
10923 row->y = it->current_y;
10924 row->start = it->current;
10925 row->continuation_lines_width = it->continuation_lines_width;
10926 row->displays_text_p = 1;
10927
10928 /* Arrange the overlays nicely for our purposes. Usually, we call
10929 display_line on only one line at a time, in which case this
10930 can't really hurt too much, or we call it on lines which appear
10931 one after another in the buffer, in which case all calls to
10932 recenter_overlay_lists but the first will be pretty cheap. */
10933 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
10934
5f5c8ee5
GM
10935 /* Move over display elements that are not visible because we are
10936 hscrolled. This may stop at an x-position < IT->first_visible_x
10937 if the first glyph is partially visible or if we hit a line end. */
10938 if (it->current_x < it->first_visible_x)
10939 move_it_in_display_line_to (it, ZV, it->first_visible_x,
10940 MOVE_TO_POS | MOVE_TO_X);
10941
10942 /* Get the initial row height. This is either the height of the
10943 text hscrolled, if there is any, or zero. */
10944 row->ascent = it->max_ascent;
10945 row->height = it->max_ascent + it->max_descent;
312246d1
GM
10946 row->phys_ascent = it->max_phys_ascent;
10947 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
10948
10949 /* Loop generating characters. The loop is left with IT on the next
10950 character to display. */
10951 while (1)
10952 {
10953 int n_glyphs_before, hpos_before, x_before;
10954 int x, i, nglyphs;
10955
10956 /* Retrieve the next thing to display. Value is zero if end of
10957 buffer reached. */
10958 if (!get_next_display_element (it))
10959 {
10960 /* Maybe add a space at the end of this line that is used to
10961 display the cursor there under X. */
10962 append_space (it, 1);
10963
10964 /* The position -1 below indicates a blank line not
10965 corresponding to any text, as opposed to an empty line
10966 corresponding to a line end. */
10967 if (row->used[TEXT_AREA] <= 1)
a2889657 10968 {
5f5c8ee5
GM
10969 row->glyphs[TEXT_AREA]->charpos = -1;
10970 row->displays_text_p = 0;
10971
10972 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines))
10973 row->indicate_empty_line_p = 1;
a2889657 10974 }
5f5c8ee5
GM
10975
10976 it->continuation_lines_width = 0;
10977 row->ends_at_zv_p = 1;
10978 break;
a2889657 10979 }
a2889657 10980
5f5c8ee5
GM
10981 /* Now, get the metrics of what we want to display. This also
10982 generates glyphs in `row' (which is IT->glyph_row). */
10983 n_glyphs_before = row->used[TEXT_AREA];
10984 x = it->current_x;
10985 PRODUCE_GLYPHS (it);
a2889657 10986
5f5c8ee5
GM
10987 /* If this display element was in marginal areas, continue with
10988 the next one. */
10989 if (it->area != TEXT_AREA)
a2889657 10990 {
5f5c8ee5
GM
10991 row->ascent = max (row->ascent, it->max_ascent);
10992 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
10993 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
10994 row->phys_height = max (row->phys_height,
10995 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
10996 set_iterator_to_next (it);
10997 continue;
10998 }
5936754e 10999
5f5c8ee5
GM
11000 /* Does the display element fit on the line? If we truncate
11001 lines, we should draw past the right edge of the window. If
11002 we don't truncate, we want to stop so that we can display the
11003 continuation glyph before the right margin. If lines are
11004 continued, there are two possible strategies for characters
11005 resulting in more than 1 glyph (e.g. tabs): Display as many
11006 glyphs as possible in this line and leave the rest for the
11007 continuation line, or display the whole element in the next
11008 line. Original redisplay did the former, so we do it also. */
11009 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
11010 hpos_before = it->hpos;
11011 x_before = x;
11012
11013 if (nglyphs == 1
11014 && it->current_x < it->last_visible_x)
11015 {
11016 ++it->hpos;
11017 row->ascent = max (row->ascent, it->max_ascent);
11018 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11019 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11020 row->phys_height = max (row->phys_height,
11021 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11022 if (it->current_x - it->pixel_width < it->first_visible_x)
11023 row->x = x - it->first_visible_x;
11024 }
11025 else
11026 {
11027 int new_x;
11028 struct glyph *glyph;
11029
11030 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 11031 {
5f5c8ee5
GM
11032 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
11033 new_x = x + glyph->pixel_width;
11034
11035 if (/* Lines are continued. */
11036 !it->truncate_lines_p
11037 && (/* Glyph doesn't fit on the line. */
11038 new_x > it->last_visible_x
11039 /* Or it fits exactly on a window system frame. */
11040 || (new_x == it->last_visible_x
11041 && FRAME_WINDOW_P (it->f))))
a2889657 11042 {
5f5c8ee5
GM
11043 /* End of a continued line. */
11044
11045 if (it->hpos == 0
11046 || (new_x == it->last_visible_x
11047 && FRAME_WINDOW_P (it->f)))
11048 {
11049 /* Current glyph fits exactly on the line. We
11050 must continue the line because we can't draw
11051 the cursor after the glyph. */
11052 row->continued_p = 1;
11053 it->current_x = new_x;
11054 it->continuation_lines_width += new_x;
11055 ++it->hpos;
11056 if (i == nglyphs - 1)
11057 set_iterator_to_next (it);
11058 }
11059 else
5936754e 11060 {
5f5c8ee5
GM
11061 /* Display element draws past the right edge of
11062 the window. Restore positions to values
11063 before the element. The next line starts
11064 with current_x before the glyph that could
11065 not be displayed, so that TAB works right. */
11066 row->used[TEXT_AREA] = n_glyphs_before + i;
11067
11068 /* Display continuation glyphs. */
11069 if (!FRAME_WINDOW_P (it->f))
11070 produce_special_glyphs (it, IT_CONTINUATION);
11071 row->continued_p = 1;
11072
11073 it->current_x = x;
11074 it->continuation_lines_width += x;
5936754e 11075 }
5f5c8ee5
GM
11076 break;
11077 }
11078 else if (new_x > it->first_visible_x)
11079 {
11080 /* Increment number of glyphs actually displayed. */
11081 ++it->hpos;
11082
11083 if (x < it->first_visible_x)
11084 /* Glyph is partially visible, i.e. row starts at
11085 negative X position. */
11086 row->x = x - it->first_visible_x;
11087 }
11088 else
11089 {
11090 /* Glyph is completely off the left margin of the
11091 window. This should not happen because of the
11092 move_it_in_display_line at the start of
11093 this function. */
11094 abort ();
a2889657 11095 }
a2889657 11096 }
5f5c8ee5
GM
11097
11098 row->ascent = max (row->ascent, it->max_ascent);
11099 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11100 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11101 row->phys_height = max (row->phys_height,
11102 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11103
11104 /* End of this display line if row is continued. */
11105 if (row->continued_p)
11106 break;
a2889657 11107 }
a2889657 11108
5f5c8ee5
GM
11109 /* Is this a line end? If yes, we're also done, after making
11110 sure that a non-default face is extended up to the right
11111 margin of the window. */
11112 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 11113 {
5f5c8ee5
GM
11114 int used_before = row->used[TEXT_AREA];
11115
11116 /* Add a space at the end of the line that is used to
11117 display the cursor there. */
11118 append_space (it, 0);
11119
11120 /* Extend the face to the end of the line. */
11121 extend_face_to_end_of_line (it);
11122
11123 /* Make sure we have the position. */
11124 if (used_before == 0)
11125 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
11126
11127 /* Consume the line end. This skips over invisible lines. */
11128 set_iterator_to_next (it);
11129 it->continuation_lines_width = 0;
11130 break;
1c9241f5 11131 }
a2889657 11132
5f5c8ee5
GM
11133 /* Proceed with next display element. Note that this skips
11134 over lines invisible because of selective display. */
11135 set_iterator_to_next (it);
b1d1124b 11136
5f5c8ee5
GM
11137 /* If we truncate lines, we are done when the last displayed
11138 glyphs reach past the right margin of the window. */
11139 if (it->truncate_lines_p
11140 && (FRAME_WINDOW_P (it->f)
11141 ? (it->current_x >= it->last_visible_x)
11142 : (it->current_x > it->last_visible_x)))
75d13c64 11143 {
5f5c8ee5
GM
11144 /* Maybe add truncation glyphs. */
11145 if (!FRAME_WINDOW_P (it->f))
11146 {
11147 --it->glyph_row->used[TEXT_AREA];
11148 produce_special_glyphs (it, IT_TRUNCATION);
11149 }
11150
11151 row->truncated_on_right_p = 1;
11152 it->continuation_lines_width = 0;
312246d1 11153 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
11154 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
11155 it->hpos = hpos_before;
11156 it->current_x = x_before;
11157 break;
75d13c64 11158 }
a2889657 11159 }
a2889657 11160
5f5c8ee5
GM
11161 /* If line is not empty and hscrolled, maybe insert truncation glyphs
11162 at the left window margin. */
11163 if (it->first_visible_x
11164 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
11165 {
11166 if (!FRAME_WINDOW_P (it->f))
11167 insert_left_trunc_glyphs (it);
11168 row->truncated_on_left_p = 1;
11169 }
a2889657 11170
5f5c8ee5
GM
11171 /* If the start of this line is the overlay arrow-position, then
11172 mark this glyph row as the one containing the overlay arrow.
11173 This is clearly a mess with variable size fonts. It would be
11174 better to let it be displayed like cursors under X. */
e24c997d 11175 if (MARKERP (Voverlay_arrow_position)
a2889657 11176 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
11177 && (MATRIX_ROW_START_CHARPOS (row)
11178 == marker_position (Voverlay_arrow_position))
e24c997d 11179 && STRINGP (Voverlay_arrow_string)
a2889657
JB
11180 && ! overlay_arrow_seen)
11181 {
5f5c8ee5
GM
11182 /* Overlay arrow in window redisplay is a bitmap. */
11183 if (!FRAME_WINDOW_P (it->f))
c4628384 11184 {
5f5c8ee5
GM
11185 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
11186 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
11187 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
11188 struct glyph *p = row->glyphs[TEXT_AREA];
11189 struct glyph *p2, *end;
11190
11191 /* Copy the arrow glyphs. */
11192 while (glyph < arrow_end)
11193 *p++ = *glyph++;
11194
11195 /* Throw away padding glyphs. */
11196 p2 = p;
11197 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
11198 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
11199 ++p2;
11200 if (p2 > p)
212e4f87 11201 {
5f5c8ee5
GM
11202 while (p2 < end)
11203 *p++ = *p2++;
11204 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 11205 }
c4628384 11206 }
5f5c8ee5 11207
a2889657 11208 overlay_arrow_seen = 1;
5f5c8ee5 11209 row->overlay_arrow_p = 1;
a2889657
JB
11210 }
11211
5f5c8ee5
GM
11212 /* Compute pixel dimensions of this line. */
11213 compute_line_metrics (it);
11214
11215 /* Remember the position at which this line ends. */
11216 row->end = it->current;
11217
11218 /* Maybe set the cursor. If you change this, it's probably a good
11219 idea to also change the code in redisplay_window for cursor
11220 movement in an unchanged window. */
11221 if (it->w->cursor.vpos < 0
11222 && PT >= MATRIX_ROW_START_CHARPOS (row)
11223 && MATRIX_ROW_END_CHARPOS (row) >= PT
11224 && !(MATRIX_ROW_END_CHARPOS (row) == PT
11225 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
11226 || !row->ends_at_zv_p)))
11227 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
11228
11229 /* Highlight trailing whitespace. */
8f897821 11230 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
11231 highlight_trailing_whitespace (it->f, it->glyph_row);
11232
11233 /* Prepare for the next line. This line starts horizontally at (X
11234 HPOS) = (0 0). Vertical positions are incremented. As a
11235 convenience for the caller, IT->glyph_row is set to the next
11236 row to be used. */
11237 it->current_x = it->hpos = 0;
11238 it->current_y += row->height;
11239 ++it->vpos;
11240 ++it->glyph_row;
11241 return row->displays_text_p;
a2889657 11242}
5f5c8ee5
GM
11243
11244
a2889657 11245\f
5f5c8ee5
GM
11246/***********************************************************************
11247 Menu Bar
11248 ***********************************************************************/
11249
11250/* Redisplay the menu bar in the frame for window W.
11251
11252 The menu bar of X frames that don't have X toolkit support is
11253 displayed in a special window W->frame->menu_bar_window.
11254
11255 The menu bar of terminal frames is treated specially as far as
11256 glyph matrices are concerned. Menu bar lines are not part of
11257 windows, so the update is done directly on the frame matrix rows
11258 for the menu bar. */
7ce2c095
RS
11259
11260static void
11261display_menu_bar (w)
11262 struct window *w;
11263{
5f5c8ee5
GM
11264 struct frame *f = XFRAME (WINDOW_FRAME (w));
11265 struct it it;
11266 Lisp_Object items;
8351baf2 11267 int i;
7ce2c095 11268
5f5c8ee5 11269 /* Don't do all this for graphical frames. */
dc937613 11270#ifdef HAVE_NTGUI
d129c4c2
KH
11271 if (!NILP (Vwindow_system))
11272 return;
dc937613 11273#endif
dc937613 11274#ifdef USE_X_TOOLKIT
d3413a53 11275 if (FRAME_X_P (f))
7ce2c095 11276 return;
5f5c8ee5
GM
11277#endif
11278
11279#ifdef USE_X_TOOLKIT
11280 xassert (!FRAME_WINDOW_P (f));
11281 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MODE_LINE_FACE_ID);
11282 it.first_visible_x = 0;
11283 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11284#else /* not USE_X_TOOLKIT */
11285 if (FRAME_WINDOW_P (f))
11286 {
11287 /* Menu bar lines are displayed in the desired matrix of the
11288 dummy window menu_bar_window. */
11289 struct window *menu_w;
11290 xassert (WINDOWP (f->menu_bar_window));
11291 menu_w = XWINDOW (f->menu_bar_window);
11292 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
11293 MODE_LINE_FACE_ID);
11294 it.first_visible_x = 0;
11295 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11296 }
11297 else
11298 {
11299 /* This is a TTY frame, i.e. character hpos/vpos are used as
11300 pixel x/y. */
11301 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
11302 MODE_LINE_FACE_ID);
11303 it.first_visible_x = 0;
11304 it.last_visible_x = FRAME_WIDTH (f);
11305 }
11306#endif /* not USE_X_TOOLKIT */
11307
11308 /* Clear all rows of the menu bar. */
11309 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
11310 {
11311 struct glyph_row *row = it.glyph_row + i;
11312 clear_glyph_row (row);
11313 row->enabled_p = 1;
11314 row->full_width_p = 1;
11315 }
7ce2c095 11316
5f5c8ee5
GM
11317 /* Make the first line of the menu bar appear in reverse video. */
11318 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
7ce2c095 11319
5f5c8ee5
GM
11320 /* Display all items of the menu bar. */
11321 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 11322 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 11323 {
5f5c8ee5
GM
11324 Lisp_Object string;
11325
11326 /* Stop at nil string. */
8351baf2
RS
11327 string = XVECTOR (items)->contents[i + 1];
11328 if (NILP (string))
11329 break;
2d66ad19 11330
5f5c8ee5
GM
11331 /* Remember where item was displayed. */
11332 XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos);
7ce2c095 11333
5f5c8ee5
GM
11334 /* Display the item, pad with one space. */
11335 if (it.current_x < it.last_visible_x)
11336 display_string (NULL, string, Qnil, 0, 0, &it,
11337 XSTRING (string)->size + 1, 0, 0, -1);
7ce2c095
RS
11338 }
11339
2d66ad19 11340 /* Fill out the line with spaces. */
5f5c8ee5
GM
11341 if (it.current_x < it.last_visible_x)
11342 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 11343
5f5c8ee5
GM
11344 /* Compute the total height of the lines. */
11345 compute_line_metrics (&it);
7ce2c095 11346}
5f5c8ee5
GM
11347
11348
7ce2c095 11349\f
5f5c8ee5
GM
11350/***********************************************************************
11351 Mode Line
11352 ***********************************************************************/
11353
11354/* Display the mode and/or top line of window W. */
a2889657
JB
11355
11356static void
5f5c8ee5 11357display_mode_lines (w)
a2889657
JB
11358 struct window *w;
11359{
5f5c8ee5 11360 /* These will be set while the mode line specs are processed. */
aa6d10fa 11361 line_number_displayed = 0;
155ef550 11362 w->column_number_displayed = Qnil;
aa6d10fa 11363
5f5c8ee5 11364 if (WINDOW_WANTS_MODELINE_P (w))
045dee35
GM
11365 display_mode_line (w, MODE_LINE_FACE_ID,
11366 current_buffer->mode_line_format);
5f5c8ee5 11367
045dee35
GM
11368 if (WINDOW_WANTS_HEADER_LINE_P (w))
11369 display_mode_line (w, HEADER_LINE_FACE_ID,
11370 current_buffer->header_line_format);
5f5c8ee5 11371}
03b294dc 11372
03b294dc 11373
5f5c8ee5 11374/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 11375 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
5f5c8ee5 11376 FORMAT is the mode line format to display. */
03b294dc 11377
5f5c8ee5
GM
11378static void
11379display_mode_line (w, face_id, format)
11380 struct window *w;
11381 enum face_id face_id;
11382 Lisp_Object format;
11383{
11384 struct it it;
11385 struct face *face;
03b294dc 11386
5f5c8ee5
GM
11387 init_iterator (&it, w, -1, -1, NULL, face_id);
11388 prepare_desired_row (it.glyph_row);
11389
11390 /* Temporarily make frame's keyboard the current kboard so that
11391 kboard-local variables in the mode_line_format will get the right
11392 values. */
11393 push_frame_kboard (it.f);
11394 display_mode_element (&it, 0, 0, 0, format);
11395 pop_frame_kboard ();
a2889657 11396
5f5c8ee5
GM
11397 /* Fill up with spaces. */
11398 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
11399
11400 compute_line_metrics (&it);
11401 it.glyph_row->full_width_p = 1;
11402 it.glyph_row->mode_line_p = 1;
11403 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
11404 it.glyph_row->continued_p = 0;
11405 it.glyph_row->truncated_on_left_p = 0;
11406 it.glyph_row->truncated_on_right_p = 0;
11407
11408 /* Make a 3D mode-line have a shadow at its right end. */
11409 face = FACE_FROM_ID (it.f, face_id);
11410 extend_face_to_end_of_line (&it);
11411 if (face->box != FACE_NO_BOX)
d7eb09a0 11412 {
5f5c8ee5
GM
11413 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
11414 + it.glyph_row->used[TEXT_AREA] - 1);
11415 last->right_box_line_p = 1;
d7eb09a0 11416 }
a2889657
JB
11417}
11418
a2889657 11419
5f5c8ee5
GM
11420/* Contribute ELT to the mode line for window IT->w. How it
11421 translates into text depends on its data type.
a2889657 11422
5f5c8ee5 11423 IT describes the display environment in which we display, as usual.
a2889657
JB
11424
11425 DEPTH is the depth in recursion. It is used to prevent
11426 infinite recursion here.
11427
5f5c8ee5
GM
11428 FIELD_WIDTH is the number of characters the display of ELT should
11429 occupy in the mode line, and PRECISION is the maximum number of
11430 characters to display from ELT's representation. See
11431 display_string for details. *
a2889657 11432
5f5c8ee5 11433 Returns the hpos of the end of the text generated by ELT. */
a2889657
JB
11434
11435static int
5f5c8ee5
GM
11436display_mode_element (it, depth, field_width, precision, elt)
11437 struct it *it;
a2889657 11438 int depth;
5f5c8ee5
GM
11439 int field_width, precision;
11440 Lisp_Object elt;
a2889657 11441{
5f5c8ee5
GM
11442 int n = 0, field, prec;
11443
a2889657
JB
11444 tail_recurse:
11445 if (depth > 10)
11446 goto invalid;
11447
11448 depth++;
11449
0220c518 11450 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
11451 {
11452 case Lisp_String:
11453 {
11454 /* A string: output it and check for %-constructs within it. */
5f5c8ee5
GM
11455 unsigned char c;
11456 unsigned char *this = XSTRING (elt)->data;
11457 unsigned char *lisp_string = this;
11458
11459 while ((precision <= 0 || n < precision)
11460 && *this
11461 && (frame_title_ptr
11462 || it->current_x < it->last_visible_x))
a2889657
JB
11463 {
11464 unsigned char *last = this;
5f5c8ee5
GM
11465
11466 /* Advance to end of string or next format specifier. */
a2889657
JB
11467 while ((c = *this++) != '\0' && c != '%')
11468 ;
5f5c8ee5 11469
a2889657
JB
11470 if (this - 1 != last)
11471 {
5f5c8ee5
GM
11472 /* Output to end of string or up to '%'. Field width
11473 is length of string. Don't output more than
11474 PRECISION allows us. */
11475 prec = --this - last;
11476 if (precision > 0 && prec > precision - n)
11477 prec = precision - n;
11478
d39b6696 11479 if (frame_title_ptr)
5f5c8ee5 11480 n += store_frame_title (last, prec, prec);
d39b6696 11481 else
5f5c8ee5
GM
11482 n += display_string (NULL, elt, Qnil, 0, last - lisp_string,
11483 it, 0, prec, 0, -1);
a2889657
JB
11484 }
11485 else /* c == '%' */
11486 {
5f5c8ee5
GM
11487 unsigned char *percent_position = this;
11488
11489 /* Get the specified minimum width. Zero means
11490 don't pad. */
11491 field = 0;
a2889657 11492 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 11493 field = field * 10 + c - '0';
a2889657 11494
5f5c8ee5
GM
11495 /* Don't pad beyond the total padding allowed. */
11496 if (field_width - n > 0 && field > field_width - n)
11497 field = field_width - n;
a2889657 11498
5f5c8ee5
GM
11499 /* Note that either PRECISION <= 0 or N < PRECISION. */
11500 prec = precision - n;
11501
a2889657 11502 if (c == 'M')
5f5c8ee5
GM
11503 n += display_mode_element (it, depth, field, prec,
11504 Vglobal_mode_string);
a2889657 11505 else if (c != 0)
d39b6696 11506 {
5f5c8ee5
GM
11507 unsigned char *spec
11508 = decode_mode_spec (it->w, c, field, prec);
11509
d39b6696 11510 if (frame_title_ptr)
5f5c8ee5 11511 n += store_frame_title (spec, field, prec);
d39b6696 11512 else
5f5c8ee5
GM
11513 {
11514 int nglyphs_before
11515 = it->glyph_row->used[TEXT_AREA];
11516 int charpos
11517 = percent_position - XSTRING (elt)->data;
11518 int nwritten
11519 = display_string (spec, Qnil, elt, charpos, 0, it,
11520 field, prec, 0, -1);
11521
11522 /* Assign to the glyphs written above the
11523 string where the `%x' came from, position
11524 of the `%'. */
11525 if (nwritten > 0)
11526 {
11527 struct glyph *glyph
11528 = (it->glyph_row->glyphs[TEXT_AREA]
11529 + nglyphs_before);
11530 int i;
11531
11532 for (i = 0; i < nwritten; ++i)
11533 {
11534 glyph[i].object = elt;
11535 glyph[i].charpos = charpos;
11536 }
11537
11538 n += nwritten;
11539 }
11540 }
d39b6696 11541 }
a2889657
JB
11542 }
11543 }
11544 }
11545 break;
11546
11547 case Lisp_Symbol:
11548 /* A symbol: process the value of the symbol recursively
11549 as if it appeared here directly. Avoid error if symbol void.
11550 Special case: if value of symbol is a string, output the string
11551 literally. */
11552 {
11553 register Lisp_Object tem;
11554 tem = Fboundp (elt);
265a9e55 11555 if (!NILP (tem))
a2889657
JB
11556 {
11557 tem = Fsymbol_value (elt);
11558 /* If value is a string, output that string literally:
11559 don't check for % within it. */
e24c997d 11560 if (STRINGP (tem))
d39b6696 11561 {
5f5c8ee5
GM
11562 prec = XSTRING (tem)->size;
11563 if (precision > 0 && prec > precision - n)
11564 prec = precision - n;
d39b6696 11565 if (frame_title_ptr)
5f5c8ee5 11566 n += store_frame_title (XSTRING (tem)->data, -1, prec);
d39b6696 11567 else
5f5c8ee5
GM
11568 n += display_string (NULL, tem, Qnil, 0, 0, it,
11569 0, prec, 0, -1);
d39b6696 11570 }
a2889657 11571 else if (!EQ (tem, elt))
5f5c8ee5
GM
11572 {
11573 /* Give up right away for nil or t. */
11574 elt = tem;
11575 goto tail_recurse;
11576 }
a2889657
JB
11577 }
11578 }
11579 break;
11580
11581 case Lisp_Cons:
11582 {
11583 register Lisp_Object car, tem;
11584
11585 /* A cons cell: three distinct cases.
11586 If first element is a string or a cons, process all the elements
11587 and effectively concatenate them.
11588 If first element is a negative number, truncate displaying cdr to
11589 at most that many characters. If positive, pad (with spaces)
11590 to at least that many characters.
11591 If first element is a symbol, process the cadr or caddr recursively
11592 according to whether the symbol's value is non-nil or nil. */
9472f927 11593 car = XCAR (elt);
5f5c8ee5
GM
11594 if (EQ (car, QCeval) && CONSP (XCDR (elt)))
11595 {
11596 /* An element of the form (:eval FORM) means evaluate FORM
11597 and use the result as mode line elements. */
11598 struct gcpro gcpro1;
11599 Lisp_Object spec;
11600
11601 spec = eval_form (XCAR (XCDR (elt)));
11602 GCPRO1 (spec);
11603 n += display_mode_element (it, depth, field_width - n,
11604 precision - n, spec);
11605 UNGCPRO;
11606 }
11607 else if (SYMBOLP (car))
a2889657
JB
11608 {
11609 tem = Fboundp (car);
9472f927 11610 elt = XCDR (elt);
e24c997d 11611 if (!CONSP (elt))
a2889657
JB
11612 goto invalid;
11613 /* elt is now the cdr, and we know it is a cons cell.
11614 Use its car if CAR has a non-nil value. */
265a9e55 11615 if (!NILP (tem))
a2889657
JB
11616 {
11617 tem = Fsymbol_value (car);
265a9e55 11618 if (!NILP (tem))
9472f927
GM
11619 {
11620 elt = XCAR (elt);
11621 goto tail_recurse;
11622 }
a2889657
JB
11623 }
11624 /* Symbol's value is nil (or symbol is unbound)
11625 Get the cddr of the original list
11626 and if possible find the caddr and use that. */
9472f927 11627 elt = XCDR (elt);
265a9e55 11628 if (NILP (elt))
a2889657 11629 break;
e24c997d 11630 else if (!CONSP (elt))
a2889657 11631 goto invalid;
9472f927 11632 elt = XCAR (elt);
a2889657
JB
11633 goto tail_recurse;
11634 }
e24c997d 11635 else if (INTEGERP (car))
a2889657
JB
11636 {
11637 register int lim = XINT (car);
9472f927 11638 elt = XCDR (elt);
a2889657 11639 if (lim < 0)
5f5c8ee5
GM
11640 {
11641 /* Negative int means reduce maximum width. */
11642 if (precision <= 0)
11643 precision = -lim;
11644 else
11645 precision = min (precision, -lim);
11646 }
a2889657
JB
11647 else if (lim > 0)
11648 {
11649 /* Padding specified. Don't let it be more than
11650 current maximum. */
5f5c8ee5
GM
11651 if (precision > 0)
11652 lim = min (precision, lim);
11653
a2889657
JB
11654 /* If that's more padding than already wanted, queue it.
11655 But don't reduce padding already specified even if
11656 that is beyond the current truncation point. */
5f5c8ee5 11657 field_width = max (lim, field_width);
a2889657
JB
11658 }
11659 goto tail_recurse;
11660 }
e24c997d 11661 else if (STRINGP (car) || CONSP (car))
a2889657
JB
11662 {
11663 register int limit = 50;
5f5c8ee5
GM
11664 /* Limit is to protect against circular lists. */
11665 while (CONSP (elt)
11666 && --limit > 0
11667 && (precision <= 0 || n < precision))
a2889657 11668 {
5f5c8ee5 11669 n += display_mode_element (it, depth, field_width - n,
9472f927
GM
11670 precision - n, XCAR (elt));
11671 elt = XCDR (elt);
a2889657
JB
11672 }
11673 }
11674 }
11675 break;
11676
11677 default:
11678 invalid:
d39b6696 11679 if (frame_title_ptr)
5f5c8ee5 11680 n += store_frame_title ("*invalid*", 0, precision - n);
d39b6696 11681 else
5f5c8ee5
GM
11682 n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
11683 precision - n, 0, 0);
11684 return n;
a2889657
JB
11685 }
11686
5f5c8ee5
GM
11687 /* Pad to FIELD_WIDTH. */
11688 if (field_width > 0 && n < field_width)
11689 {
11690 if (frame_title_ptr)
11691 n += store_frame_title ("", field_width - n, 0);
11692 else
11693 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
11694 0, 0, 0);
11695 }
11696
11697 return n;
a2889657 11698}
5f5c8ee5
GM
11699
11700
766525bc
RS
11701/* Write a null-terminated, right justified decimal representation of
11702 the positive integer D to BUF using a minimal field width WIDTH. */
11703
11704static void
11705pint2str (buf, width, d)
11706 register char *buf;
11707 register int width;
11708 register int d;
11709{
11710 register char *p = buf;
11711
11712 if (d <= 0)
5f5c8ee5 11713 *p++ = '0';
766525bc 11714 else
5f5c8ee5 11715 {
766525bc 11716 while (d > 0)
5f5c8ee5 11717 {
766525bc
RS
11718 *p++ = d % 10 + '0';
11719 d /= 10;
5f5c8ee5
GM
11720 }
11721 }
11722
11723 for (width -= (int) (p - buf); width > 0; --width)
11724 *p++ = ' ';
766525bc
RS
11725 *p-- = '\0';
11726 while (p > buf)
5f5c8ee5 11727 {
766525bc
RS
11728 d = *buf;
11729 *buf++ = *p;
11730 *p-- = d;
5f5c8ee5 11731 }
766525bc
RS
11732}
11733
5f5c8ee5 11734/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
11735 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
11736 type of CODING_SYSTEM. Return updated pointer into BUF. */
11737
6693a99a 11738static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 11739
1c9241f5
KH
11740static char *
11741decode_mode_spec_coding (coding_system, buf, eol_flag)
11742 Lisp_Object coding_system;
11743 register char *buf;
11744 int eol_flag;
11745{
1e1078d6 11746 Lisp_Object val;
916848d8 11747 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
302f2b38
EZ
11748 unsigned char *eol_str;
11749 int eol_str_len;
11750 /* The EOL conversion we are using. */
11751 Lisp_Object eoltype;
1e1078d6
RS
11752
11753 val = coding_system;
1c9241f5
KH
11754
11755 if (NILP (val)) /* Not yet decided. */
11756 {
916848d8
RS
11757 if (multibyte)
11758 *buf++ = '-';
21e989e3 11759 if (eol_flag)
302f2b38 11760 eoltype = eol_mnemonic_undecided;
1e1078d6 11761 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
11762 }
11763 else
11764 {
1e1078d6
RS
11765 Lisp_Object eolvalue;
11766
11767 eolvalue = Fget (coding_system, Qeol_type);
11768
1c9241f5 11769 while (!NILP (val) && SYMBOLP (val))
1e1078d6
RS
11770 {
11771 val = Fget (val, Qcoding_system);
11772 if (NILP (eolvalue))
b070c1d7 11773 eolvalue = Fget (val, Qeol_type);
1e1078d6
RS
11774 }
11775
916848d8
RS
11776 if (multibyte)
11777 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
11778
1c9241f5
KH
11779 if (eol_flag)
11780 {
1e1078d6
RS
11781 /* The EOL conversion that is normal on this system. */
11782
11783 if (NILP (eolvalue)) /* Not yet decided. */
11784 eoltype = eol_mnemonic_undecided;
11785 else if (VECTORP (eolvalue)) /* Not yet decided. */
11786 eoltype = eol_mnemonic_undecided;
11787 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
11788 eoltype = (XFASTINT (eolvalue) == 0
11789 ? eol_mnemonic_unix
11790 : (XFASTINT (eolvalue) == 1
11791 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
11792 }
11793 }
5f5c8ee5 11794
302f2b38
EZ
11795 if (eol_flag)
11796 {
11797 /* Mention the EOL conversion if it is not the usual one. */
11798 if (STRINGP (eoltype))
11799 {
11800 eol_str = XSTRING (eoltype)->data;
11801 eol_str_len = XSTRING (eoltype)->size;
11802 }
f30b3499
KH
11803 else if (INTEGERP (eoltype)
11804 && CHAR_VALID_P (XINT (eoltype), 0))
11805 {
f30b3499
KH
11806 unsigned char work[4];
11807
11808 eol_str_len = CHAR_STRING (XINT (eoltype), work, eol_str);
11809 }
302f2b38
EZ
11810 else
11811 {
11812 eol_str = invalid_eol_type;
11813 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 11814 }
f30b3499 11815 bcopy (eol_str, buf, eol_str_len);
302f2b38 11816 buf += eol_str_len;
1c9241f5 11817 }
302f2b38 11818
1c9241f5
KH
11819 return buf;
11820}
11821
a2889657 11822/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
11823 generated by character C. PRECISION >= 0 means don't return a
11824 string longer than that value. FIELD_WIDTH > 0 means pad the
11825 string returned with spaces to that value. */
a2889657 11826
11e82b76
JB
11827static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
11828
a2889657 11829static char *
5f5c8ee5 11830decode_mode_spec (w, c, field_width, precision)
a2889657
JB
11831 struct window *w;
11832 register char c;
5f5c8ee5 11833 int field_width, precision;
a2889657 11834{
0b67772d 11835 Lisp_Object obj;
5f5c8ee5
GM
11836 struct frame *f = XFRAME (WINDOW_FRAME (w));
11837 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 11838 struct buffer *b = XBUFFER (w->buffer);
a2889657 11839
0b67772d 11840 obj = Qnil;
a2889657
JB
11841
11842 switch (c)
11843 {
1af9f229
RS
11844 case '*':
11845 if (!NILP (b->read_only))
11846 return "%";
11847 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
11848 return "*";
11849 return "-";
11850
11851 case '+':
11852 /* This differs from %* only for a modified read-only buffer. */
11853 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
11854 return "*";
11855 if (!NILP (b->read_only))
11856 return "%";
11857 return "-";
11858
11859 case '&':
11860 /* This differs from %* in ignoring read-only-ness. */
11861 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
11862 return "*";
11863 return "-";
11864
11865 case '%':
11866 return "%";
11867
11868 case '[':
11869 {
11870 int i;
11871 char *p;
11872
11873 if (command_loop_level > 5)
11874 return "[[[... ";
11875 p = decode_mode_spec_buf;
11876 for (i = 0; i < command_loop_level; i++)
11877 *p++ = '[';
11878 *p = 0;
11879 return decode_mode_spec_buf;
11880 }
11881
11882 case ']':
11883 {
11884 int i;
11885 char *p;
11886
11887 if (command_loop_level > 5)
11888 return " ...]]]";
11889 p = decode_mode_spec_buf;
11890 for (i = 0; i < command_loop_level; i++)
11891 *p++ = ']';
11892 *p = 0;
11893 return decode_mode_spec_buf;
11894 }
11895
11896 case '-':
11897 {
1af9f229 11898 register int i;
5f5c8ee5
GM
11899
11900 /* Let lots_of_dashes be a string of infinite length. */
11901 if (field_width <= 0
11902 || field_width > sizeof (lots_of_dashes))
1af9f229 11903 {
5f5c8ee5
GM
11904 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
11905 decode_mode_spec_buf[i] = '-';
11906 decode_mode_spec_buf[i] = '\0';
11907 return decode_mode_spec_buf;
1af9f229 11908 }
5f5c8ee5
GM
11909 else
11910 return lots_of_dashes;
1af9f229
RS
11911 }
11912
a2889657 11913 case 'b':
d39b6696 11914 obj = b->name;
a2889657
JB
11915 break;
11916
1af9f229
RS
11917 case 'c':
11918 {
11919 int col = current_column ();
11920 XSETFASTINT (w->column_number_displayed, col);
5f5c8ee5 11921 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
11922 return decode_mode_spec_buf;
11923 }
11924
11925 case 'F':
11926 /* %F displays the frame name. */
5f5c8ee5 11927 if (!NILP (f->title))
95184b48 11928 return (char *) XSTRING (f->title)->data;
fd8ff63d 11929 if (f->explicit_name || ! FRAME_WINDOW_P (f))
95184b48 11930 return (char *) XSTRING (f->name)->data;
9c6da96f 11931 return "Emacs";
1af9f229 11932
a2889657 11933 case 'f':
d39b6696 11934 obj = b->filename;
a2889657
JB
11935 break;
11936
aa6d10fa
RS
11937 case 'l':
11938 {
12adba34
RS
11939 int startpos = XMARKER (w->start)->charpos;
11940 int startpos_byte = marker_byte_position (w->start);
11941 int line, linepos, linepos_byte, topline;
aa6d10fa 11942 int nlines, junk;
aa6d10fa
RS
11943 int height = XFASTINT (w->height);
11944
11945 /* If we decided that this buffer isn't suitable for line numbers,
11946 don't forget that too fast. */
11947 if (EQ (w->base_line_pos, w->buffer))
766525bc 11948 goto no_value;
5300fd39
RS
11949 /* But do forget it, if the window shows a different buffer now. */
11950 else if (BUFFERP (w->base_line_pos))
11951 w->base_line_pos = Qnil;
aa6d10fa
RS
11952
11953 /* If the buffer is very big, don't waste time. */
d39b6696 11954 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
aa6d10fa
RS
11955 {
11956 w->base_line_pos = Qnil;
11957 w->base_line_number = Qnil;
766525bc 11958 goto no_value;
aa6d10fa
RS
11959 }
11960
11961 if (!NILP (w->base_line_number)
11962 && !NILP (w->base_line_pos)
12adba34 11963 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
11964 {
11965 line = XFASTINT (w->base_line_number);
11966 linepos = XFASTINT (w->base_line_pos);
12adba34 11967 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
11968 }
11969 else
11970 {
11971 line = 1;
d39b6696 11972 linepos = BUF_BEGV (b);
12adba34 11973 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
11974 }
11975
11976 /* Count lines from base line to window start position. */
12adba34
RS
11977 nlines = display_count_lines (linepos, linepos_byte,
11978 startpos_byte,
11979 startpos, &junk);
aa6d10fa
RS
11980
11981 topline = nlines + line;
11982
11983 /* Determine a new base line, if the old one is too close
11984 or too far away, or if we did not have one.
11985 "Too close" means it's plausible a scroll-down would
11986 go back past it. */
d39b6696 11987 if (startpos == BUF_BEGV (b))
aa6d10fa 11988 {
c2213350
KH
11989 XSETFASTINT (w->base_line_number, topline);
11990 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
11991 }
11992 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 11993 || linepos == BUF_BEGV (b))
aa6d10fa 11994 {
d39b6696 11995 int limit = BUF_BEGV (b);
12adba34 11996 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 11997 int position;
5d121aec 11998 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
11999
12000 if (startpos - distance > limit)
12adba34
RS
12001 {
12002 limit = startpos - distance;
12003 limit_byte = CHAR_TO_BYTE (limit);
12004 }
aa6d10fa 12005
12adba34
RS
12006 nlines = display_count_lines (startpos, startpos_byte,
12007 limit_byte,
12008 - (height * 2 + 30),
aa6d10fa
RS
12009 &position);
12010 /* If we couldn't find the lines we wanted within
5d121aec 12011 line_number_display_limit_width chars per line,
aa6d10fa 12012 give up on line numbers for this window. */
12adba34 12013 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
12014 {
12015 w->base_line_pos = w->buffer;
12016 w->base_line_number = Qnil;
766525bc 12017 goto no_value;
aa6d10fa
RS
12018 }
12019
c2213350 12020 XSETFASTINT (w->base_line_number, topline - nlines);
12adba34 12021 XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
aa6d10fa
RS
12022 }
12023
12024 /* Now count lines from the start pos to point. */
12adba34
RS
12025 nlines = display_count_lines (startpos, startpos_byte,
12026 PT_BYTE, PT, &junk);
aa6d10fa
RS
12027
12028 /* Record that we did display the line number. */
12029 line_number_displayed = 1;
12030
12031 /* Make the string to show. */
5f5c8ee5 12032 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 12033 return decode_mode_spec_buf;
766525bc
RS
12034 no_value:
12035 {
12036 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
12037 int pad = field_width - 2;
12038 while (pad-- > 0)
12039 *p++ = ' ';
12040 *p++ = '?';
12041 *p = '?';
766525bc
RS
12042 return decode_mode_spec_buf;
12043 }
aa6d10fa
RS
12044 }
12045 break;
12046
a2889657 12047 case 'm':
d39b6696 12048 obj = b->mode_name;
a2889657
JB
12049 break;
12050
12051 case 'n':
d39b6696 12052 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
12053 return " Narrow";
12054 break;
12055
a2889657
JB
12056 case 'p':
12057 {
12058 int pos = marker_position (w->start);
d39b6696 12059 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 12060
d39b6696 12061 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 12062 {
d39b6696 12063 if (pos <= BUF_BEGV (b))
a2889657
JB
12064 return "All";
12065 else
12066 return "Bottom";
12067 }
d39b6696 12068 else if (pos <= BUF_BEGV (b))
a2889657
JB
12069 return "Top";
12070 else
12071 {
3c7d31b9
RS
12072 if (total > 1000000)
12073 /* Do it differently for a large value, to avoid overflow. */
12074 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12075 else
12076 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
12077 /* We can't normally display a 3-digit number,
12078 so get us a 2-digit number that is close. */
12079 if (total == 100)
12080 total = 99;
12081 sprintf (decode_mode_spec_buf, "%2d%%", total);
12082 return decode_mode_spec_buf;
12083 }
12084 }
12085
8ffcb79f
RS
12086 /* Display percentage of size above the bottom of the screen. */
12087 case 'P':
12088 {
12089 int toppos = marker_position (w->start);
d39b6696
KH
12090 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
12091 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 12092
d39b6696 12093 if (botpos >= BUF_ZV (b))
8ffcb79f 12094 {
d39b6696 12095 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12096 return "All";
12097 else
12098 return "Bottom";
12099 }
12100 else
12101 {
3c7d31b9
RS
12102 if (total > 1000000)
12103 /* Do it differently for a large value, to avoid overflow. */
12104 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12105 else
12106 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
12107 /* We can't normally display a 3-digit number,
12108 so get us a 2-digit number that is close. */
12109 if (total == 100)
12110 total = 99;
d39b6696 12111 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12112 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
12113 else
12114 sprintf (decode_mode_spec_buf, "%2d%%", total);
12115 return decode_mode_spec_buf;
12116 }
12117 }
12118
1af9f229
RS
12119 case 's':
12120 /* status of process */
12121 obj = Fget_buffer_process (w->buffer);
12122 if (NILP (obj))
12123 return "no process";
12124#ifdef subprocesses
12125 obj = Fsymbol_name (Fprocess_status (obj));
12126#endif
12127 break;
d39b6696 12128
1af9f229
RS
12129 case 't': /* indicate TEXT or BINARY */
12130#ifdef MODE_LINE_BINARY_TEXT
12131 return MODE_LINE_BINARY_TEXT (b);
12132#else
12133 return "T";
12134#endif
1c9241f5
KH
12135
12136 case 'z':
12137 /* coding-system (not including end-of-line format) */
12138 case 'Z':
12139 /* coding-system (including end-of-line type) */
12140 {
12141 int eol_flag = (c == 'Z');
539b4d41 12142 char *p = decode_mode_spec_buf;
1c9241f5 12143
d30e754b 12144 if (! FRAME_WINDOW_P (f))
1c9241f5 12145 {
11c52c4f
RS
12146 /* No need to mention EOL here--the terminal never needs
12147 to do EOL conversion. */
12148 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
12149 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 12150 }
f13c925f 12151 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 12152 p, eol_flag);
f13c925f 12153
11c52c4f 12154#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
12155#ifdef subprocesses
12156 obj = Fget_buffer_process (Fcurrent_buffer ());
12157 if (PROCESSP (obj))
12158 {
12159 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
12160 p, eol_flag);
12161 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
12162 p, eol_flag);
12163 }
12164#endif /* subprocesses */
11c52c4f 12165#endif /* 0 */
1c9241f5
KH
12166 *p = 0;
12167 return decode_mode_spec_buf;
12168 }
a2889657 12169 }
d39b6696 12170
e24c997d 12171 if (STRINGP (obj))
a2889657
JB
12172 return (char *) XSTRING (obj)->data;
12173 else
12174 return "";
12175}
5f5c8ee5
GM
12176
12177
12adba34
RS
12178/* Count up to COUNT lines starting from START / START_BYTE.
12179 But don't go beyond LIMIT_BYTE.
12180 Return the number of lines thus found (always nonnegative).
59b49f63 12181
12adba34 12182 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
12183
12184static int
12adba34
RS
12185display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
12186 int start, start_byte, limit_byte, count;
12187 int *byte_pos_ptr;
59b49f63 12188{
59b49f63
RS
12189 register unsigned char *cursor;
12190 unsigned char *base;
12191
12192 register int ceiling;
12193 register unsigned char *ceiling_addr;
12adba34 12194 int orig_count = count;
59b49f63
RS
12195
12196 /* If we are not in selective display mode,
12197 check only for newlines. */
12adba34
RS
12198 int selective_display = (!NILP (current_buffer->selective_display)
12199 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
12200
12201 if (count > 0)
12adba34
RS
12202 {
12203 while (start_byte < limit_byte)
12204 {
12205 ceiling = BUFFER_CEILING_OF (start_byte);
12206 ceiling = min (limit_byte - 1, ceiling);
12207 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
12208 base = (cursor = BYTE_POS_ADDR (start_byte));
12209 while (1)
12210 {
12211 if (selective_display)
12212 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
12213 ;
12214 else
12215 while (*cursor != '\n' && ++cursor != ceiling_addr)
12216 ;
12217
12218 if (cursor != ceiling_addr)
12219 {
12220 if (--count == 0)
12221 {
12222 start_byte += cursor - base + 1;
12223 *byte_pos_ptr = start_byte;
12224 return orig_count;
12225 }
12226 else
12227 if (++cursor == ceiling_addr)
12228 break;
12229 }
12230 else
12231 break;
12232 }
12233 start_byte += cursor - base;
12234 }
12235 }
59b49f63
RS
12236 else
12237 {
12adba34
RS
12238 while (start_byte > limit_byte)
12239 {
12240 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
12241 ceiling = max (limit_byte, ceiling);
12242 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
12243 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
12244 while (1)
12245 {
12adba34
RS
12246 if (selective_display)
12247 while (--cursor != ceiling_addr
12248 && *cursor != '\n' && *cursor != 015)
12249 ;
12250 else
12251 while (--cursor != ceiling_addr && *cursor != '\n')
12252 ;
12253
59b49f63
RS
12254 if (cursor != ceiling_addr)
12255 {
12256 if (++count == 0)
12257 {
12adba34
RS
12258 start_byte += cursor - base + 1;
12259 *byte_pos_ptr = start_byte;
12260 /* When scanning backwards, we should
12261 not count the newline posterior to which we stop. */
12262 return - orig_count - 1;
59b49f63
RS
12263 }
12264 }
12265 else
12266 break;
12267 }
12adba34
RS
12268 /* Here we add 1 to compensate for the last decrement
12269 of CURSOR, which took it past the valid range. */
12270 start_byte += cursor - base + 1;
59b49f63
RS
12271 }
12272 }
12273
12adba34 12274 *byte_pos_ptr = limit_byte;
aa6d10fa 12275
12adba34
RS
12276 if (count < 0)
12277 return - orig_count + count;
12278 return orig_count - count;
aa6d10fa 12279
12adba34 12280}
a2889657 12281
a2889657 12282
5f5c8ee5
GM
12283\f
12284/***********************************************************************
12285 Displaying strings
12286 ***********************************************************************/
278feba9 12287
5f5c8ee5 12288/* Display a NUL-terminated string, starting with index START.
a3788d53 12289
5f5c8ee5
GM
12290 If STRING is non-null, display that C string. Otherwise, the Lisp
12291 string LISP_STRING is displayed.
a2889657 12292
5f5c8ee5
GM
12293 If FACE_STRING is not nil, FACE_STRING_POS is a position in
12294 FACE_STRING. Display STRING or LISP_STRING with the face at
12295 FACE_STRING_POS in FACE_STRING:
a2889657 12296
5f5c8ee5
GM
12297 Display the string in the environment given by IT, but use the
12298 standard display table, temporarily.
a3788d53 12299
5f5c8ee5
GM
12300 FIELD_WIDTH is the minimum number of output glyphs to produce.
12301 If STRING has fewer characters than FIELD_WIDTH, pad to the right
12302 with spaces. If STRING has more characters, more than FIELD_WIDTH
12303 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
12304
12305 PRECISION is the maximum number of characters to output from
12306 STRING. PRECISION < 0 means don't truncate the string.
a2889657 12307
5f5c8ee5 12308 This is roughly equivalent to printf format specifiers:
a2889657 12309
5f5c8ee5
GM
12310 FIELD_WIDTH PRECISION PRINTF
12311 ----------------------------------------
12312 -1 -1 %s
12313 -1 10 %.10s
12314 10 -1 %10s
12315 20 10 %20.10s
a2889657 12316
5f5c8ee5
GM
12317 MULTIBYTE zero means do not display multibyte chars, > 0 means do
12318 display them, and < 0 means obey the current buffer's value of
12319 enable_multibyte_characters.
278feba9 12320
5f5c8ee5 12321 Value is the number of glyphs produced. */
b1d1124b 12322
5f5c8ee5
GM
12323static int
12324display_string (string, lisp_string, face_string, face_string_pos,
12325 start, it, field_width, precision, max_x, multibyte)
12326 unsigned char *string;
12327 Lisp_Object lisp_string;
12328 int start;
12329 struct it *it;
12330 int field_width, precision, max_x;
12331 int multibyte;
12332{
12333 int hpos_at_start = it->hpos;
12334 int saved_face_id = it->face_id;
12335 struct glyph_row *row = it->glyph_row;
12336
12337 /* Initialize the iterator IT for iteration over STRING beginning
12338 with index START. We assume that IT may be modified here (which
12339 means that display_line has to do something when displaying a
12340 mini-buffer prompt, which it does). */
12341 reseat_to_string (it, string, lisp_string, start,
12342 precision, field_width, multibyte);
12343
12344 /* If displaying STRING, set up the face of the iterator
12345 from LISP_STRING, if that's given. */
12346 if (STRINGP (face_string))
12347 {
12348 int endptr;
12349 struct face *face;
12350
12351 it->face_id
12352 = face_at_string_position (it->w, face_string, face_string_pos,
12353 0, it->region_beg_charpos,
12354 it->region_end_charpos,
12355 &endptr, it->base_face_id);
12356 face = FACE_FROM_ID (it->f, it->face_id);
12357 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 12358 }
a2889657 12359
5f5c8ee5
GM
12360 /* Set max_x to the maximum allowed X position. Don't let it go
12361 beyond the right edge of the window. */
12362 if (max_x <= 0)
12363 max_x = it->last_visible_x;
12364 else
12365 max_x = min (max_x, it->last_visible_x);
efc63ef0 12366
5f5c8ee5
GM
12367 /* Skip over display elements that are not visible. because IT->w is
12368 hscrolled. */
12369 if (it->current_x < it->first_visible_x)
12370 move_it_in_display_line_to (it, 100000, it->first_visible_x,
12371 MOVE_TO_POS | MOVE_TO_X);
a2889657 12372
5f5c8ee5
GM
12373 row->ascent = it->max_ascent;
12374 row->height = it->max_ascent + it->max_descent;
312246d1
GM
12375 row->phys_ascent = it->max_phys_ascent;
12376 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 12377
5f5c8ee5
GM
12378 /* This condition is for the case that we are called with current_x
12379 past last_visible_x. */
12380 while (it->current_x < max_x)
a2889657 12381 {
5f5c8ee5 12382 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 12383
5f5c8ee5
GM
12384 /* Get the next display element. */
12385 if (!get_next_display_element (it))
90adcf20 12386 break;
1c9241f5 12387
5f5c8ee5
GM
12388 /* Produce glyphs. */
12389 x_before = it->current_x;
12390 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
12391 PRODUCE_GLYPHS (it);
90adcf20 12392
5f5c8ee5
GM
12393 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
12394 i = 0;
12395 x = x_before;
12396 while (i < nglyphs)
a2889657 12397 {
5f5c8ee5
GM
12398 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
12399
12400 if (!it->truncate_lines_p
12401 && x + glyph->pixel_width > max_x)
12402 {
12403 /* End of continued line or max_x reached. */
12404 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
12405 it->current_x = x;
12406 break;
12407 }
12408 else if (x + glyph->pixel_width > it->first_visible_x)
12409 {
12410 /* Glyph is at least partially visible. */
12411 ++it->hpos;
12412 if (x < it->first_visible_x)
12413 it->glyph_row->x = x - it->first_visible_x;
12414 }
12415 else
a2889657 12416 {
5f5c8ee5
GM
12417 /* Glyph is off the left margin of the display area.
12418 Should not happen. */
12419 abort ();
a2889657 12420 }
5f5c8ee5
GM
12421
12422 row->ascent = max (row->ascent, it->max_ascent);
12423 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
12424 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
12425 row->phys_height = max (row->phys_height,
12426 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
12427 x += glyph->pixel_width;
12428 ++i;
a2889657 12429 }
5f5c8ee5
GM
12430
12431 /* Stop if max_x reached. */
12432 if (i < nglyphs)
12433 break;
12434
12435 /* Stop at line ends. */
12436 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 12437 {
5f5c8ee5
GM
12438 it->continuation_lines_width = 0;
12439 break;
a2889657 12440 }
1c9241f5 12441
5f5c8ee5 12442 set_iterator_to_next (it);
a688bb24 12443
5f5c8ee5
GM
12444 /* Stop if truncating at the right edge. */
12445 if (it->truncate_lines_p
12446 && it->current_x >= it->last_visible_x)
12447 {
12448 /* Add truncation mark, but don't do it if the line is
12449 truncated at a padding space. */
12450 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 12451 {
5f5c8ee5
GM
12452 if (!FRAME_WINDOW_P (it->f))
12453 produce_special_glyphs (it, IT_TRUNCATION);
12454 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 12455 }
5f5c8ee5 12456 break;
1c9241f5 12457 }
a2889657
JB
12458 }
12459
5f5c8ee5
GM
12460 /* Maybe insert a truncation at the left. */
12461 if (it->first_visible_x
12462 && IT_CHARPOS (*it) > 0)
a2889657 12463 {
5f5c8ee5
GM
12464 if (!FRAME_WINDOW_P (it->f))
12465 insert_left_trunc_glyphs (it);
12466 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
12467 }
12468
5f5c8ee5
GM
12469 it->face_id = saved_face_id;
12470
12471 /* Value is number of columns displayed. */
12472 return it->hpos - hpos_at_start;
12473}
a2889657 12474
a2889657 12475
a2889657 12476\f
5f5c8ee5
GM
12477/* This is like a combination of memq and assq. Return 1 if PROPVAL
12478 appears as an element of LIST or as the car of an element of LIST.
12479 If PROPVAL is a list, compare each element against LIST in that
12480 way, and return 1 if any element of PROPVAL is found in LIST.
12481 Otherwise return 0. This function cannot quit. */
642eefc6
RS
12482
12483int
12484invisible_p (propval, list)
12485 register Lisp_Object propval;
12486 Lisp_Object list;
12487{
af460d46 12488 register Lisp_Object tail, proptail;
9472f927 12489 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
12490 {
12491 register Lisp_Object tem;
9472f927 12492 tem = XCAR (tail);
642eefc6
RS
12493 if (EQ (propval, tem))
12494 return 1;
9472f927 12495 if (CONSP (tem) && EQ (propval, XCAR (tem)))
642eefc6
RS
12496 return 1;
12497 }
af460d46
RS
12498 if (CONSP (propval))
12499 for (proptail = propval; CONSP (proptail);
9472f927 12500 proptail = XCDR (proptail))
af460d46
RS
12501 {
12502 Lisp_Object propelt;
9472f927
GM
12503 propelt = XCAR (proptail);
12504 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
12505 {
12506 register Lisp_Object tem;
9472f927 12507 tem = XCAR (tail);
af460d46
RS
12508 if (EQ (propelt, tem))
12509 return 1;
9472f927 12510 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
af460d46
RS
12511 return 1;
12512 }
12513 }
642eefc6
RS
12514 return 0;
12515}
12516
5f5c8ee5
GM
12517
12518/* Return 1 if PROPVAL appears as the car of an element of LIST and
12519 the cdr of that element is non-nil. If PROPVAL is a list, check
12520 each element of PROPVAL in that way, and the first time some
12521 element is found, return 1 if the cdr of that element is non-nil.
12522 Otherwise return 0. This function cannot quit. */
642eefc6
RS
12523
12524int
12525invisible_ellipsis_p (propval, list)
12526 register Lisp_Object propval;
12527 Lisp_Object list;
12528{
af460d46 12529 register Lisp_Object tail, proptail;
9472f927
GM
12530
12531 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
12532 {
12533 register Lisp_Object tem;
9472f927
GM
12534 tem = XCAR (tail);
12535 if (CONSP (tem) && EQ (propval, XCAR (tem)))
12536 return ! NILP (XCDR (tem));
642eefc6 12537 }
9472f927 12538
af460d46 12539 if (CONSP (propval))
9472f927 12540 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
af460d46
RS
12541 {
12542 Lisp_Object propelt;
9472f927
GM
12543 propelt = XCAR (proptail);
12544 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
12545 {
12546 register Lisp_Object tem;
9472f927
GM
12547 tem = XCAR (tail);
12548 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
12549 return ! NILP (XCDR (tem));
af460d46
RS
12550 }
12551 }
9472f927 12552
642eefc6
RS
12553 return 0;
12554}
5f5c8ee5
GM
12555
12556
642eefc6 12557\f
5f5c8ee5
GM
12558/***********************************************************************
12559 Initialization
12560 ***********************************************************************/
12561
a2889657
JB
12562void
12563syms_of_xdisp ()
12564{
c6e89d6c
GM
12565 Vwith_echo_area_save_vector = Qnil;
12566 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 12567
c6e89d6c
GM
12568 Vmessage_stack = Qnil;
12569 staticpro (&Vmessage_stack);
12570
735c094c 12571 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 12572 staticpro (&Qinhibit_redisplay);
735c094c 12573
5f5c8ee5
GM
12574#if GLYPH_DEBUG
12575 defsubr (&Sdump_glyph_matrix);
12576 defsubr (&Sdump_glyph_row);
e037b9ec 12577 defsubr (&Sdump_tool_bar_row);
5f5c8ee5
GM
12578 defsubr (&Strace_redisplay_toggle);
12579#endif
12580
cf074754
RS
12581 staticpro (&Qmenu_bar_update_hook);
12582 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
12583
d46fb96a 12584 staticpro (&Qoverriding_terminal_local_map);
7079aefa 12585 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 12586
399164b4
KH
12587 staticpro (&Qoverriding_local_map);
12588 Qoverriding_local_map = intern ("overriding-local-map");
12589
75c43375
RS
12590 staticpro (&Qwindow_scroll_functions);
12591 Qwindow_scroll_functions = intern ("window-scroll-functions");
12592
e0bfbde6
RS
12593 staticpro (&Qredisplay_end_trigger_functions);
12594 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
5f5c8ee5 12595
2e54982e
RS
12596 staticpro (&Qinhibit_point_motion_hooks);
12597 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
12598
5f5c8ee5
GM
12599 staticpro (&Qdisplay);
12600 Qdisplay = intern ("display");
12601 staticpro (&Qleft_margin);
12602 Qspace_width = intern ("space-width");
12603 staticpro (&Qspace_width);
12604 Qheight = intern ("height");
12605 staticpro (&Qheight);
12606 Qraise = intern ("raise");
12607 staticpro (&Qraise);
12608 Qspace = intern ("space");
12609 staticpro (&Qspace);
12610 Qleft_margin = intern ("left-margin");
12611 staticpro (&Qright_margin);
12612 Qright_margin = intern ("right-margin");
12613 Qalign_to = intern ("align-to");
12614 staticpro (&Qalign_to);
12615 QCalign_to = intern (":align-to");
12616 staticpro (&QCalign_to);
12617 Qwidth = intern ("width");
12618 staticpro (&Qwidth);
12619 Qrelative_width = intern ("relative-width");
12620 staticpro (&Qrelative_width);
12621 QCrelative_width = intern (":relative-width");
12622 staticpro (&QCrelative_width);
12623 QCrelative_height = intern (":relative-height");
12624 staticpro (&QCrelative_height);
12625 QCeval = intern (":eval");
12626 staticpro (&QCeval);
d3acf96b 12627 Qwhen = intern ("when");
886bd6f2
GM
12628 QCfile = intern (":file");
12629 staticpro (&QCfile);
d3acf96b 12630 staticpro (&Qwhen);
5f5c8ee5
GM
12631 Qfontified = intern ("fontified");
12632 staticpro (&Qfontified);
12633 Qfontification_functions = intern ("fontification-functions");
12634 staticpro (&Qfontification_functions);
5f5c8ee5
GM
12635 Qtrailing_whitespace = intern ("trailing-whitespace");
12636 staticpro (&Qtrailing_whitespace);
12637 Qimage = intern ("image");
12638 staticpro (&Qimage);
12639
a2889657
JB
12640 staticpro (&last_arrow_position);
12641 staticpro (&last_arrow_string);
12642 last_arrow_position = Qnil;
12643 last_arrow_string = Qnil;
c6e89d6c
GM
12644
12645 echo_buffer[0] = echo_buffer[1] = Qnil;
12646 staticpro (&echo_buffer[0]);
12647 staticpro (&echo_buffer[1]);
12648
12649 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
12650 staticpro (&echo_area_buffer[0]);
12651 staticpro (&echo_area_buffer[1]);
a2889657 12652
8f897821
GM
12653 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
12654 "Non-nil means highlight trailing whitespace.\n\
12655The face used for trailing whitespace is `trailing-whitespace'.");
12656 Vshow_trailing_whitespace = Qnil;
12657
735c094c
KH
12658 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
12659 "Non-nil means don't actually do any redisplay.\n\
12660This is used for internal purposes.");
12661 Vinhibit_redisplay = Qnil;
12662
a2889657 12663 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 12664 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
12665 Vglobal_mode_string = Qnil;
12666
12667 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
12668 "Marker for where to display an arrow on top of the buffer text.\n\
12669This must be the beginning of a line in order to work.\n\
12670See also `overlay-arrow-string'.");
12671 Voverlay_arrow_position = Qnil;
12672
12673 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
12674 "String to display as an arrow. See also `overlay-arrow-position'.");
12675 Voverlay_arrow_string = Qnil;
12676
12677 DEFVAR_INT ("scroll-step", &scroll_step,
12678 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
12679If that fails to bring point back on frame, point is centered instead.\n\
12680If this is zero, point is always centered after it moves off frame.");
a2889657 12681
0789adb2
RS
12682 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
12683 "*Scroll up to this many lines, to bring point back on screen.");
12684 scroll_conservatively = 0;
12685
9afd2168
RS
12686 DEFVAR_INT ("scroll-margin", &scroll_margin,
12687 "*Number of lines of margin at the top and bottom of a window.\n\
12688Recenter the window whenever point gets within this many lines\n\
12689of the top or bottom of the window.");
12690 scroll_margin = 0;
12691
5f5c8ee5 12692#if GLYPH_DEBUG
a2889657 12693 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
5f5c8ee5 12694#endif
a2889657
JB
12695
12696 DEFVAR_BOOL ("truncate-partial-width-windows",
12697 &truncate_partial_width_windows,
44fa5b1e 12698 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
12699 truncate_partial_width_windows = 1;
12700
12701 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
12702 "*Non-nil means use inverse video for the mode line.");
12703 mode_line_inverse_video = 1;
aa6d10fa
RS
12704
12705 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
5f5c8ee5 12706 "*Maximum buffer size for which line number should be displayed.\n\
db4f2bfa 12707If the buffer is bigger than this, the line number does not appear\n\
9f027393 12708in the mode line.");
aa6d10fa 12709 line_number_display_limit = 1000000;
fba9ce76 12710
5d121aec
KH
12711 DEFVAR_INT ("line-number-display-limit-width", &line_number_display_limit_width,
12712 "*Maximum line width (in characters) for line number display.\n\
12713If the average length of the lines near point is bigger than this, then the\n\
12714line number may be omitted from the mode line.");
12715 line_number_display_limit_width = 200;
12716
fba9ce76
RS
12717 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
12718 "*Non-nil means highlight region even in nonselected windows.");
293a54ce 12719 highlight_nonselected_windows = 0;
d39b6696
KH
12720
12721 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
12722 "Non-nil if more than one frame is visible on this display.\n\
12723Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
12724This variable is not guaranteed to be accurate except while processing\n\
12725`frame-title-format' and `icon-title-format'.");
d39b6696
KH
12726
12727 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
5f5c8ee5 12728 "Template for displaying the title bar of visible frames.\n\
d39b6696
KH
12729\(Assuming the window manager supports this feature.)\n\
12730This variable has the same structure as `mode-line-format' (which see),\n\
12731and is used only on frames for which no explicit name has been set\n\
12732\(see `modify-frame-parameters').");
12733 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
5f5c8ee5 12734 "Template for displaying the title bar of an iconified frame.\n\
d39b6696
KH
12735\(Assuming the window manager supports this feature.)\n\
12736This variable has the same structure as `mode-line-format' (which see),\n\
12737and is used only on frames for which no explicit name has been set\n\
12738\(see `modify-frame-parameters').");
12739 Vicon_title_format
12740 = Vframe_title_format
12741 = Fcons (intern ("multiple-frames"),
12742 Fcons (build_string ("%b"),
12743 Fcons (Fcons (build_string (""),
12744 Fcons (intern ("invocation-name"),
12745 Fcons (build_string ("@"),
12746 Fcons (intern ("system-name"),
12747 Qnil)))),
12748 Qnil)));
5992c4f7
KH
12749
12750 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
12751 "Maximum number of lines to keep in the message log buffer.\n\
12752If nil, disable message logging. If t, log messages but don't truncate\n\
12753the buffer when it becomes large.");
12754 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
12755
12756 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
12757 "Functions called before redisplay, if window sizes have changed.\n\
12758The value should be a list of functions that take one argument.\n\
12759Just before redisplay, for each frame, if any of its windows have changed\n\
12760size since the last redisplay, or have been split or deleted,\n\
12761all the functions in the list are called, with the frame as argument.");
12762 Vwindow_size_change_functions = Qnil;
75c43375
RS
12763
12764 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
5f5c8ee5 12765 "List of Functions to call before redisplaying a window with scrolling.\n\
75c43375 12766Each function is called with two arguments, the window\n\
8d9583b0
RS
12767and its new display-start position. Note that the value of `window-end'\n\
12768is not valid when these functions are called.");
75c43375 12769 Vwindow_scroll_functions = Qnil;
5f5c8ee5 12770
e037b9ec
GM
12771 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
12772 "*Non-nil means automatically resize tool-bars.\n\
12773This increases a tool-bar's height if not all tool-bar items are visible.\n\
12774It decreases a tool-bar's height when it would display blank lines\n\
5f5c8ee5 12775otherwise.");
e037b9ec 12776 auto_resize_tool_bars_p = 1;
5f5c8ee5 12777
e037b9ec
GM
12778 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
12779 "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
12780 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 12781
e037b9ec
GM
12782 DEFVAR_INT ("tool-bar-button-margin", &tool_bar_button_margin,
12783 "*Margin around tool-bar buttons in pixels.");
12784 tool_bar_button_margin = 1;
5f5c8ee5 12785
e037b9ec
GM
12786 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
12787 "Relief thickness of tool-bar buttons.");
12788 tool_bar_button_relief = 3;
5f5c8ee5
GM
12789
12790 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
12791 "List of functions to call to fontify regions of text.\n\
12792Each function is called with one argument POS. Functions must\n\
12793fontify a region starting at POS in the current buffer, and give\n\
12794fontified regions the property `fontified'.\n\
12795This variable automatically becomes buffer-local when set.");
12796 Vfontification_functions = Qnil;
12797 Fmake_local_variable (Qfontification_functions);
7bbe686f
AI
12798
12799 DEFVAR_BOOL ("unibyte-display-via-language-environment",
5f5c8ee5
GM
12800 &unibyte_display_via_language_environment,
12801 "*Non-nil means display unibyte text according to language environment.\n\
7bbe686f
AI
12802Specifically this means that unibyte non-ASCII characters\n\
12803are displayed by converting them to the equivalent multibyte characters\n\
12804according to the current language environment. As a result, they are\n\
12805displayed according to the current fontset.");
12806 unibyte_display_via_language_environment = 0;
c6e89d6c
GM
12807
12808 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
12809 "*Maximum height for resizing mini-windows.\n\
12810If a float, it specifies a fraction of the mini-window frame's height.\n\
97cafc0f
GM
12811If an integer, it specifies a number of lines.\n\
12812If nil, don't resize.");
c6e89d6c 12813 Vmax_mini_window_height = make_float (0.25);
a2889657
JB
12814}
12815
5f5c8ee5
GM
12816
12817/* Initialize this module when Emacs starts. */
12818
dfcf069d 12819void
a2889657
JB
12820init_xdisp ()
12821{
12822 Lisp_Object root_window;
5f5c8ee5 12823 struct window *mini_w;
a2889657 12824
5f5c8ee5 12825 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
12826
12827 mini_w = XWINDOW (minibuf_window);
11e82b76 12828 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 12829
a2889657
JB
12830 if (!noninteractive)
12831 {
5f5c8ee5
GM
12832 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
12833 int i;
12834
12835 XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f));
12c226c5 12836 set_window_height (root_window,
5f5c8ee5 12837 FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 12838 0);
c2213350 12839 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
12840 set_window_height (minibuf_window, 1, 0);
12841
c2213350
KH
12842 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
12843 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
5f5c8ee5
GM
12844
12845 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
12846 scratch_glyph_row.glyphs[TEXT_AREA + 1]
12847 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
12848
12849 /* The default ellipsis glyphs `...'. */
12850 for (i = 0; i < 3; ++i)
12851 XSETFASTINT (default_invis_vector[i], '.');
a2889657 12852 }
5f5c8ee5
GM
12853
12854#ifdef HAVE_WINDOW_SYSTEM
12855 {
12856 /* Allocate the buffer for frame titles. */
12857 int size = 100;
12858 frame_title_buf = (char *) xmalloc (size);
12859 frame_title_buf_end = frame_title_buf + size;
12860 frame_title_ptr = NULL;
12861 }
12862#endif /* HAVE_WINDOW_SYSTEM */
a2889657 12863}
5f5c8ee5
GM
12864
12865