(HAVE_INDEX, HAVE_RINDEX, HAVE_STRINGS_H): Add undefs.
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
a0315a63 2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99, 2000
5f5c8ee5 3 Free Software Foundation, Inc.
a2889657
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
b1d1124b 9the Free Software Foundation; either version 2, or (at your option)
a2889657
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
a2889657 21
5f5c8ee5
GM
22/* New redisplay written by Gerd Moellmann <gerd@gnu.org>.
23
24 Redisplay.
25
26 Emacs separates the task of updating the display from code
27 modifying global state, e.g. buffer text. This way functions
28 operating on buffers don't also have to be concerned with updating
29 the display.
30
31 Updating the display is triggered by the Lisp interpreter when it
32 decides it's time to do it. This is done either automatically for
33 you as part of the interpreter's command loop or as the result of
34 calling Lisp functions like `sit-for'. The C function `redisplay'
35 in xdisp.c is the only entry into the inner redisplay code. (Or,
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>
a2889657 172#include "lisp.h"
546a4f00 173#include "keyboard.h"
44fa5b1e 174#include "frame.h"
a2889657
JB
175#include "window.h"
176#include "termchar.h"
177#include "dispextern.h"
178#include "buffer.h"
1c9241f5 179#include "charset.h"
a2889657
JB
180#include "indent.h"
181#include "commands.h"
182#include "macros.h"
183#include "disptab.h"
30c566e4 184#include "termhooks.h"
b0a0fbda 185#include "intervals.h"
1c9241f5
KH
186#include "coding.h"
187#include "process.h"
dfcf069d 188#include "region-cache.h"
0ef75e87 189#include "fontset.h"
dfcf069d 190
6d55d620 191#ifdef HAVE_X_WINDOWS
dfcf069d
AS
192#include "xterm.h"
193#endif
a75dfea0
AI
194#ifdef WINDOWSNT
195#include "w32term.h"
196#endif
a2889657 197
5f5c8ee5
GM
198#define min(a, b) ((a) < (b) ? (a) : (b))
199#define max(a, b) ((a) > (b) ? (a) : (b))
200
201#define INFINITY 10000000
202
8f3343d0 203#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
2e621225 204extern void set_frame_menubar P_ ((struct frame *f, int, int));
cd6dfed6 205extern int pending_menu_activation;
76412d64
RS
206#endif
207
a2889657
JB
208extern int interrupt_input;
209extern int command_loop_level;
210
b6436d4e
RS
211extern int minibuffer_auto_raise;
212
c4628384
RS
213extern Lisp_Object Qface;
214
399164b4
KH
215extern Lisp_Object Voverriding_local_map;
216extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 217extern Lisp_Object Qmenu_item;
399164b4 218
d46fb96a 219Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 220Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 221Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 222Lisp_Object Qinhibit_point_motion_hooks;
9499d71b 223Lisp_Object QCeval, Qwhen, QCfile, QCdata;
5f5c8ee5
GM
224Lisp_Object Qfontified;
225
226/* Functions called to fontify regions of text. */
227
228Lisp_Object Vfontification_functions;
229Lisp_Object Qfontification_functions;
230
e037b9ec 231/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
232 over them. */
233
e037b9ec 234int auto_raise_tool_bar_buttons_p;
5f5c8ee5 235
e037b9ec 236/* Margin around tool bar buttons in pixels. */
5f5c8ee5 237
e037b9ec 238int tool_bar_button_margin;
5f5c8ee5 239
e037b9ec 240/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 241
e037b9ec 242int tool_bar_button_relief;
5f5c8ee5 243
e037b9ec 244/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
245 items are visible, and no blank lines remain. */
246
e037b9ec 247int auto_resize_tool_bars_p;
399164b4 248
735c094c
KH
249/* Non-nil means don't actually do any redisplay. */
250
251Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
252
5f5c8ee5
GM
253/* Names of text properties relevant for redisplay. */
254
a7e27ef7
DL
255Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
256extern Lisp_Object Qface, Qinvisible, Qimage, Qwidth;
5f5c8ee5
GM
257
258/* Symbols used in text property values. */
259
260Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
a7e27ef7 261Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
f3751a65 262Lisp_Object Qmargin;
a7e27ef7 263extern Lisp_Object Qheight;
5f5c8ee5 264
8f897821 265/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 266
8f897821 267Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5
GM
268
269/* Name of the face used to highlight trailing whitespace. */
270
271Lisp_Object Qtrailing_whitespace;
272
273/* The symbol `image' which is the car of the lists used to represent
274 images in Lisp. */
275
276Lisp_Object Qimage;
277
278/* Non-zero means print newline to stdout before next mini-buffer
279 message. */
a2889657
JB
280
281int noninteractive_need_newline;
282
5f5c8ee5 283/* Non-zero means print newline to message log before next message. */
f88eb0b6 284
3c6595e0 285static int message_log_need_newline;
f88eb0b6 286
5f5c8ee5
GM
287\f
288/* The buffer position of the first character appearing entirely or
289 partially on the line of the selected window which contains the
290 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
291 redisplay optimization in redisplay_internal. */
a2889657 292
5f5c8ee5 293static struct text_pos this_line_start_pos;
a2889657 294
5f5c8ee5
GM
295/* Number of characters past the end of the line above, including the
296 terminating newline. */
297
298static struct text_pos this_line_end_pos;
299
300/* The vertical positions and the height of this line. */
a2889657 301
a2889657 302static int this_line_vpos;
5f5c8ee5
GM
303static int this_line_y;
304static int this_line_pixel_height;
305
306/* X position at which this display line starts. Usually zero;
307 negative if first character is partially visible. */
308
309static int this_line_start_x;
a2889657 310
5f5c8ee5 311/* Buffer that this_line_.* variables are referring to. */
a2889657 312
a2889657
JB
313static struct buffer *this_line_buffer;
314
5f5c8ee5
GM
315/* Nonzero means truncate lines in all windows less wide than the
316 frame. */
a2889657 317
a2889657
JB
318int truncate_partial_width_windows;
319
7bbe686f 320/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 321
7bbe686f 322int unibyte_display_via_language_environment;
5f5c8ee5
GM
323
324/* Nonzero means we have more than one non-mini-buffer-only frame.
325 Not guaranteed to be accurate except while parsing
326 frame-title-format. */
7bbe686f 327
d39b6696
KH
328int multiple_frames;
329
a2889657
JB
330Lisp_Object Vglobal_mode_string;
331
332/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 333
a2889657
JB
334Lisp_Object Voverlay_arrow_position;
335
5f5c8ee5
GM
336/* String to display for the arrow. Only used on terminal frames. */
337
a2889657
JB
338Lisp_Object Voverlay_arrow_string;
339
5f5c8ee5
GM
340/* Values of those variables at last redisplay. However, if
341 Voverlay_arrow_position is a marker, last_arrow_position is its
342 numerical position. */
343
d45de95b
RS
344static Lisp_Object last_arrow_position, last_arrow_string;
345
5f5c8ee5
GM
346/* Like mode-line-format, but for the title bar on a visible frame. */
347
d39b6696
KH
348Lisp_Object Vframe_title_format;
349
5f5c8ee5
GM
350/* Like mode-line-format, but for the title bar on an iconified frame. */
351
d39b6696
KH
352Lisp_Object Vicon_title_format;
353
08b610e4
RS
354/* List of functions to call when a window's size changes. These
355 functions get one arg, a frame on which one or more windows' sizes
356 have changed. */
5f5c8ee5 357
08b610e4
RS
358static Lisp_Object Vwindow_size_change_functions;
359
cf074754
RS
360Lisp_Object Qmenu_bar_update_hook;
361
a2889657 362/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 363
5f5c8ee5 364static int overlay_arrow_seen;
ca26e1c8 365
fba9ce76 366/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 367
5f5c8ee5
GM
368int highlight_nonselected_windows;
369
370/* If cursor motion alone moves point off frame, try scrolling this
371 many lines up or down if that will bring it back. */
372
14510fee 373static int scroll_step;
a2889657 374
5f5c8ee5
GM
375/* Non-0 means scroll just far enough to bring point back on the
376 screen, when appropriate. */
377
0789adb2
RS
378static int scroll_conservatively;
379
5f5c8ee5
GM
380/* Recenter the window whenever point gets within this many lines of
381 the top or bottom of the window. This value is translated into a
382 pixel value by multiplying it with CANON_Y_UNIT, which means that
383 there is really a fixed pixel height scroll margin. */
384
9afd2168
RS
385int scroll_margin;
386
5f5c8ee5
GM
387/* Number of windows showing the buffer of the selected window (or
388 another buffer with the same base buffer). keyboard.c refers to
389 this. */
a2889657 390
a2889657
JB
391int buffer_shared;
392
5f5c8ee5 393/* Vector containing glyphs for an ellipsis `...'. */
a2889657 394
5f5c8ee5 395static Lisp_Object default_invis_vector[3];
a2889657 396
5f5c8ee5 397/* Nonzero means display mode line highlighted. */
a2889657 398
a2889657
JB
399int mode_line_inverse_video;
400
5f5c8ee5
GM
401/* Prompt to display in front of the mini-buffer contents. */
402
8c5b6a0a 403Lisp_Object minibuf_prompt;
a2889657 404
5f5c8ee5
GM
405/* Width of current mini-buffer prompt. Only set after display_line
406 of the line that contains the prompt. */
407
a2889657 408int minibuf_prompt_width;
5f5c8ee5
GM
409int minibuf_prompt_pixel_width;
410
5f5c8ee5
GM
411/* This is the window where the echo area message was displayed. It
412 is always a mini-buffer window, but it may not be the same window
413 currently active as a mini-buffer. */
414
73af359d
RS
415Lisp_Object echo_area_window;
416
c6e89d6c
GM
417/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
418 pushes the current message and the value of
419 message_enable_multibyte on the stack, the function restore_message
420 pops the stack and displays MESSAGE again. */
421
422Lisp_Object Vmessage_stack;
423
a3788d53
RS
424/* Nonzero means multibyte characters were enabled when the echo area
425 message was specified. */
5f5c8ee5 426
a3788d53
RS
427int message_enable_multibyte;
428
5f5c8ee5
GM
429/* True if we should redraw the mode lines on the next redisplay. */
430
a2889657
JB
431int update_mode_lines;
432
5f5c8ee5
GM
433/* Nonzero if window sizes or contents have changed since last
434 redisplay that finished */
435
a2889657
JB
436int windows_or_buffers_changed;
437
5f5c8ee5
GM
438/* Nonzero after display_mode_line if %l was used and it displayed a
439 line number. */
440
aa6d10fa
RS
441int line_number_displayed;
442
443/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 444
090703f4 445Lisp_Object Vline_number_display_limit;
5992c4f7 446
5d121aec
KH
447/* line width to consider when repostioning for line number display */
448
449static int line_number_display_limit_width;
450
5f5c8ee5
GM
451/* Number of lines to keep in the message log buffer. t means
452 infinite. nil means don't log at all. */
453
5992c4f7 454Lisp_Object Vmessage_log_max;
d45de95b 455
6a94510a
GM
456/* The name of the *Messages* buffer, a string. */
457
458static Lisp_Object Vmessages_buffer_name;
459
c6e89d6c
GM
460/* Current, index 0, and last displayed echo area message. Either
461 buffers from echo_buffers, or nil to indicate no message. */
462
463Lisp_Object echo_area_buffer[2];
464
465/* The buffers referenced from echo_area_buffer. */
466
467static Lisp_Object echo_buffer[2];
468
469/* A vector saved used in with_area_buffer to reduce consing. */
470
471static Lisp_Object Vwith_echo_area_save_vector;
472
473/* Non-zero means display_echo_area should display the last echo area
474 message again. Set by redisplay_preserve_echo_area. */
475
476static int display_last_displayed_message_p;
477
478/* Nonzero if echo area is being used by print; zero if being used by
479 message. */
480
481int message_buf_print;
482
9142dd5b
GM
483/* Maximum height for resizing mini-windows. Either a float
484 specifying a fraction of the available height, or an integer
485 specifying a number of lines. */
c6e89d6c 486
ad4f174e
GM
487Lisp_Object Vmax_mini_window_height;
488
489/* Non-zero means messages should be displayed with truncated
490 lines instead of being continued. */
491
492int message_truncate_lines;
493Lisp_Object Qmessage_truncate_lines;
c6e89d6c 494
d6d26ed3
GM
495/* Non-zero means we want a hollow cursor in windows that are not
496 selected. Zero means there's no cursor in such windows. */
497
498int cursor_in_non_selected_windows;
499
5f5c8ee5
GM
500/* A scratch glyph row with contents used for generating truncation
501 glyphs. Also used in direct_output_for_insert. */
12adba34 502
5f5c8ee5
GM
503#define MAX_SCRATCH_GLYPHS 100
504struct glyph_row scratch_glyph_row;
505static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 506
5f5c8ee5
GM
507/* Ascent and height of the last line processed by move_it_to. */
508
509static int last_max_ascent, last_height;
510
511/* The maximum distance to look ahead for text properties. Values
512 that are too small let us call compute_char_face and similar
513 functions too often which is expensive. Values that are too large
514 let us call compute_char_face and alike too often because we
515 might not be interested in text properties that far away. */
516
517#define TEXT_PROP_DISTANCE_LIMIT 100
518
47589c8c
GM
519#if GLYPH_DEBUG
520
5f5c8ee5
GM
521/* Non-zero means print traces of redisplay if compiled with
522 GLYPH_DEBUG != 0. */
523
5f5c8ee5 524int trace_redisplay_p;
47589c8c 525
546a4f00 526#endif /* GLYPH_DEBUG */
47589c8c 527
546a4f00
AI
528#ifdef DEBUG_TRACE_MOVE
529/* Non-zero means trace with TRACE_MOVE to stderr. */
47589c8c
GM
530int trace_move;
531
47589c8c
GM
532#define TRACE_MOVE(x) if (trace_move) fprintf x; else (void) 0
533#else
91c3f500 534#define TRACE_MOVE(x) (void) 0
5f5c8ee5 535#endif
546a4f00 536
d475bcb8
GM
537/* Non-zero means automatically scroll windows horizontally to make
538 point visible. */
539
540int automatic_hscrolling_p;
541
e00daaa0
GM
542/* A list of symbols, one for each supported image type. */
543
544Lisp_Object Vimage_types;
545
5f5c8ee5
GM
546/* Value returned from text property handlers (see below). */
547
548enum prop_handled
3c6595e0 549{
5f5c8ee5
GM
550 HANDLED_NORMALLY,
551 HANDLED_RECOMPUTE_PROPS,
552 HANDLED_OVERLAY_STRING_CONSUMED,
553 HANDLED_RETURN
554};
3c6595e0 555
5f5c8ee5
GM
556/* A description of text properties that redisplay is interested
557 in. */
3c6595e0 558
5f5c8ee5
GM
559struct props
560{
561 /* The name of the property. */
562 Lisp_Object *name;
90adcf20 563
5f5c8ee5
GM
564 /* A unique index for the property. */
565 enum prop_idx idx;
566
567 /* A handler function called to set up iterator IT from the property
568 at IT's current position. Value is used to steer handle_stop. */
569 enum prop_handled (*handler) P_ ((struct it *it));
570};
571
572static enum prop_handled handle_face_prop P_ ((struct it *));
573static enum prop_handled handle_invisible_prop P_ ((struct it *));
574static enum prop_handled handle_display_prop P_ ((struct it *));
260a86a0 575static enum prop_handled handle_composition_prop P_ ((struct it *));
5f5c8ee5
GM
576static enum prop_handled handle_overlay_change P_ ((struct it *));
577static enum prop_handled handle_fontified_prop P_ ((struct it *));
578
579/* Properties handled by iterators. */
580
581static struct props it_props[] =
5992c4f7 582{
5f5c8ee5
GM
583 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
584 /* Handle `face' before `display' because some sub-properties of
585 `display' need to know the face. */
586 {&Qface, FACE_PROP_IDX, handle_face_prop},
587 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
588 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
260a86a0 589 {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
5f5c8ee5
GM
590 {NULL, 0, NULL}
591};
5992c4f7 592
5f5c8ee5
GM
593/* Value is the position described by X. If X is a marker, value is
594 the marker_position of X. Otherwise, value is X. */
12adba34 595
5f5c8ee5 596#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 597
5f5c8ee5 598/* Enumeration returned by some move_it_.* functions internally. */
12adba34 599
5f5c8ee5
GM
600enum move_it_result
601{
602 /* Not used. Undefined value. */
603 MOVE_UNDEFINED,
bab29e15 604
5f5c8ee5
GM
605 /* Move ended at the requested buffer position or ZV. */
606 MOVE_POS_MATCH_OR_ZV,
bab29e15 607
5f5c8ee5
GM
608 /* Move ended at the requested X pixel position. */
609 MOVE_X_REACHED,
12adba34 610
5f5c8ee5
GM
611 /* Move within a line ended at the end of a line that must be
612 continued. */
613 MOVE_LINE_CONTINUED,
614
615 /* Move within a line ended at the end of a line that would
616 be displayed truncated. */
617 MOVE_LINE_TRUNCATED,
ff6c30e5 618
5f5c8ee5
GM
619 /* Move within a line ended at a line end. */
620 MOVE_NEWLINE_OR_CR
621};
12adba34 622
ff6c30e5 623
5f5c8ee5
GM
624\f
625/* Function prototypes. */
626
2e621225
GM
627static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
628static int invisible_text_between_p P_ ((struct it *, int, int));
629static int next_element_from_ellipsis P_ ((struct it *));
630static void pint2str P_ ((char *, int, int));
631static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
632 struct text_pos));
633static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
634static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
635static void store_frame_title_char P_ ((char));
636static int store_frame_title P_ ((unsigned char *, int, int));
637static void x_consider_frame_title P_ ((Lisp_Object));
638static void handle_stop P_ ((struct it *));
639static int tool_bar_lines_needed P_ ((struct frame *));
06568bbf 640static int single_display_prop_intangible_p P_ ((Lisp_Object));
5bcfeb49 641static void ensure_echo_area_buffers P_ ((void));
e037b9ec
GM
642static struct glyph_row *row_containing_pos P_ ((struct window *, int,
643 struct glyph_row *,
644 struct glyph_row *));
c6e89d6c
GM
645static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
646static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
23a96c77 647static int with_echo_area_buffer P_ ((struct window *, int,
23dd2d97
KR
648 int (*) (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT),
649 EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 650static void clear_garbaged_frames P_ ((void));
23dd2d97
KR
651static int current_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
652static int truncate_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
653static int set_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 654static int display_echo_area P_ ((struct window *));
23dd2d97
KR
655static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
656static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
28514cd9 657static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
4fdb80f2 658static int string_char_and_length P_ ((unsigned char *, int, int *));
5f5c8ee5
GM
659static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
660 struct text_pos));
661static int compute_window_start_on_continuation_line P_ ((struct window *));
662static Lisp_Object eval_handler P_ ((Lisp_Object));
5f5c8ee5
GM
663static void insert_left_trunc_glyphs P_ ((struct it *));
664static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
665static void extend_face_to_end_of_line P_ ((struct it *));
80c6cb1f 666static int append_space P_ ((struct it *, int));
5f5c8ee5
GM
667static void make_cursor_line_fully_visible P_ ((struct window *));
668static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
47589c8c 669static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
5f5c8ee5
GM
670static int trailing_whitespace_p P_ ((int));
671static int message_log_check_duplicate P_ ((int, int, int, int));
672int invisible_p P_ ((Lisp_Object, Lisp_Object));
673int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
674static void push_it P_ ((struct it *));
675static void pop_it P_ ((struct it *));
676static void sync_frame_with_window_matrix_rows P_ ((struct window *));
677static void redisplay_internal P_ ((int));
c6e89d6c 678static int echo_area_display P_ ((int));
5f5c8ee5
GM
679static void redisplay_windows P_ ((Lisp_Object));
680static void redisplay_window P_ ((Lisp_Object, int));
681static void update_menu_bar P_ ((struct frame *, int));
682static int try_window_reusing_current_matrix P_ ((struct window *));
683static int try_window_id P_ ((struct window *));
684static int display_line P_ ((struct it *));
685static void display_mode_lines P_ ((struct window *));
686static void display_mode_line P_ ((struct window *, enum face_id,
687 Lisp_Object));
688static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
68c45bf0 689static char *decode_mode_spec P_ ((struct window *, int, int, int));
5f5c8ee5
GM
690static void display_menu_bar P_ ((struct window *));
691static int display_count_lines P_ ((int, int, int, int, int *));
692static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
693 int, int, struct it *, int, int, int, int));
694static void compute_line_metrics P_ ((struct it *));
695static void run_redisplay_end_trigger_hook P_ ((struct it *));
696static int get_overlay_strings P_ ((struct it *));
697static void next_overlay_string P_ ((struct it *));
698void set_iterator_to_next P_ ((struct it *));
699static void reseat P_ ((struct it *, struct text_pos, int));
700static void reseat_1 P_ ((struct it *, struct text_pos, int));
701static void back_to_previous_visible_line_start P_ ((struct it *));
702static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 703static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
704static int next_element_from_display_vector P_ ((struct it *));
705static int next_element_from_string P_ ((struct it *));
706static int next_element_from_c_string P_ ((struct it *));
707static int next_element_from_buffer P_ ((struct it *));
260a86a0 708static int next_element_from_composition P_ ((struct it *));
5f5c8ee5
GM
709static int next_element_from_image P_ ((struct it *));
710static int next_element_from_stretch P_ ((struct it *));
711static void load_overlay_strings P_ ((struct it *));
712static void init_from_display_pos P_ ((struct it *, struct window *,
713 struct display_pos *));
714static void reseat_to_string P_ ((struct it *, unsigned char *,
715 Lisp_Object, int, int, int, int));
5f5c8ee5
GM
716static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
717 int, int, int));
718void move_it_vertically_backward P_ ((struct it *, int));
719static void init_to_row_start P_ ((struct it *, struct window *,
720 struct glyph_row *));
721static void init_to_row_end P_ ((struct it *, struct window *,
722 struct glyph_row *));
723static void back_to_previous_line_start P_ ((struct it *));
724static void forward_to_next_line_start P_ ((struct it *));
725static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
726 Lisp_Object, int));
727static struct text_pos string_pos P_ ((int, Lisp_Object));
728static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
729static int number_of_chars P_ ((unsigned char *, int));
730static void compute_stop_pos P_ ((struct it *));
731static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
732 Lisp_Object));
733static int face_before_or_after_it_pos P_ ((struct it *, int));
734static int next_overlay_change P_ ((int));
735static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
736 Lisp_Object, struct text_pos *));
737
738#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
739#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 740
5f5c8ee5 741#ifdef HAVE_WINDOW_SYSTEM
12adba34 742
e037b9ec
GM
743static void update_tool_bar P_ ((struct frame *, int));
744static void build_desired_tool_bar_string P_ ((struct frame *f));
745static int redisplay_tool_bar P_ ((struct frame *));
746static void display_tool_bar_line P_ ((struct it *));
12adba34 747
5f5c8ee5 748#endif /* HAVE_WINDOW_SYSTEM */
12adba34 749
5f5c8ee5
GM
750\f
751/***********************************************************************
752 Window display dimensions
753 ***********************************************************************/
12adba34 754
5f5c8ee5
GM
755/* Return the window-relative maximum y + 1 for glyph rows displaying
756 text in window W. This is the height of W minus the height of a
757 mode line, if any. */
758
759INLINE int
760window_text_bottom_y (w)
761 struct window *w;
762{
763 struct frame *f = XFRAME (w->frame);
764 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
765
766 if (WINDOW_WANTS_MODELINE_P (w))
767 height -= CURRENT_MODE_LINE_HEIGHT (w);
768 return height;
f88eb0b6
KH
769}
770
f82aff7c 771
5f5c8ee5
GM
772/* Return the pixel width of display area AREA of window W. AREA < 0
773 means return the total width of W, not including bitmap areas to
774 the left and right of the window. */
ff6c30e5 775
5f5c8ee5
GM
776INLINE int
777window_box_width (w, area)
778 struct window *w;
779 int area;
780{
781 struct frame *f = XFRAME (w->frame);
782 int width = XFASTINT (w->width);
783
784 if (!w->pseudo_window_p)
ff6c30e5 785 {
050d82d7 786 width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FLAGS_AREA_COLS (f);
5f5c8ee5
GM
787
788 if (area == TEXT_AREA)
789 {
790 if (INTEGERP (w->left_margin_width))
791 width -= XFASTINT (w->left_margin_width);
792 if (INTEGERP (w->right_margin_width))
793 width -= XFASTINT (w->right_margin_width);
794 }
795 else if (area == LEFT_MARGIN_AREA)
796 width = (INTEGERP (w->left_margin_width)
797 ? XFASTINT (w->left_margin_width) : 0);
798 else if (area == RIGHT_MARGIN_AREA)
799 width = (INTEGERP (w->right_margin_width)
800 ? XFASTINT (w->right_margin_width) : 0);
ff6c30e5 801 }
5f5c8ee5
GM
802
803 return width * CANON_X_UNIT (f);
ff6c30e5 804}
1adc55de 805
1adc55de 806
5f5c8ee5
GM
807/* Return the pixel height of the display area of window W, not
808 including mode lines of W, if any.. */
f88eb0b6 809
5f5c8ee5
GM
810INLINE int
811window_box_height (w)
812 struct window *w;
f88eb0b6 813{
5f5c8ee5
GM
814 struct frame *f = XFRAME (w->frame);
815 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
816
817 if (WINDOW_WANTS_MODELINE_P (w))
818 height -= CURRENT_MODE_LINE_HEIGHT (w);
819
045dee35
GM
820 if (WINDOW_WANTS_HEADER_LINE_P (w))
821 height -= CURRENT_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
822
823 return height;
5992c4f7
KH
824}
825
826
5f5c8ee5
GM
827/* Return the frame-relative coordinate of the left edge of display
828 area AREA of window W. AREA < 0 means return the left edge of the
829 whole window, to the right of any bitmap area at the left side of
830 W. */
5992c4f7 831
5f5c8ee5
GM
832INLINE int
833window_box_left (w, area)
834 struct window *w;
835 int area;
90adcf20 836{
5f5c8ee5
GM
837 struct frame *f = XFRAME (w->frame);
838 int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
a3788d53 839
5f5c8ee5 840 if (!w->pseudo_window_p)
90adcf20 841 {
5f5c8ee5 842 x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
050d82d7 843 + FRAME_LEFT_FLAGS_AREA_WIDTH (f));
5f5c8ee5
GM
844
845 if (area == TEXT_AREA)
846 x += window_box_width (w, LEFT_MARGIN_AREA);
847 else if (area == RIGHT_MARGIN_AREA)
848 x += (window_box_width (w, LEFT_MARGIN_AREA)
849 + window_box_width (w, TEXT_AREA));
90adcf20 850 }
73af359d 851
5f5c8ee5
GM
852 return x;
853}
90adcf20 854
b6436d4e 855
5f5c8ee5
GM
856/* Return the frame-relative coordinate of the right edge of display
857 area AREA of window W. AREA < 0 means return the left edge of the
858 whole window, to the left of any bitmap area at the right side of
859 W. */
ded34426 860
5f5c8ee5
GM
861INLINE int
862window_box_right (w, area)
863 struct window *w;
864 int area;
865{
866 return window_box_left (w, area) + window_box_width (w, area);
867}
868
869
870/* Get the bounding box of the display area AREA of window W, without
871 mode lines, in frame-relative coordinates. AREA < 0 means the
872 whole window, not including bitmap areas to the left and right of
873 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
874 coordinates of the upper-left corner of the box. Return in
875 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
876
877INLINE void
878window_box (w, area, box_x, box_y, box_width, box_height)
879 struct window *w;
880 int area;
881 int *box_x, *box_y, *box_width, *box_height;
882{
883 struct frame *f = XFRAME (w->frame);
884
885 *box_width = window_box_width (w, area);
886 *box_height = window_box_height (w);
887 *box_x = window_box_left (w, area);
888 *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
889 + XFASTINT (w->top) * CANON_Y_UNIT (f));
045dee35
GM
890 if (WINDOW_WANTS_HEADER_LINE_P (w))
891 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
ded34426 892}
1adc55de 893
1adc55de 894
5f5c8ee5
GM
895/* Get the bounding box of the display area AREA of window W, without
896 mode lines. AREA < 0 means the whole window, not including bitmap
897 areas to the left and right of the window. Return in *TOP_LEFT_X
898 and TOP_LEFT_Y the frame-relative pixel coordinates of the
899 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
900 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
901 box. */
ded34426 902
5f5c8ee5
GM
903INLINE void
904window_box_edges (w, area, top_left_x, top_left_y,
905 bottom_right_x, bottom_right_y)
906 struct window *w;
907 int area;
908 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 909{
5f5c8ee5
GM
910 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
911 bottom_right_y);
912 *bottom_right_x += *top_left_x;
913 *bottom_right_y += *top_left_y;
48ae5f0a
KH
914}
915
5f5c8ee5
GM
916
917\f
918/***********************************************************************
919 Utilities
920 ***********************************************************************/
921
4fdb80f2
GM
922/* Return the next character from STR which is MAXLEN bytes long.
923 Return in *LEN the length of the character. This is like
924 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
9ab8560d 925 we find one, we return a `?', but with the length of the invalid
4fdb80f2
GM
926 character. */
927
928static INLINE int
7a5b8a93 929string_char_and_length (str, maxlen, len)
4fdb80f2 930 unsigned char *str;
7a5b8a93 931 int maxlen, *len;
4fdb80f2
GM
932{
933 int c;
934
935 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
936 if (!CHAR_VALID_P (c, 1))
937 /* We may not change the length here because other places in Emacs
9ab8560d 938 don't use this function, i.e. they silently accept invalid
4fdb80f2
GM
939 characters. */
940 c = '?';
941
942 return c;
943}
944
945
946
5f5c8ee5
GM
947/* Given a position POS containing a valid character and byte position
948 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
949
950static struct text_pos
951string_pos_nchars_ahead (pos, string, nchars)
952 struct text_pos pos;
953 Lisp_Object string;
954 int nchars;
0b1005ef 955{
5f5c8ee5
GM
956 xassert (STRINGP (string) && nchars >= 0);
957
958 if (STRING_MULTIBYTE (string))
959 {
960 int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos);
961 unsigned char *p = XSTRING (string)->data + BYTEPOS (pos);
962 int len;
963
964 while (nchars--)
965 {
4fdb80f2 966 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
967 p += len, rest -= len;
968 xassert (rest >= 0);
969 CHARPOS (pos) += 1;
970 BYTEPOS (pos) += len;
971 }
972 }
973 else
974 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
975
976 return pos;
0a9dc68b
RS
977}
978
0a9dc68b 979
5f5c8ee5
GM
980/* Value is the text position, i.e. character and byte position,
981 for character position CHARPOS in STRING. */
982
983static INLINE struct text_pos
984string_pos (charpos, string)
985 int charpos;
0a9dc68b 986 Lisp_Object string;
0a9dc68b 987{
5f5c8ee5
GM
988 struct text_pos pos;
989 xassert (STRINGP (string));
990 xassert (charpos >= 0);
991 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
992 return pos;
993}
994
995
996/* Value is a text position, i.e. character and byte position, for
997 character position CHARPOS in C string S. MULTIBYTE_P non-zero
998 means recognize multibyte characters. */
999
1000static struct text_pos
1001c_string_pos (charpos, s, multibyte_p)
1002 int charpos;
1003 unsigned char *s;
1004 int multibyte_p;
1005{
1006 struct text_pos pos;
1007
1008 xassert (s != NULL);
1009 xassert (charpos >= 0);
1010
1011 if (multibyte_p)
0a9dc68b 1012 {
5f5c8ee5
GM
1013 int rest = strlen (s), len;
1014
1015 SET_TEXT_POS (pos, 0, 0);
1016 while (charpos--)
0a9dc68b 1017 {
4fdb80f2 1018 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
1019 s += len, rest -= len;
1020 xassert (rest >= 0);
1021 CHARPOS (pos) += 1;
1022 BYTEPOS (pos) += len;
0a9dc68b
RS
1023 }
1024 }
5f5c8ee5
GM
1025 else
1026 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 1027
5f5c8ee5
GM
1028 return pos;
1029}
0a9dc68b 1030
0a9dc68b 1031
5f5c8ee5
GM
1032/* Value is the number of characters in C string S. MULTIBYTE_P
1033 non-zero means recognize multibyte characters. */
0a9dc68b 1034
5f5c8ee5
GM
1035static int
1036number_of_chars (s, multibyte_p)
1037 unsigned char *s;
1038 int multibyte_p;
1039{
1040 int nchars;
1041
1042 if (multibyte_p)
1043 {
1044 int rest = strlen (s), len;
1045 unsigned char *p = (unsigned char *) s;
0a9dc68b 1046
5f5c8ee5
GM
1047 for (nchars = 0; rest > 0; ++nchars)
1048 {
4fdb80f2 1049 string_char_and_length (p, rest, &len);
5f5c8ee5 1050 rest -= len, p += len;
0a9dc68b
RS
1051 }
1052 }
5f5c8ee5
GM
1053 else
1054 nchars = strlen (s);
1055
1056 return nchars;
0b1005ef
KH
1057}
1058
5f5c8ee5
GM
1059
1060/* Compute byte position NEWPOS->bytepos corresponding to
1061 NEWPOS->charpos. POS is a known position in string STRING.
1062 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1063
5f5c8ee5
GM
1064static void
1065compute_string_pos (newpos, pos, string)
1066 struct text_pos *newpos, pos;
1067 Lisp_Object string;
76412d64 1068{
5f5c8ee5
GM
1069 xassert (STRINGP (string));
1070 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
1071
1072 if (STRING_MULTIBYTE (string))
6fc556fd
KR
1073 *newpos = string_pos_nchars_ahead (pos, string,
1074 CHARPOS (*newpos) - CHARPOS (pos));
5f5c8ee5
GM
1075 else
1076 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1077}
1078
9c74a0dd 1079
5f5c8ee5
GM
1080\f
1081/***********************************************************************
1082 Lisp form evaluation
1083 ***********************************************************************/
1084
0d8b31c0 1085/* Error handler for eval_form and call_function. */
5f5c8ee5
GM
1086
1087static Lisp_Object
1088eval_handler (arg)
1089 Lisp_Object arg;
1090{
1091 return Qnil;
1092}
1093
1094
1095/* Evaluate SEXPR and return the result, or nil if something went
1096 wrong. */
1097
71e5b1b8 1098Lisp_Object
5f5c8ee5
GM
1099eval_form (sexpr)
1100 Lisp_Object sexpr;
1101{
1102 int count = specpdl_ptr - specpdl;
0d8b31c0 1103 struct gcpro gcpro1;
5f5c8ee5 1104 Lisp_Object val;
0d8b31c0
GM
1105
1106 GCPRO1 (sexpr);
5f5c8ee5
GM
1107 specbind (Qinhibit_redisplay, Qt);
1108 val = internal_condition_case_1 (Feval, sexpr, Qerror, eval_handler);
0d8b31c0
GM
1109 UNGCPRO;
1110 return unbind_to (count, val);
1111}
1112
1113
1114/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
1115 Return the result, or nil if something went wrong. */
1116
1117Lisp_Object
1118call_function (nargs, args)
1119 int nargs;
1120 Lisp_Object *args;
1121{
1122 int count = specpdl_ptr - specpdl;
1123 Lisp_Object val;
1124 struct gcpro gcpro1;
1125
1126 GCPRO1 (args[0]);
1127 gcpro1.nvars = nargs;
1128 specbind (Qinhibit_redisplay, Qt);
1129 val = internal_condition_case_2 (Ffuncall, nargs, args, Qerror,
1130 eval_handler);
1131 UNGCPRO;
5f5c8ee5
GM
1132 return unbind_to (count, val);
1133}
1134
1135
1136\f
1137/***********************************************************************
1138 Debugging
1139 ***********************************************************************/
1140
1141#if 0
1142
1143/* Define CHECK_IT to perform sanity checks on iterators.
1144 This is for debugging. It is too slow to do unconditionally. */
1145
1146static void
1147check_it (it)
1148 struct it *it;
1149{
1150 if (it->method == next_element_from_string)
a2889657 1151 {
5f5c8ee5
GM
1152 xassert (STRINGP (it->string));
1153 xassert (IT_STRING_CHARPOS (*it) >= 0);
1154 }
1155 else if (it->method == next_element_from_buffer)
1156 {
1157 /* Check that character and byte positions agree. */
1158 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1159 }
73af359d 1160
5f5c8ee5
GM
1161 if (it->dpvec)
1162 xassert (it->current.dpvec_index >= 0);
1163 else
1164 xassert (it->current.dpvec_index < 0);
1165}
1f40cad2 1166
5f5c8ee5
GM
1167#define CHECK_IT(IT) check_it ((IT))
1168
1169#else /* not 0 */
1170
1171#define CHECK_IT(IT) (void) 0
1172
1173#endif /* not 0 */
1174
1175
1176#if GLYPH_DEBUG
1177
1178/* Check that the window end of window W is what we expect it
1179 to be---the last row in the current matrix displaying text. */
1180
1181static void
1182check_window_end (w)
1183 struct window *w;
1184{
1185 if (!MINI_WINDOW_P (w)
1186 && !NILP (w->window_end_valid))
1187 {
1188 struct glyph_row *row;
1189 xassert ((row = MATRIX_ROW (w->current_matrix,
1190 XFASTINT (w->window_end_vpos)),
1191 !row->enabled_p
1192 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1193 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1194 }
1195}
1196
1197#define CHECK_WINDOW_END(W) check_window_end ((W))
1198
1199#else /* not GLYPH_DEBUG */
1200
1201#define CHECK_WINDOW_END(W) (void) 0
1202
1203#endif /* not GLYPH_DEBUG */
1204
1205
1206\f
1207/***********************************************************************
1208 Iterator initialization
1209 ***********************************************************************/
1210
1211/* Initialize IT for displaying current_buffer in window W, starting
1212 at character position CHARPOS. CHARPOS < 0 means that no buffer
1213 position is specified which is useful when the iterator is assigned
1214 a position later. BYTEPOS is the byte position corresponding to
1215 CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS.
1216
1217 If ROW is not null, calls to produce_glyphs with IT as parameter
1218 will produce glyphs in that row.
1219
1220 BASE_FACE_ID is the id of a base face to use. It must be one of
1221 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or
045dee35 1222 HEADER_LINE_FACE_ID for displaying mode lines, or TOOL_BAR_FACE_ID for
e037b9ec 1223 displaying the tool-bar.
5f5c8ee5
GM
1224
1225 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or
045dee35 1226 HEADER_LINE_FACE_ID, the iterator will be initialized to use the
5f5c8ee5
GM
1227 corresponding mode line glyph row of the desired matrix of W. */
1228
1229void
1230init_iterator (it, w, charpos, bytepos, row, base_face_id)
1231 struct it *it;
1232 struct window *w;
1233 int charpos, bytepos;
1234 struct glyph_row *row;
1235 enum face_id base_face_id;
1236{
1237 int highlight_region_p;
5f5c8ee5
GM
1238
1239 /* Some precondition checks. */
1240 xassert (w != NULL && it != NULL);
5f5c8ee5
GM
1241 xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
1242
1243 /* If face attributes have been changed since the last redisplay,
1244 free realized faces now because they depend on face definitions
1245 that might have changed. */
1246 if (face_change_count)
1247 {
1248 face_change_count = 0;
1249 free_all_realized_faces (Qnil);
1250 }
1251
1252 /* Use one of the mode line rows of W's desired matrix if
1253 appropriate. */
1254 if (row == NULL)
1255 {
1256 if (base_face_id == MODE_LINE_FACE_ID)
1257 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
1258 else if (base_face_id == HEADER_LINE_FACE_ID)
1259 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5
GM
1260 }
1261
1262 /* Clear IT. */
1263 bzero (it, sizeof *it);
1264 it->current.overlay_string_index = -1;
1265 it->current.dpvec_index = -1;
5f5c8ee5
GM
1266 it->base_face_id = base_face_id;
1267
1268 /* The window in which we iterate over current_buffer: */
1269 XSETWINDOW (it->window, w);
1270 it->w = w;
1271 it->f = XFRAME (w->frame);
1272
d475bcb8
GM
1273 /* Extra space between lines (on window systems only). */
1274 if (base_face_id == DEFAULT_FACE_ID
1275 && FRAME_WINDOW_P (it->f))
1276 {
1277 if (NATNUMP (current_buffer->extra_line_spacing))
1278 it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
1279 else if (it->f->extra_line_spacing > 0)
1280 it->extra_line_spacing = it->f->extra_line_spacing;
1281 }
1282
5f5c8ee5
GM
1283 /* If realized faces have been removed, e.g. because of face
1284 attribute changes of named faces, recompute them. */
1285 if (FRAME_FACE_CACHE (it->f)->used == 0)
1286 recompute_basic_faces (it->f);
1287
5f5c8ee5
GM
1288 /* Current value of the `space-width', and 'height' properties. */
1289 it->space_width = Qnil;
1290 it->font_height = Qnil;
1291
1292 /* Are control characters displayed as `^C'? */
1293 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
1294
1295 /* -1 means everything between a CR and the following line end
1296 is invisible. >0 means lines indented more than this value are
1297 invisible. */
1298 it->selective = (INTEGERP (current_buffer->selective_display)
1299 ? XFASTINT (current_buffer->selective_display)
1300 : (!NILP (current_buffer->selective_display)
1301 ? -1 : 0));
1302 it->selective_display_ellipsis_p
1303 = !NILP (current_buffer->selective_display_ellipses);
1304
1305 /* Display table to use. */
1306 it->dp = window_display_table (w);
1307
1308 /* Are multibyte characters enabled in current_buffer? */
1309 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1310
1311 /* Non-zero if we should highlight the region. */
1312 highlight_region_p
1313 = (!NILP (Vtransient_mark_mode)
1314 && !NILP (current_buffer->mark_active)
1315 && XMARKER (current_buffer->mark)->buffer != 0);
1316
1317 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
1318 start and end of a visible region in window IT->w. Set both to
1319 -1 to indicate no region. */
1320 if (highlight_region_p
1321 /* Maybe highlight only in selected window. */
1322 && (/* Either show region everywhere. */
1323 highlight_nonselected_windows
1324 /* Or show region in the selected window. */
1325 || w == XWINDOW (selected_window)
1326 /* Or show the region if we are in the mini-buffer and W is
1327 the window the mini-buffer refers to. */
1328 || (MINI_WINDOW_P (XWINDOW (selected_window))
1329 && w == XWINDOW (Vminibuf_scroll_window))))
1330 {
1331 int charpos = marker_position (current_buffer->mark);
1332 it->region_beg_charpos = min (PT, charpos);
1333 it->region_end_charpos = max (PT, charpos);
1334 }
1335 else
1336 it->region_beg_charpos = it->region_end_charpos = -1;
1337
1338 /* Get the position at which the redisplay_end_trigger hook should
1339 be run, if it is to be run at all. */
1340 if (MARKERP (w->redisplay_end_trigger)
1341 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
1342 it->redisplay_end_trigger_charpos
1343 = marker_position (w->redisplay_end_trigger);
1344 else if (INTEGERP (w->redisplay_end_trigger))
1345 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
1346
1347 /* Correct bogus values of tab_width. */
1348 it->tab_width = XINT (current_buffer->tab_width);
1349 if (it->tab_width <= 0 || it->tab_width > 1000)
1350 it->tab_width = 8;
1351
1352 /* Are lines in the display truncated? */
1353 it->truncate_lines_p
1354 = (base_face_id != DEFAULT_FACE_ID
1355 || XINT (it->w->hscroll)
1356 || (truncate_partial_width_windows
1357 && !WINDOW_FULL_WIDTH_P (it->w))
1358 || !NILP (current_buffer->truncate_lines));
1359
1360 /* Get dimensions of truncation and continuation glyphs. These are
1361 displayed as bitmaps under X, so we don't need them for such
1362 frames. */
1363 if (!FRAME_WINDOW_P (it->f))
1364 {
1365 if (it->truncate_lines_p)
1366 {
1367 /* We will need the truncation glyph. */
1368 xassert (it->glyph_row == NULL);
1369 produce_special_glyphs (it, IT_TRUNCATION);
1370 it->truncation_pixel_width = it->pixel_width;
1371 }
1372 else
1373 {
1374 /* We will need the continuation glyph. */
1375 xassert (it->glyph_row == NULL);
1376 produce_special_glyphs (it, IT_CONTINUATION);
1377 it->continuation_pixel_width = it->pixel_width;
1378 }
1379
1380 /* Reset these values to zero becaue the produce_special_glyphs
1381 above has changed them. */
1382 it->pixel_width = it->ascent = it->descent = 0;
312246d1 1383 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
1384 }
1385
1386 /* Set this after getting the dimensions of truncation and
1387 continuation glyphs, so that we don't produce glyphs when calling
1388 produce_special_glyphs, above. */
1389 it->glyph_row = row;
1390 it->area = TEXT_AREA;
1391
1392 /* Get the dimensions of the display area. The display area
1393 consists of the visible window area plus a horizontally scrolled
1394 part to the left of the window. All x-values are relative to the
1395 start of this total display area. */
1396 if (base_face_id != DEFAULT_FACE_ID)
1397 {
1398 /* Mode lines, menu bar in terminal frames. */
1399 it->first_visible_x = 0;
1400 it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
1401 }
1402 else
1403 {
1404 it->first_visible_x
1405 = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
1406 it->last_visible_x = (it->first_visible_x
1407 + window_box_width (w, TEXT_AREA));
1408
1409 /* If we truncate lines, leave room for the truncator glyph(s) at
1410 the right margin. Otherwise, leave room for the continuation
1411 glyph(s). Truncation and continuation glyphs are not inserted
1412 for window-based redisplay. */
1413 if (!FRAME_WINDOW_P (it->f))
1414 {
1415 if (it->truncate_lines_p)
1416 it->last_visible_x -= it->truncation_pixel_width;
1417 else
1418 it->last_visible_x -= it->continuation_pixel_width;
1419 }
1420
045dee35
GM
1421 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
1422 it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
1423 }
1424
1425 /* Leave room for a border glyph. */
1426 if (!FRAME_WINDOW_P (it->f)
1427 && !WINDOW_RIGHTMOST_P (it->w))
1428 it->last_visible_x -= 1;
1429
1430 it->last_visible_y = window_text_bottom_y (w);
1431
1432 /* For mode lines and alike, arrange for the first glyph having a
1433 left box line if the face specifies a box. */
1434 if (base_face_id != DEFAULT_FACE_ID)
1435 {
1436 struct face *face;
1437
1438 it->face_id = base_face_id;
1439
1440 /* If we have a boxed mode line, make the first character appear
1441 with a left box line. */
1442 face = FACE_FROM_ID (it->f, base_face_id);
1443 if (face->box != FACE_NO_BOX)
1444 it->start_of_box_run_p = 1;
1445 }
1446
1447 /* If a buffer position was specified, set the iterator there,
1448 getting overlays and face properties from that position. */
1449 if (charpos > 0)
1450 {
1451 it->end_charpos = ZV;
1452 it->face_id = -1;
1453 IT_CHARPOS (*it) = charpos;
1454
1455 /* Compute byte position if not specified. */
1456 if (bytepos <= 0)
1457 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
1458 else
1459 IT_BYTEPOS (*it) = bytepos;
1460
1461 /* Compute faces etc. */
1462 reseat (it, it->current.pos, 1);
1463 }
1464
1465 CHECK_IT (it);
1466}
1467
1468
1469/* Initialize IT for the display of window W with window start POS. */
1470
1471void
1472start_display (it, w, pos)
1473 struct it *it;
1474 struct window *w;
1475 struct text_pos pos;
1476{
1477 int start_at_line_beg_p;
1478 struct glyph_row *row;
045dee35 1479 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
1480 int first_y;
1481
1482 row = w->desired_matrix->rows + first_vpos;
1483 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
1484 first_y = it->current_y;
1485
1486 /* If window start is not at a line start, move back to the line
1487 start. This makes sure that we take continuation lines into
1488 account. */
1489 start_at_line_beg_p = (CHARPOS (pos) == BEGV
1490 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
1491 if (!start_at_line_beg_p)
1492 reseat_at_previous_visible_line_start (it);
1493
5f5c8ee5
GM
1494 /* If window start is not at a line start, skip forward to POS to
1495 get the correct continuation_lines_width and current_x. */
1496 if (!start_at_line_beg_p)
1497 {
1498 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
1499
1500 /* If lines are continued, this line may end in the middle of a
1501 multi-glyph character (e.g. a control character displayed as
1502 \003, or in the middle of an overlay string). In this case
1503 move_it_to above will not have taken us to the start of
1504 the continuation line but to the end of the continued line. */
b28cb6ed 1505 if (!it->truncate_lines_p)
5f5c8ee5 1506 {
b28cb6ed 1507 if (it->current_x > 0)
5f5c8ee5 1508 {
b28cb6ed
GM
1509 if (it->current.dpvec_index >= 0
1510 || it->current.overlay_string_index >= 0)
1511 {
1512 set_iterator_to_next (it);
1513 move_it_in_display_line_to (it, -1, -1, 0);
1514 }
1515
1516 it->continuation_lines_width += it->current_x;
5f5c8ee5 1517 }
b28cb6ed
GM
1518
1519 /* We're starting a new display line, not affected by the
1520 height of the continued line, so clear the appropriate
1521 fields in the iterator structure. */
1522 it->max_ascent = it->max_descent = 0;
1523 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5
GM
1524 }
1525
1526 it->current_y = first_y;
1527 it->vpos = 0;
1528 it->current_x = it->hpos = 0;
1529 }
1530
1531#if 0 /* Don't assert the following because start_display is sometimes
1532 called intentionally with a window start that is not at a
1533 line start. Please leave this code in as a comment. */
1534
1535 /* Window start should be on a line start, now. */
1536 xassert (it->continuation_lines_width
1537 || IT_CHARPOS (it) == BEGV
1538 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
1539#endif /* 0 */
1540}
1541
1542
1543/* Initialize IT for stepping through current_buffer in window W,
1544 starting at position POS that includes overlay string and display
1545 vector/ control character translation position information. */
1546
1547static void
1548init_from_display_pos (it, w, pos)
1549 struct it *it;
1550 struct window *w;
1551 struct display_pos *pos;
1552{
1553 /* Keep in mind: the call to reseat in init_iterator skips invisible
1554 text, so we might end up at a position different from POS. This
1555 is only a problem when POS is a row start after a newline and an
1556 overlay starts there with an after-string, and the overlay has an
1557 invisible property. Since we don't skip invisible text in
1558 display_line and elsewhere immediately after consuming the
1559 newline before the row start, such a POS will not be in a string,
1560 but the call to init_iterator below will move us to the
1561 after-string. */
1562 init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos),
1563 NULL, DEFAULT_FACE_ID);
1564
1565 /* If position is within an overlay string, set up IT to
1566 the right overlay string. */
1567 if (pos->overlay_string_index >= 0)
1568 {
1569 int relative_index;
1570
1571 /* We already have the first chunk of overlay strings in
1572 IT->overlay_strings. Load more until the one for
1573 pos->overlay_string_index is in IT->overlay_strings. */
1574 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
1575 {
1576 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
1577 it->current.overlay_string_index = 0;
1578 while (n--)
1579 {
1580 load_overlay_strings (it);
1581 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
1582 }
1583 }
1584
1585 it->current.overlay_string_index = pos->overlay_string_index;
1586 relative_index = (it->current.overlay_string_index
1587 % OVERLAY_STRING_CHUNK_SIZE);
1588 it->string = it->overlay_strings[relative_index];
1589 it->current.string_pos = pos->string_pos;
1590 it->method = next_element_from_string;
1591 }
1592 else if (CHARPOS (pos->string_pos) >= 0)
1593 {
1594 /* Recorded position is not in an overlay string, but in another
1595 string. This can only be a string from a `display' property.
1596 IT should already be filled with that string. */
1597 it->current.string_pos = pos->string_pos;
1598 xassert (STRINGP (it->string));
1599 }
1600
1601 /* Restore position in display vector translations or control
1602 character translations. */
1603 if (pos->dpvec_index >= 0)
1604 {
1605 /* This fills IT->dpvec. */
1606 get_next_display_element (it);
1607 xassert (it->dpvec && it->current.dpvec_index == 0);
1608 it->current.dpvec_index = pos->dpvec_index;
1609 }
1610
1611 CHECK_IT (it);
1612}
1613
1614
1615/* Initialize IT for stepping through current_buffer in window W
1616 starting at ROW->start. */
1617
1618static void
1619init_to_row_start (it, w, row)
1620 struct it *it;
1621 struct window *w;
1622 struct glyph_row *row;
1623{
1624 init_from_display_pos (it, w, &row->start);
1625 it->continuation_lines_width = row->continuation_lines_width;
1626 CHECK_IT (it);
1627}
1628
1629
1630/* Initialize IT for stepping through current_buffer in window W
1631 starting in the line following ROW, i.e. starting at ROW->end. */
1632
1633static void
1634init_to_row_end (it, w, row)
1635 struct it *it;
1636 struct window *w;
1637 struct glyph_row *row;
1638{
1639 init_from_display_pos (it, w, &row->end);
1640
1641 if (row->continued_p)
1642 it->continuation_lines_width = (row->continuation_lines_width
1643 + row->pixel_width);
1644 CHECK_IT (it);
1645}
1646
1647
1648
1649\f
1650/***********************************************************************
1651 Text properties
1652 ***********************************************************************/
1653
1654/* Called when IT reaches IT->stop_charpos. Handle text property and
1655 overlay changes. Set IT->stop_charpos to the next position where
1656 to stop. */
1657
1658static void
1659handle_stop (it)
1660 struct it *it;
1661{
1662 enum prop_handled handled;
1663 int handle_overlay_change_p = 1;
1664 struct props *p;
1665
1666 it->dpvec = NULL;
1667 it->current.dpvec_index = -1;
2970b9be 1668 it->add_overlay_start = 0;
5f5c8ee5
GM
1669
1670 do
1671 {
1672 handled = HANDLED_NORMALLY;
1673
1674 /* Call text property handlers. */
1675 for (p = it_props; p->handler; ++p)
1676 {
1677 handled = p->handler (it);
2970b9be 1678
5f5c8ee5
GM
1679 if (handled == HANDLED_RECOMPUTE_PROPS)
1680 break;
1681 else if (handled == HANDLED_RETURN)
1682 return;
1683 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
1684 handle_overlay_change_p = 0;
1685 }
1686
1687 if (handled != HANDLED_RECOMPUTE_PROPS)
1688 {
1689 /* Don't check for overlay strings below when set to deliver
1690 characters from a display vector. */
1691 if (it->method == next_element_from_display_vector)
1692 handle_overlay_change_p = 0;
1693
1694 /* Handle overlay changes. */
1695 if (handle_overlay_change_p)
1696 handled = handle_overlay_change (it);
1697
1698 /* Determine where to stop next. */
1699 if (handled == HANDLED_NORMALLY)
1700 compute_stop_pos (it);
1701 }
1702 }
1703 while (handled == HANDLED_RECOMPUTE_PROPS);
1704}
1705
1706
1707/* Compute IT->stop_charpos from text property and overlay change
1708 information for IT's current position. */
1709
1710static void
1711compute_stop_pos (it)
1712 struct it *it;
1713{
1714 register INTERVAL iv, next_iv;
1715 Lisp_Object object, limit, position;
1716
1717 /* If nowhere else, stop at the end. */
1718 it->stop_charpos = it->end_charpos;
1719
1720 if (STRINGP (it->string))
1721 {
1722 /* Strings are usually short, so don't limit the search for
1723 properties. */
1724 object = it->string;
1725 limit = Qnil;
1726 XSETFASTINT (position, IT_STRING_CHARPOS (*it));
1727 }
1728 else
1729 {
1730 int charpos;
1731
1732 /* If next overlay change is in front of the current stop pos
1733 (which is IT->end_charpos), stop there. Note: value of
1734 next_overlay_change is point-max if no overlay change
1735 follows. */
1736 charpos = next_overlay_change (IT_CHARPOS (*it));
1737 if (charpos < it->stop_charpos)
1738 it->stop_charpos = charpos;
1739
1740 /* If showing the region, we have to stop at the region
1741 start or end because the face might change there. */
1742 if (it->region_beg_charpos > 0)
1743 {
1744 if (IT_CHARPOS (*it) < it->region_beg_charpos)
1745 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
1746 else if (IT_CHARPOS (*it) < it->region_end_charpos)
1747 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
1748 }
1749
1750 /* Set up variables for computing the stop position from text
1751 property changes. */
1752 XSETBUFFER (object, current_buffer);
1753 XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
1754 XSETFASTINT (position, IT_CHARPOS (*it));
1755
1756 }
1757
1758 /* Get the interval containing IT's position. Value is a null
1759 interval if there isn't such an interval. */
1760 iv = validate_interval_range (object, &position, &position, 0);
1761 if (!NULL_INTERVAL_P (iv))
1762 {
1763 Lisp_Object values_here[LAST_PROP_IDX];
1764 struct props *p;
1765
1766 /* Get properties here. */
1767 for (p = it_props; p->handler; ++p)
1768 values_here[p->idx] = textget (iv->plist, *p->name);
1769
1770 /* Look for an interval following iv that has different
1771 properties. */
1772 for (next_iv = next_interval (iv);
1773 (!NULL_INTERVAL_P (next_iv)
1774 && (NILP (limit)
1775 || XFASTINT (limit) > next_iv->position));
1776 next_iv = next_interval (next_iv))
1777 {
1778 for (p = it_props; p->handler; ++p)
1779 {
1780 Lisp_Object new_value;
1781
1782 new_value = textget (next_iv->plist, *p->name);
1783 if (!EQ (values_here[p->idx], new_value))
1784 break;
1785 }
1786
1787 if (p->handler)
1788 break;
1789 }
1790
1791 if (!NULL_INTERVAL_P (next_iv))
1792 {
1793 if (INTEGERP (limit)
1794 && next_iv->position >= XFASTINT (limit))
1795 /* No text property change up to limit. */
1796 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
1797 else
1798 /* Text properties change in next_iv. */
1799 it->stop_charpos = min (it->stop_charpos, next_iv->position);
1800 }
1801 }
1802
1803 xassert (STRINGP (it->string)
1804 || (it->stop_charpos >= BEGV
1805 && it->stop_charpos >= IT_CHARPOS (*it)));
1806}
1807
1808
1809/* Return the position of the next overlay change after POS in
1810 current_buffer. Value is point-max if no overlay change
1811 follows. This is like `next-overlay-change' but doesn't use
1812 xmalloc. */
1813
1814static int
1815next_overlay_change (pos)
1816 int pos;
1817{
1818 int noverlays;
1819 int endpos;
1820 Lisp_Object *overlays;
1821 int len;
1822 int i;
1823
1824 /* Get all overlays at the given position. */
1825 len = 10;
1826 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 1827 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
1828 if (noverlays > len)
1829 {
1830 len = noverlays;
1831 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 1832 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
1833 }
1834
1835 /* If any of these overlays ends before endpos,
1836 use its ending point instead. */
1837 for (i = 0; i < noverlays; ++i)
1838 {
1839 Lisp_Object oend;
1840 int oendpos;
1841
1842 oend = OVERLAY_END (overlays[i]);
1843 oendpos = OVERLAY_POSITION (oend);
1844 endpos = min (endpos, oendpos);
1845 }
1846
1847 return endpos;
1848}
1849
1850
1851\f
1852/***********************************************************************
1853 Fontification
1854 ***********************************************************************/
1855
1856/* Handle changes in the `fontified' property of the current buffer by
1857 calling hook functions from Qfontification_functions to fontify
1858 regions of text. */
1859
1860static enum prop_handled
1861handle_fontified_prop (it)
1862 struct it *it;
1863{
1864 Lisp_Object prop, pos;
1865 enum prop_handled handled = HANDLED_NORMALLY;
1866
1867 /* Get the value of the `fontified' property at IT's current buffer
1868 position. (The `fontified' property doesn't have a special
1869 meaning in strings.) If the value is nil, call functions from
1870 Qfontification_functions. */
1871 if (!STRINGP (it->string)
1872 && it->s == NULL
1873 && !NILP (Vfontification_functions)
1874 && (pos = make_number (IT_CHARPOS (*it)),
1875 prop = Fget_char_property (pos, Qfontified, Qnil),
1876 NILP (prop)))
1877 {
1878 Lisp_Object args[2];
1879
1880 /* Run the hook functions. */
1881 args[0] = Qfontification_functions;
1882 args[1] = pos;
6fc556fd 1883 Frun_hook_with_args (2, args);
5f5c8ee5
GM
1884
1885 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
1886 something. This avoids an endless loop if they failed to
1887 fontify the text for which reason ever. */
1888 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
1889 handled = HANDLED_RECOMPUTE_PROPS;
1890 }
1891
1892 return handled;
1893}
1894
1895
1896\f
1897/***********************************************************************
1898 Faces
1899 ***********************************************************************/
1900
1901/* Set up iterator IT from face properties at its current position.
1902 Called from handle_stop. */
1903
1904static enum prop_handled
1905handle_face_prop (it)
1906 struct it *it;
1907{
1908 int new_face_id, next_stop;
1909
1910 if (!STRINGP (it->string))
1911 {
1912 new_face_id
1913 = face_at_buffer_position (it->w,
1914 IT_CHARPOS (*it),
1915 it->region_beg_charpos,
1916 it->region_end_charpos,
1917 &next_stop,
1918 (IT_CHARPOS (*it)
1919 + TEXT_PROP_DISTANCE_LIMIT),
1920 0);
1921
1922 /* Is this a start of a run of characters with box face?
1923 Caveat: this can be called for a freshly initialized
1924 iterator; face_id is -1 is this case. We know that the new
1925 face will not change until limit, i.e. if the new face has a
1926 box, all characters up to limit will have one. But, as
1927 usual, we don't know whether limit is really the end. */
1928 if (new_face_id != it->face_id)
1929 {
1930 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1931
1932 /* If new face has a box but old face has not, this is
1933 the start of a run of characters with box, i.e. it has
1934 a shadow on the left side. The value of face_id of the
1935 iterator will be -1 if this is the initial call that gets
1936 the face. In this case, we have to look in front of IT's
1937 position and see whether there is a face != new_face_id. */
1938 it->start_of_box_run_p
1939 = (new_face->box != FACE_NO_BOX
1940 && (it->face_id >= 0
1941 || IT_CHARPOS (*it) == BEG
1942 || new_face_id != face_before_it_pos (it)));
1943 it->face_box_p = new_face->box != FACE_NO_BOX;
1944 }
1945 }
1946 else
1947 {
1948 new_face_id
1949 = face_at_string_position (it->w,
1950 it->string,
1951 IT_STRING_CHARPOS (*it),
1952 (it->current.overlay_string_index >= 0
1953 ? IT_CHARPOS (*it)
1954 : 0),
1955 it->region_beg_charpos,
1956 it->region_end_charpos,
1957 &next_stop,
1958 it->base_face_id);
1959
1960#if 0 /* This shouldn't be neccessary. Let's check it. */
1961 /* If IT is used to display a mode line we would really like to
1962 use the mode line face instead of the frame's default face. */
1963 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
1964 && new_face_id == DEFAULT_FACE_ID)
1965 new_face_id = MODE_LINE_FACE_ID;
1966#endif
1967
1968 /* Is this a start of a run of characters with box? Caveat:
1969 this can be called for a freshly allocated iterator; face_id
1970 is -1 is this case. We know that the new face will not
1971 change until the next check pos, i.e. if the new face has a
1972 box, all characters up to that position will have a
1973 box. But, as usual, we don't know whether that position
1974 is really the end. */
1975 if (new_face_id != it->face_id)
1976 {
1977 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1978 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
1979
1980 /* If new face has a box but old face hasn't, this is the
1981 start of a run of characters with box, i.e. it has a
1982 shadow on the left side. */
1983 it->start_of_box_run_p
1984 = new_face->box && (old_face == NULL || !old_face->box);
1985 it->face_box_p = new_face->box != FACE_NO_BOX;
1986 }
1987 }
1988
1989 it->face_id = new_face_id;
5f5c8ee5
GM
1990 return HANDLED_NORMALLY;
1991}
1992
1993
1994/* Compute the face one character before or after the current position
1995 of IT. BEFORE_P non-zero means get the face in front of IT's
1996 position. Value is the id of the face. */
1997
1998static int
1999face_before_or_after_it_pos (it, before_p)
2000 struct it *it;
2001 int before_p;
2002{
2003 int face_id, limit;
2004 int next_check_charpos;
2005 struct text_pos pos;
2006
2007 xassert (it->s == NULL);
2008
2009 if (STRINGP (it->string))
2010 {
2011 /* No face change past the end of the string (for the case
2012 we are padding with spaces). No face change before the
2013 string start. */
2014 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size
2015 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
2016 return it->face_id;
2017
2018 /* Set pos to the position before or after IT's current position. */
2019 if (before_p)
2020 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
2021 else
260a86a0
KH
2022 /* For composition, we must check the character after the
2023 composition. */
2024 pos = (it->what == IT_COMPOSITION
2025 ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
2026 : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
5f5c8ee5
GM
2027
2028 /* Get the face for ASCII, or unibyte. */
2029 face_id
2030 = face_at_string_position (it->w,
2031 it->string,
2032 CHARPOS (pos),
2033 (it->current.overlay_string_index >= 0
2034 ? IT_CHARPOS (*it)
2035 : 0),
2036 it->region_beg_charpos,
2037 it->region_end_charpos,
2038 &next_check_charpos,
2039 it->base_face_id);
2040
2041 /* Correct the face for charsets different from ASCII. Do it
2042 for the multibyte case only. The face returned above is
2043 suitable for unibyte text if IT->string is unibyte. */
2044 if (STRING_MULTIBYTE (it->string))
2045 {
2046 unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
2047 int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
980806b6
KH
2048 int c, len;
2049 struct face *face = FACE_FROM_ID (it->f, face_id);
5f5c8ee5 2050
4fdb80f2 2051 c = string_char_and_length (p, rest, &len);
980806b6 2052 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2053 }
2054 }
2055 else
2056 {
70851746
GM
2057 if ((IT_CHARPOS (*it) >= ZV && !before_p)
2058 || (IT_CHARPOS (*it) <= BEGV && before_p))
2059 return it->face_id;
2060
5f5c8ee5
GM
2061 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
2062 pos = it->current.pos;
2063
2064 if (before_p)
c1005d06 2065 DEC_TEXT_POS (pos, it->multibyte_p);
5f5c8ee5 2066 else
260a86a0
KH
2067 {
2068 if (it->what == IT_COMPOSITION)
2069 /* For composition, we must check the position after the
2070 composition. */
2071 pos.charpos += it->cmp_len, pos.bytepos += it->len;
2072 else
c1005d06 2073 INC_TEXT_POS (pos, it->multibyte_p);
260a86a0 2074 }
5f5c8ee5
GM
2075 /* Determine face for CHARSET_ASCII, or unibyte. */
2076 face_id = face_at_buffer_position (it->w,
2077 CHARPOS (pos),
2078 it->region_beg_charpos,
2079 it->region_end_charpos,
2080 &next_check_charpos,
2081 limit, 0);
2082
2083 /* Correct the face for charsets different from ASCII. Do it
2084 for the multibyte case only. The face returned above is
2085 suitable for unibyte text if current_buffer is unibyte. */
2086 if (it->multibyte_p)
2087 {
980806b6
KH
2088 int c = FETCH_MULTIBYTE_CHAR (CHARPOS (pos));
2089 struct face *face = FACE_FROM_ID (it->f, face_id);
2090 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2091 }
2092 }
2093
2094 return face_id;
2095}
2096
2097
2098\f
2099/***********************************************************************
2100 Invisible text
2101 ***********************************************************************/
2102
2103/* Set up iterator IT from invisible properties at its current
2104 position. Called from handle_stop. */
2105
2106static enum prop_handled
2107handle_invisible_prop (it)
2108 struct it *it;
2109{
2110 enum prop_handled handled = HANDLED_NORMALLY;
2111
2112 if (STRINGP (it->string))
2113 {
2114 extern Lisp_Object Qinvisible;
2115 Lisp_Object prop, end_charpos, limit, charpos;
2116
2117 /* Get the value of the invisible text property at the
2118 current position. Value will be nil if there is no such
2119 property. */
2120 XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
2121 prop = Fget_text_property (charpos, Qinvisible, it->string);
2122
eadc0bf8
GM
2123 if (!NILP (prop)
2124 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
2125 {
2126 handled = HANDLED_RECOMPUTE_PROPS;
2127
2128 /* Get the position at which the next change of the
2129 invisible text property can be found in IT->string.
2130 Value will be nil if the property value is the same for
2131 all the rest of IT->string. */
2132 XSETINT (limit, XSTRING (it->string)->size);
2133 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2134 it->string, limit);
2135
2136 /* Text at current position is invisible. The next
2137 change in the property is at position end_charpos.
2138 Move IT's current position to that position. */
2139 if (INTEGERP (end_charpos)
2140 && XFASTINT (end_charpos) < XFASTINT (limit))
2141 {
2142 struct text_pos old;
2143 old = it->current.string_pos;
2144 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
2145 compute_string_pos (&it->current.string_pos, old, it->string);
2146 }
2147 else
2148 {
2149 /* The rest of the string is invisible. If this is an
2150 overlay string, proceed with the next overlay string
2151 or whatever comes and return a character from there. */
2152 if (it->current.overlay_string_index >= 0)
2153 {
2154 next_overlay_string (it);
2155 /* Don't check for overlay strings when we just
2156 finished processing them. */
2157 handled = HANDLED_OVERLAY_STRING_CONSUMED;
2158 }
2159 else
2160 {
2161 struct Lisp_String *s = XSTRING (it->string);
2162 IT_STRING_CHARPOS (*it) = s->size;
2163 IT_STRING_BYTEPOS (*it) = STRING_BYTES (s);
2164 }
2165 }
2166 }
2167 }
2168 else
2169 {
2170 int visible_p, newpos, next_stop;
2171 Lisp_Object pos, prop;
2172
2173 /* First of all, is there invisible text at this position? */
2174 XSETFASTINT (pos, IT_CHARPOS (*it));
2175 prop = Fget_char_property (pos, Qinvisible, it->window);
2176
2177 /* If we are on invisible text, skip over it. */
eadc0bf8
GM
2178 if (TEXT_PROP_MEANS_INVISIBLE (prop)
2179 && IT_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
2180 {
2181 /* Record whether we have to display an ellipsis for the
2182 invisible text. */
2183 int display_ellipsis_p
2184 = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
2185
2186 handled = HANDLED_RECOMPUTE_PROPS;
2970b9be 2187 it->add_overlay_start = IT_CHARPOS (*it);
5f5c8ee5
GM
2188
2189 /* Loop skipping over invisible text. The loop is left at
2190 ZV or with IT on the first char being visible again. */
2191 do
2192 {
2193 /* Try to skip some invisible text. Return value is the
2194 position reached which can be equal to IT's position
2195 if there is nothing invisible here. This skips both
2196 over invisible text properties and overlays with
2197 invisible property. */
2198 newpos = skip_invisible (IT_CHARPOS (*it),
2199 &next_stop, ZV, it->window);
2200
2201 /* If we skipped nothing at all we weren't at invisible
2202 text in the first place. If everything to the end of
2203 the buffer was skipped, end the loop. */
2204 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
2205 visible_p = 1;
2206 else
2207 {
2208 /* We skipped some characters but not necessarily
2209 all there are. Check if we ended up on visible
2210 text. Fget_char_property returns the property of
2211 the char before the given position, i.e. if we
2212 get visible_p = 1, this means that the char at
2213 newpos is visible. */
2214 XSETFASTINT (pos, newpos);
2215 prop = Fget_char_property (pos, Qinvisible, it->window);
2216 visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
2217 }
2218
2219 /* If we ended up on invisible text, proceed to
2220 skip starting with next_stop. */
2221 if (!visible_p)
2222 IT_CHARPOS (*it) = next_stop;
2223 }
2224 while (!visible_p);
2225
2226 /* The position newpos is now either ZV or on visible text. */
2227 IT_CHARPOS (*it) = newpos;
2228 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2229
2230 /* Maybe return `...' next for the end of the invisible text. */
2231 if (display_ellipsis_p)
2232 {
2233 if (it->dp
2234 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
2235 {
2236 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
2237 it->dpvec = v->contents;
2238 it->dpend = v->contents + v->size;
2239 }
2240 else
2241 {
2242 /* Default `...'. */
2243 it->dpvec = default_invis_vector;
2244 it->dpend = default_invis_vector + 3;
2245 }
2246
2247 /* The ellipsis display does not replace the display of
2248 the character at the new position. Indicate this by
2249 setting IT->dpvec_char_len to zero. */
2250 it->dpvec_char_len = 0;
2251
2252 it->current.dpvec_index = 0;
2253 it->method = next_element_from_display_vector;
2254 }
2255 }
2256 }
2257
2258 return handled;
2259}
2260
2261
2262\f
2263/***********************************************************************
2264 'display' property
2265 ***********************************************************************/
2266
2267/* Set up iterator IT from `display' property at its current position.
2268 Called from handle_stop. */
2269
2270static enum prop_handled
2271handle_display_prop (it)
2272 struct it *it;
2273{
2274 Lisp_Object prop, object;
2275 struct text_pos *position;
2276 int space_or_image_found_p;
2277
2278 if (STRINGP (it->string))
2279 {
2280 object = it->string;
2281 position = &it->current.string_pos;
2282 }
2283 else
2284 {
2285 object = Qnil;
2286 position = &it->current.pos;
2287 }
2288
2289 /* Reset those iterator values set from display property values. */
2290 it->font_height = Qnil;
2291 it->space_width = Qnil;
2292 it->voffset = 0;
2293
2294 /* We don't support recursive `display' properties, i.e. string
2295 values that have a string `display' property, that have a string
2296 `display' property etc. */
2297 if (!it->string_from_display_prop_p)
2298 it->area = TEXT_AREA;
2299
2300 prop = Fget_char_property (make_number (position->charpos),
2301 Qdisplay, object);
2302 if (NILP (prop))
2303 return HANDLED_NORMALLY;
2304
2305 space_or_image_found_p = 0;
f3751a65
GM
2306 if (CONSP (prop)
2307 && CONSP (XCAR (prop))
2308 && !EQ (Qmargin, XCAR (XCAR (prop))))
5f5c8ee5 2309 {
f3751a65 2310 /* A list of sub-properties. */
5f5c8ee5
GM
2311 while (CONSP (prop))
2312 {
2313 if (handle_single_display_prop (it, XCAR (prop), object, position))
2314 space_or_image_found_p = 1;
2315 prop = XCDR (prop);
2316 }
2317 }
2318 else if (VECTORP (prop))
2319 {
2320 int i;
2321 for (i = 0; i < XVECTOR (prop)->size; ++i)
2322 if (handle_single_display_prop (it, XVECTOR (prop)->contents[i],
2323 object, position))
2324 space_or_image_found_p = 1;
2325 }
2326 else
2327 {
2328 if (handle_single_display_prop (it, prop, object, position))
2329 space_or_image_found_p = 1;
2330 }
2331
2332 return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY;
2333}
2334
2335
6c577098 2336/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
2337 at START_POS in OBJECT. */
2338
2339static struct text_pos
2340display_prop_end (it, object, start_pos)
2341 struct it *it;
2342 Lisp_Object object;
2343 struct text_pos start_pos;
2344{
2345 Lisp_Object end;
2346 struct text_pos end_pos;
5f5c8ee5 2347
016b5642
MB
2348 end = Fnext_single_char_property_change (make_number (CHARPOS (start_pos)),
2349 Qdisplay, object, Qnil);
6c577098
GM
2350 CHARPOS (end_pos) = XFASTINT (end);
2351 if (STRINGP (object))
5f5c8ee5
GM
2352 compute_string_pos (&end_pos, start_pos, it->string);
2353 else
6c577098 2354 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
2355
2356 return end_pos;
2357}
2358
2359
2360/* Set up IT from a single `display' sub-property value PROP. OBJECT
2361 is the object in which the `display' property was found. *POSITION
2362 is the position at which it was found.
2363
2364 If PROP is a `space' or `image' sub-property, set *POSITION to the
2365 end position of the `display' property.
2366
2367 Value is non-zero if a `space' or `image' property value was found. */
2368
2369static int
2370handle_single_display_prop (it, prop, object, position)
2371 struct it *it;
2372 Lisp_Object prop;
2373 Lisp_Object object;
2374 struct text_pos *position;
2375{
2376 Lisp_Object value;
2377 int space_or_image_found_p = 0;
5f5c8ee5
GM
2378 Lisp_Object form;
2379
d3acf96b 2380 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
5a4c88c4 2381 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 2382 form = Qt;
d3acf96b 2383 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
2384 {
2385 prop = XCDR (prop);
2386 if (!CONSP (prop))
2387 return 0;
2388 form = XCAR (prop);
2389 prop = XCDR (prop);
5f5c8ee5
GM
2390 }
2391
2392 if (!NILP (form) && !EQ (form, Qt))
2393 {
2394 struct gcpro gcpro1;
2395 struct text_pos end_pos, pt;
2396
5f5c8ee5 2397 GCPRO1 (form);
c7aca1ad 2398 end_pos = display_prop_end (it, object, *position);
5f5c8ee5
GM
2399
2400 /* Temporarily set point to the end position, and then evaluate
2401 the form. This makes `(eolp)' work as FORM. */
c7aca1ad
GM
2402 if (BUFFERP (object))
2403 {
2404 CHARPOS (pt) = PT;
2405 BYTEPOS (pt) = PT_BYTE;
2406 TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
2407 }
2408
5f5c8ee5 2409 form = eval_form (form);
c7aca1ad
GM
2410
2411 if (BUFFERP (object))
2412 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
5f5c8ee5
GM
2413 UNGCPRO;
2414 }
2415
2416 if (NILP (form))
2417 return 0;
2418
2419 if (CONSP (prop)
2420 && EQ (XCAR (prop), Qheight)
2421 && CONSP (XCDR (prop)))
2422 {
2423 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2424 return 0;
2425
2426 /* `(height HEIGHT)'. */
2427 it->font_height = XCAR (XCDR (prop));
2428 if (!NILP (it->font_height))
2429 {
2430 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2431 int new_height = -1;
2432
2433 if (CONSP (it->font_height)
2434 && (EQ (XCAR (it->font_height), Qplus)
2435 || EQ (XCAR (it->font_height), Qminus))
2436 && CONSP (XCDR (it->font_height))
2437 && INTEGERP (XCAR (XCDR (it->font_height))))
2438 {
2439 /* `(+ N)' or `(- N)' where N is an integer. */
2440 int steps = XINT (XCAR (XCDR (it->font_height)));
2441 if (EQ (XCAR (it->font_height), Qplus))
2442 steps = - steps;
2443 it->face_id = smaller_face (it->f, it->face_id, steps);
2444 }
0d8b31c0 2445 else if (FUNCTIONP (it->font_height))
5f5c8ee5
GM
2446 {
2447 /* Call function with current height as argument.
2448 Value is the new height. */
0d8b31c0
GM
2449 Lisp_Object args[2], height;
2450
2451 args[0] = it->font_height;
2452 args[1] = face->lface[LFACE_HEIGHT_INDEX];
2453 height = call_function (2, args);
5f5c8ee5 2454
5f5c8ee5
GM
2455 if (NUMBERP (height))
2456 new_height = XFLOATINT (height);
5f5c8ee5
GM
2457 }
2458 else if (NUMBERP (it->font_height))
2459 {
2460 /* Value is a multiple of the canonical char height. */
2461 struct face *face;
2462
2463 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
2464 new_height = (XFLOATINT (it->font_height)
2465 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
2466 }
2467 else
2468 {
2469 /* Evaluate IT->font_height with `height' bound to the
2470 current specified height to get the new height. */
2471 Lisp_Object value;
2472 int count = specpdl_ptr - specpdl;
2473
2474 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
2475 value = eval_form (it->font_height);
2476 unbind_to (count, Qnil);
2477
2478 if (NUMBERP (value))
2479 new_height = XFLOATINT (value);
2480 }
2481
2482 if (new_height > 0)
2483 it->face_id = face_with_height (it->f, it->face_id, new_height);
2484 }
2485 }
2486 else if (CONSP (prop)
2487 && EQ (XCAR (prop), Qspace_width)
2488 && CONSP (XCDR (prop)))
2489 {
2490 /* `(space_width WIDTH)'. */
2491 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2492 return 0;
2493
2494 value = XCAR (XCDR (prop));
2495 if (NUMBERP (value) && XFLOATINT (value) > 0)
2496 it->space_width = value;
2497 }
2498 else if (CONSP (prop)
2499 && EQ (XCAR (prop), Qraise)
2500 && CONSP (XCDR (prop)))
2501 {
5f5c8ee5
GM
2502 /* `(raise FACTOR)'. */
2503 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2504 return 0;
2505
fb3842a8 2506#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
2507 value = XCAR (XCDR (prop));
2508 if (NUMBERP (value))
2509 {
2510 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2511 it->voffset = - (XFLOATINT (value)
1ab3e082 2512 * (FONT_HEIGHT (face->font)));
5f5c8ee5
GM
2513 }
2514#endif /* HAVE_WINDOW_SYSTEM */
2515 }
2516 else if (!it->string_from_display_prop_p)
2517 {
f3751a65
GM
2518 /* `((margin left-margin) VALUE)' or `((margin right-margin)
2519 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
2520 Lisp_Object location, value;
2521 struct text_pos start_pos;
2522 int valid_p;
2523
2524 /* Characters having this form of property are not displayed, so
2525 we have to find the end of the property. */
5f5c8ee5
GM
2526 start_pos = *position;
2527 *position = display_prop_end (it, object, start_pos);
15e26c76 2528 value = Qnil;
5f5c8ee5
GM
2529
2530 /* Let's stop at the new position and assume that all
2531 text properties change there. */
2532 it->stop_charpos = position->charpos;
2533
f3751a65
GM
2534 location = Qunbound;
2535 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 2536 {
f3751a65
GM
2537 Lisp_Object tem;
2538
5f5c8ee5 2539 value = XCDR (prop);
f3751a65
GM
2540 if (CONSP (value))
2541 value = XCAR (value);
2542
2543 tem = XCAR (prop);
2544 if (EQ (XCAR (tem), Qmargin)
2545 && (tem = XCDR (tem),
2546 tem = CONSP (tem) ? XCAR (tem) : Qnil,
2547 (NILP (tem)
2548 || EQ (tem, Qleft_margin)
2549 || EQ (tem, Qright_margin))))
2550 location = tem;
5f5c8ee5 2551 }
f3751a65
GM
2552
2553 if (EQ (location, Qunbound))
5f5c8ee5
GM
2554 {
2555 location = Qnil;
2556 value = prop;
2557 }
2558
2559#ifdef HAVE_WINDOW_SYSTEM
fb3842a8 2560 if (FRAME_TERMCAP_P (it->f))
5f5c8ee5
GM
2561 valid_p = STRINGP (value);
2562 else
2563 valid_p = (STRINGP (value)
2564 || (CONSP (value) && EQ (XCAR (value), Qspace))
2565 || valid_image_p (value));
2566#else /* not HAVE_WINDOW_SYSTEM */
2567 valid_p = STRINGP (value);
2568#endif /* not HAVE_WINDOW_SYSTEM */
2569
2570 if ((EQ (location, Qleft_margin)
2571 || EQ (location, Qright_margin)
2572 || NILP (location))
2573 && valid_p)
2574 {
a21a3943
GM
2575 space_or_image_found_p = 1;
2576
5f5c8ee5
GM
2577 /* Save current settings of IT so that we can restore them
2578 when we are finished with the glyph property value. */
2579 push_it (it);
2580
2581 if (NILP (location))
2582 it->area = TEXT_AREA;
2583 else if (EQ (location, Qleft_margin))
2584 it->area = LEFT_MARGIN_AREA;
2585 else
2586 it->area = RIGHT_MARGIN_AREA;
2587
2588 if (STRINGP (value))
2589 {
2590 it->string = value;
2591 it->multibyte_p = STRING_MULTIBYTE (it->string);
2592 it->current.overlay_string_index = -1;
2593 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2594 it->end_charpos = it->string_nchars
2595 = XSTRING (it->string)->size;
2596 it->method = next_element_from_string;
2597 it->stop_charpos = 0;
2598 it->string_from_display_prop_p = 1;
2599 }
2600 else if (CONSP (value) && EQ (XCAR (value), Qspace))
2601 {
2602 it->method = next_element_from_stretch;
2603 it->object = value;
2604 it->current.pos = it->position = start_pos;
2605 }
2606#ifdef HAVE_WINDOW_SYSTEM
2607 else
2608 {
2609 it->what = IT_IMAGE;
2610 it->image_id = lookup_image (it->f, value);
2611 it->position = start_pos;
2612 it->object = NILP (object) ? it->w->buffer : object;
2613 it->method = next_element_from_image;
2614
02513cdd 2615 /* Say that we haven't consumed the characters with
5f5c8ee5
GM
2616 `display' property yet. The call to pop_it in
2617 set_iterator_to_next will clean this up. */
2618 *position = start_pos;
2619 }
2620#endif /* HAVE_WINDOW_SYSTEM */
2621 }
a21a3943
GM
2622 else
2623 /* Invalid property or property not supported. Restore
2624 the position to what it was before. */
2625 *position = start_pos;
5f5c8ee5
GM
2626 }
2627
2628 return space_or_image_found_p;
2629}
2630
2631
06568bbf
GM
2632/* Check if PROP is a display sub-property value whose text should be
2633 treated as intangible. */
2634
2635static int
2636single_display_prop_intangible_p (prop)
2637 Lisp_Object prop;
2638{
2639 /* Skip over `when FORM'. */
2640 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
2641 {
2642 prop = XCDR (prop);
2643 if (!CONSP (prop))
2644 return 0;
2645 prop = XCDR (prop);
2646 }
2647
2648 if (!CONSP (prop))
2649 return 0;
2650
2651 /* Skip over `margin LOCATION'. If LOCATION is in the margins,
2652 we don't need to treat text as intangible. */
2653 if (EQ (XCAR (prop), Qmargin))
2654 {
2655 prop = XCDR (prop);
2656 if (!CONSP (prop))
2657 return 0;
2658
2659 prop = XCDR (prop);
2660 if (!CONSP (prop)
2661 || EQ (XCAR (prop), Qleft_margin)
2662 || EQ (XCAR (prop), Qright_margin))
2663 return 0;
2664 }
2665
2666 return CONSP (prop) && EQ (XCAR (prop), Qimage);
2667}
2668
2669
2670/* Check if PROP is a display property value whose text should be
2671 treated as intangible. */
2672
2673int
2674display_prop_intangible_p (prop)
2675 Lisp_Object prop;
2676{
2677 if (CONSP (prop)
2678 && CONSP (XCAR (prop))
2679 && !EQ (Qmargin, XCAR (XCAR (prop))))
2680 {
2681 /* A list of sub-properties. */
2682 while (CONSP (prop))
2683 {
2684 if (single_display_prop_intangible_p (XCAR (prop)))
2685 return 1;
2686 prop = XCDR (prop);
2687 }
2688 }
2689 else if (VECTORP (prop))
2690 {
2691 /* A vector of sub-properties. */
2692 int i;
2693 for (i = 0; i < XVECTOR (prop)->size; ++i)
2694 if (single_display_prop_intangible_p (XVECTOR (prop)->contents[i]))
2695 return 1;
2696 }
2697 else
2698 return single_display_prop_intangible_p (prop);
2699
2700 return 0;
2701}
2702
5f5c8ee5 2703\f
260a86a0
KH
2704/***********************************************************************
2705 `composition' property
2706 ***********************************************************************/
2707
2708/* Set up iterator IT from `composition' property at its current
2709 position. Called from handle_stop. */
2710
2711static enum prop_handled
2712handle_composition_prop (it)
2713 struct it *it;
2714{
2715 Lisp_Object prop, string;
2716 int pos, pos_byte, end;
2717 enum prop_handled handled = HANDLED_NORMALLY;
2718
2719 if (STRINGP (it->string))
2720 {
2721 pos = IT_STRING_CHARPOS (*it);
2722 pos_byte = IT_STRING_BYTEPOS (*it);
2723 string = it->string;
2724 }
2725 else
2726 {
2727 pos = IT_CHARPOS (*it);
2728 pos_byte = IT_BYTEPOS (*it);
2729 string = Qnil;
2730 }
2731
2732 /* If there's a valid composition and point is not inside of the
2733 composition (in the case that the composition is from the current
2734 buffer), draw a glyph composed from the composition components. */
2735 if (find_composition (pos, -1, &pos, &end, &prop, string)
2736 && COMPOSITION_VALID_P (pos, end, prop)
2737 && (STRINGP (it->string) || (PT <= pos || PT >= end)))
2738 {
2739 int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
2740
2741 if (id >= 0)
2742 {
2743 it->method = next_element_from_composition;
2744 it->cmp_id = id;
2745 it->cmp_len = COMPOSITION_LENGTH (prop);
2746 /* For a terminal, draw only the first character of the
2747 components. */
2748 it->c = COMPOSITION_GLYPH (composition_table[id], 0);
2749 it->len = (STRINGP (it->string)
2750 ? string_char_to_byte (it->string, end)
2751 : CHAR_TO_BYTE (end)) - pos_byte;
2752 it->stop_charpos = end;
2753 handled = HANDLED_RETURN;
2754 }
2755 }
2756
2757 return handled;
2758}
2759
2760
2761\f
5f5c8ee5
GM
2762/***********************************************************************
2763 Overlay strings
2764 ***********************************************************************/
2765
2766/* The following structure is used to record overlay strings for
2767 later sorting in load_overlay_strings. */
2768
2769struct overlay_entry
2770{
2970b9be 2771 Lisp_Object overlay;
5f5c8ee5
GM
2772 Lisp_Object string;
2773 int priority;
2774 int after_string_p;
2775};
2776
2777
2778/* Set up iterator IT from overlay strings at its current position.
2779 Called from handle_stop. */
2780
2781static enum prop_handled
2782handle_overlay_change (it)
2783 struct it *it;
2784{
2970b9be
GM
2785 if (!STRINGP (it->string) && get_overlay_strings (it))
2786 return HANDLED_RECOMPUTE_PROPS;
5f5c8ee5 2787 else
2970b9be 2788 return HANDLED_NORMALLY;
5f5c8ee5
GM
2789}
2790
2791
2792/* Set up the next overlay string for delivery by IT, if there is an
2793 overlay string to deliver. Called by set_iterator_to_next when the
2794 end of the current overlay string is reached. If there are more
2795 overlay strings to display, IT->string and
2796 IT->current.overlay_string_index are set appropriately here.
2797 Otherwise IT->string is set to nil. */
2798
2799static void
2800next_overlay_string (it)
2801 struct it *it;
2802{
2803 ++it->current.overlay_string_index;
2804 if (it->current.overlay_string_index == it->n_overlay_strings)
2805 {
2806 /* No more overlay strings. Restore IT's settings to what
2807 they were before overlay strings were processed, and
2808 continue to deliver from current_buffer. */
2809 pop_it (it);
2810 xassert (it->stop_charpos >= BEGV
2811 && it->stop_charpos <= it->end_charpos);
2812 it->string = Qnil;
2813 it->current.overlay_string_index = -1;
2814 SET_TEXT_POS (it->current.string_pos, -1, -1);
2815 it->n_overlay_strings = 0;
2816 it->method = next_element_from_buffer;
2970b9be
GM
2817
2818 /* If we're at the end of the buffer, record that we have
2819 processed the overlay strings there already, so that
2820 next_element_from_buffer doesn't try it again. */
2821 if (IT_CHARPOS (*it) >= it->end_charpos)
2822 it->overlay_strings_at_end_processed_p = 1;
5f5c8ee5
GM
2823 }
2824 else
2825 {
2826 /* There are more overlay strings to process. If
2827 IT->current.overlay_string_index has advanced to a position
2828 where we must load IT->overlay_strings with more strings, do
2829 it. */
2830 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2831
2832 if (it->current.overlay_string_index && i == 0)
2833 load_overlay_strings (it);
2834
2835 /* Initialize IT to deliver display elements from the overlay
2836 string. */
2837 it->string = it->overlay_strings[i];
2838 it->multibyte_p = STRING_MULTIBYTE (it->string);
2839 SET_TEXT_POS (it->current.string_pos, 0, 0);
2840 it->method = next_element_from_string;
2841 it->stop_charpos = 0;
2842 }
2843
2844 CHECK_IT (it);
2845}
2846
2847
2848/* Compare two overlay_entry structures E1 and E2. Used as a
2849 comparison function for qsort in load_overlay_strings. Overlay
2850 strings for the same position are sorted so that
2851
2970b9be
GM
2852 1. All after-strings come in front of before-strings, except
2853 when they come from the same overlay.
5f5c8ee5
GM
2854
2855 2. Within after-strings, strings are sorted so that overlay strings
2856 from overlays with higher priorities come first.
2857
2858 2. Within before-strings, strings are sorted so that overlay
2859 strings from overlays with higher priorities come last.
2860
2861 Value is analogous to strcmp. */
2862
2863
2864static int
2865compare_overlay_entries (e1, e2)
2866 void *e1, *e2;
2867{
2868 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
2869 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
2870 int result;
2871
2872 if (entry1->after_string_p != entry2->after_string_p)
2970b9be
GM
2873 {
2874 /* Let after-strings appear in front of before-strings if
2875 they come from different overlays. */
2876 if (EQ (entry1->overlay, entry2->overlay))
2877 result = entry1->after_string_p ? 1 : -1;
2878 else
2879 result = entry1->after_string_p ? -1 : 1;
2880 }
5f5c8ee5
GM
2881 else if (entry1->after_string_p)
2882 /* After-strings sorted in order of decreasing priority. */
2883 result = entry2->priority - entry1->priority;
2884 else
2885 /* Before-strings sorted in order of increasing priority. */
2886 result = entry1->priority - entry2->priority;
2887
2888 return result;
2889}
2890
2891
2892/* Load the vector IT->overlay_strings with overlay strings from IT's
2893 current buffer position. Set IT->n_overlays to the total number of
2894 overlay strings found.
2895
2896 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
2897 a time. On entry into load_overlay_strings,
2898 IT->current.overlay_string_index gives the number of overlay
2899 strings that have already been loaded by previous calls to this
2900 function.
2901
2970b9be
GM
2902 IT->add_overlay_start contains an additional overlay start
2903 position to consider for taking overlay strings from, if non-zero.
2904 This position comes into play when the overlay has an `invisible'
2905 property, and both before and after-strings. When we've skipped to
2906 the end of the overlay, because of its `invisible' property, we
2907 nevertheless want its before-string to appear.
2908 IT->add_overlay_start will contain the overlay start position
2909 in this case.
2910
5f5c8ee5
GM
2911 Overlay strings are sorted so that after-string strings come in
2912 front of before-string strings. Within before and after-strings,
2913 strings are sorted by overlay priority. See also function
2914 compare_overlay_entries. */
2915
2916static void
2917load_overlay_strings (it)
2918 struct it *it;
2919{
2920 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
2921 Lisp_Object ov, overlay, window, str;
2922 int start, end;
2923 int size = 20;
2924 int n = 0, i, j;
2925 struct overlay_entry *entries
2926 = (struct overlay_entry *) alloca (size * sizeof *entries);
2927
2928 /* Append the overlay string STRING of overlay OVERLAY to vector
2929 `entries' which has size `size' and currently contains `n'
2930 elements. AFTER_P non-zero means STRING is an after-string of
2931 OVERLAY. */
2932#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
2933 do \
2934 { \
2935 Lisp_Object priority; \
2936 \
2937 if (n == size) \
2938 { \
2939 int new_size = 2 * size; \
2940 struct overlay_entry *old = entries; \
2941 entries = \
2942 (struct overlay_entry *) alloca (new_size \
2943 * sizeof *entries); \
2944 bcopy (old, entries, size * sizeof *entries); \
2945 size = new_size; \
2946 } \
2947 \
2948 entries[n].string = (STRING); \
2970b9be 2949 entries[n].overlay = (OVERLAY); \
5f5c8ee5 2950 priority = Foverlay_get ((OVERLAY), Qpriority); \
2970b9be 2951 entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0; \
5f5c8ee5
GM
2952 entries[n].after_string_p = (AFTER_P); \
2953 ++n; \
2954 } \
2955 while (0)
2956
2957 /* Process overlay before the overlay center. */
2970b9be 2958 for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
5f5c8ee5 2959 {
9472f927 2960 overlay = XCAR (ov);
5f5c8ee5
GM
2961 xassert (OVERLAYP (overlay));
2962 start = OVERLAY_POSITION (OVERLAY_START (overlay));
2963 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2964
2965 if (end < IT_CHARPOS (*it))
2966 break;
2967
2968 /* Skip this overlay if it doesn't start or end at IT's current
2969 position. */
2970b9be
GM
2970 if (end != IT_CHARPOS (*it)
2971 && start != IT_CHARPOS (*it)
2972 && it->add_overlay_start != IT_CHARPOS (*it))
5f5c8ee5
GM
2973 continue;
2974
2975 /* Skip this overlay if it doesn't apply to IT->w. */
2976 window = Foverlay_get (overlay, Qwindow);
2977 if (WINDOWP (window) && XWINDOW (window) != it->w)
2978 continue;
2979
2980 /* If overlay has a non-empty before-string, record it. */
2970b9be
GM
2981 if ((start == IT_CHARPOS (*it)
2982 || start == it->add_overlay_start)
5f5c8ee5
GM
2983 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2984 && XSTRING (str)->size)
2985 RECORD_OVERLAY_STRING (overlay, str, 0);
2986
2987 /* If overlay has a non-empty after-string, record it. */
2988 if (end == IT_CHARPOS (*it)
2989 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2990 && XSTRING (str)->size)
2991 RECORD_OVERLAY_STRING (overlay, str, 1);
2992 }
2993
2994 /* Process overlays after the overlay center. */
2970b9be 2995 for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
5f5c8ee5 2996 {
9472f927 2997 overlay = XCAR (ov);
5f5c8ee5
GM
2998 xassert (OVERLAYP (overlay));
2999 start = OVERLAY_POSITION (OVERLAY_START (overlay));
3000 end = OVERLAY_POSITION (OVERLAY_END (overlay));
3001
3002 if (start > IT_CHARPOS (*it))
3003 break;
3004
3005 /* Skip this overlay if it doesn't start or end at IT's current
3006 position. */
2970b9be
GM
3007 if (end != IT_CHARPOS (*it)
3008 && start != IT_CHARPOS (*it)
3009 && it->add_overlay_start != IT_CHARPOS (*it))
5f5c8ee5
GM
3010 continue;
3011
3012 /* Skip this overlay if it doesn't apply to IT->w. */
3013 window = Foverlay_get (overlay, Qwindow);
3014 if (WINDOWP (window) && XWINDOW (window) != it->w)
3015 continue;
3016
3017 /* If overlay has a non-empty before-string, record it. */
2970b9be
GM
3018 if ((start == IT_CHARPOS (*it)
3019 || start == it->add_overlay_start)
5f5c8ee5
GM
3020 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
3021 && XSTRING (str)->size)
3022 RECORD_OVERLAY_STRING (overlay, str, 0);
3023
3024 /* If overlay has a non-empty after-string, record it. */
3025 if (end == IT_CHARPOS (*it)
3026 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
3027 && XSTRING (str)->size)
3028 RECORD_OVERLAY_STRING (overlay, str, 1);
3029 }
3030
3031#undef RECORD_OVERLAY_STRING
3032
3033 /* Sort entries. */
2970b9be
GM
3034 if (n)
3035 qsort (entries, n, sizeof *entries, compare_overlay_entries);
5f5c8ee5
GM
3036
3037 /* Record the total number of strings to process. */
3038 it->n_overlay_strings = n;
3039
3040 /* IT->current.overlay_string_index is the number of overlay strings
3041 that have already been consumed by IT. Copy some of the
3042 remaining overlay strings to IT->overlay_strings. */
3043 i = 0;
3044 j = it->current.overlay_string_index;
3045 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
3046 it->overlay_strings[i++] = entries[j++].string;
2970b9be 3047
5f5c8ee5
GM
3048 CHECK_IT (it);
3049}
3050
3051
3052/* Get the first chunk of overlay strings at IT's current buffer
3053 position. Value is non-zero if at least one overlay string was
3054 found. */
3055
3056static int
3057get_overlay_strings (it)
3058 struct it *it;
3059{
3060 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
3061 process. This fills IT->overlay_strings with strings, and sets
3062 IT->n_overlay_strings to the total number of strings to process.
3063 IT->pos.overlay_string_index has to be set temporarily to zero
3064 because load_overlay_strings needs this; it must be set to -1
3065 when no overlay strings are found because a zero value would
3066 indicate a position in the first overlay string. */
3067 it->current.overlay_string_index = 0;
3068 load_overlay_strings (it);
3069
3070 /* If we found overlay strings, set up IT to deliver display
3071 elements from the first one. Otherwise set up IT to deliver
3072 from current_buffer. */
3073 if (it->n_overlay_strings)
3074 {
3075 /* Make sure we know settings in current_buffer, so that we can
3076 restore meaningful values when we're done with the overlay
3077 strings. */
3078 compute_stop_pos (it);
3079 xassert (it->face_id >= 0);
3080
3081 /* Save IT's settings. They are restored after all overlay
3082 strings have been processed. */
3083 xassert (it->sp == 0);
3084 push_it (it);
3085
3086 /* Set up IT to deliver display elements from the first overlay
3087 string. */
3088 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
3089 it->stop_charpos = 0;
3090 it->string = it->overlay_strings[0];
3091 it->multibyte_p = STRING_MULTIBYTE (it->string);
3092 xassert (STRINGP (it->string));
3093 it->method = next_element_from_string;
3094 }
3095 else
3096 {
3097 it->string = Qnil;
3098 it->current.overlay_string_index = -1;
3099 it->method = next_element_from_buffer;
3100 }
3101
3102 CHECK_IT (it);
3103
3104 /* Value is non-zero if we found at least one overlay string. */
3105 return STRINGP (it->string);
3106}
3107
3108
3109\f
3110/***********************************************************************
3111 Saving and restoring state
3112 ***********************************************************************/
3113
3114/* Save current settings of IT on IT->stack. Called, for example,
3115 before setting up IT for an overlay string, to be able to restore
3116 IT's settings to what they were after the overlay string has been
3117 processed. */
3118
3119static void
3120push_it (it)
3121 struct it *it;
3122{
3123 struct iterator_stack_entry *p;
3124
3125 xassert (it->sp < 2);
3126 p = it->stack + it->sp;
3127
3128 p->stop_charpos = it->stop_charpos;
3129 xassert (it->face_id >= 0);
3130 p->face_id = it->face_id;
3131 p->string = it->string;
3132 p->pos = it->current;
3133 p->end_charpos = it->end_charpos;
3134 p->string_nchars = it->string_nchars;
3135 p->area = it->area;
3136 p->multibyte_p = it->multibyte_p;
3137 p->space_width = it->space_width;
3138 p->font_height = it->font_height;
3139 p->voffset = it->voffset;
3140 p->string_from_display_prop_p = it->string_from_display_prop_p;
3141 ++it->sp;
3142}
3143
3144
3145/* Restore IT's settings from IT->stack. Called, for example, when no
3146 more overlay strings must be processed, and we return to delivering
3147 display elements from a buffer, or when the end of a string from a
3148 `display' property is reached and we return to delivering display
3149 elements from an overlay string, or from a buffer. */
3150
3151static void
3152pop_it (it)
3153 struct it *it;
3154{
3155 struct iterator_stack_entry *p;
3156
3157 xassert (it->sp > 0);
3158 --it->sp;
3159 p = it->stack + it->sp;
3160 it->stop_charpos = p->stop_charpos;
3161 it->face_id = p->face_id;
3162 it->string = p->string;
3163 it->current = p->pos;
3164 it->end_charpos = p->end_charpos;
3165 it->string_nchars = p->string_nchars;
3166 it->area = p->area;
3167 it->multibyte_p = p->multibyte_p;
3168 it->space_width = p->space_width;
3169 it->font_height = p->font_height;
3170 it->voffset = p->voffset;
3171 it->string_from_display_prop_p = p->string_from_display_prop_p;
3172}
3173
3174
3175\f
3176/***********************************************************************
3177 Moving over lines
3178 ***********************************************************************/
3179
3180/* Set IT's current position to the previous line start. */
3181
3182static void
3183back_to_previous_line_start (it)
3184 struct it *it;
3185{
3186 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
3187 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3188}
3189
3190
3191/* Set IT's current position to the next line start. */
3192
3193static void
3194forward_to_next_line_start (it)
3195 struct it *it;
3196{
3197 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it), 1);
3198 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3199}
3200
3201
3202/* Set IT's current position to the previous visible line start. Skip
3203 invisible text that is so either due to text properties or due to
3204 selective display. Caution: this does not change IT->current_x and
3205 IT->hpos. */
3206
3207static void
3208back_to_previous_visible_line_start (it)
3209 struct it *it;
3210{
3211 int visible_p = 0;
3212
3213 /* Go back one newline if not on BEGV already. */
3214 if (IT_CHARPOS (*it) > BEGV)
3215 back_to_previous_line_start (it);
3216
3217 /* Move over lines that are invisible because of selective display
3218 or text properties. */
3219 while (IT_CHARPOS (*it) > BEGV
3220 && !visible_p)
3221 {
3222 visible_p = 1;
3223
3224 /* If selective > 0, then lines indented more than that values
3225 are invisible. */
3226 if (it->selective > 0
3227 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3228 it->selective))
3229 visible_p = 0;
5f5c8ee5
GM
3230 else
3231 {
3232 Lisp_Object prop;
3233
6fc556fd
KR
3234 prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
3235 Qinvisible, it->window);
5f5c8ee5
GM
3236 if (TEXT_PROP_MEANS_INVISIBLE (prop))
3237 visible_p = 0;
3238 }
5f5c8ee5
GM
3239
3240 /* Back one more newline if the current one is invisible. */
3241 if (!visible_p)
3242 back_to_previous_line_start (it);
3243 }
3244
3245 xassert (IT_CHARPOS (*it) >= BEGV);
3246 xassert (IT_CHARPOS (*it) == BEGV
3247 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3248 CHECK_IT (it);
3249}
3250
3251
3252/* Reseat iterator IT at the previous visible line start. Skip
3253 invisible text that is so either due to text properties or due to
3254 selective display. At the end, update IT's overlay information,
3255 face information etc. */
3256
3257static void
3258reseat_at_previous_visible_line_start (it)
3259 struct it *it;
3260{
3261 back_to_previous_visible_line_start (it);
3262 reseat (it, it->current.pos, 1);
3263 CHECK_IT (it);
3264}
3265
3266
3267/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
3268 buffer. ON_NEWLINE_P non-zero means position IT on the newline
3269 preceding the line start. Skip over invisible text that is so
3270 because of selective display. Compute faces, overlays etc at the
3271 new position. Note that this function does not skip over text that
3272 is invisible because of text properties. */
5f5c8ee5
GM
3273
3274static void
312246d1 3275reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 3276 struct it *it;
312246d1 3277 int on_newline_p;
5f5c8ee5
GM
3278{
3279 /* Restore the buffer position when currently not delivering display
3280 elements from the current buffer. This is the case, for example,
3281 when called at the end of a truncated overlay string. */
3282 while (it->sp)
3283 pop_it (it);
3284 it->method = next_element_from_buffer;
3285
3286 /* Otherwise, scan_buffer would not work. */
3287 if (IT_CHARPOS (*it) < ZV)
3288 {
3289 /* If on a newline, advance past it. Otherwise, find the next
3290 newline which automatically gives us the position following
3291 the newline. */
3292 if (FETCH_BYTE (IT_BYTEPOS (*it)) == '\n')
3293 {
3294 ++IT_CHARPOS (*it);
3295 ++IT_BYTEPOS (*it);
3296 }
3297 else
3298 forward_to_next_line_start (it);
3299
3300 /* We must either have reached the end of the buffer or end up
3301 after a newline. */
3302 xassert (IT_CHARPOS (*it) == ZV
3303 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3304
3305 /* Skip over lines that are invisible because they are indented
3306 more than the value of IT->selective. */
3307 if (it->selective > 0)
3308 while (IT_CHARPOS (*it) < ZV
3309 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3310 it->selective))
3311 forward_to_next_line_start (it);
312246d1
GM
3312
3313 /* Position on the newline if we should. */
13f19968
GM
3314 if (on_newline_p
3315 && IT_CHARPOS (*it) > BEGV
3316 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n')
312246d1
GM
3317 {
3318 --IT_CHARPOS (*it);
3319 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3320 }
5f5c8ee5
GM
3321
3322 /* Set the iterator there. The 0 as the last parameter of
3323 reseat means don't force a text property lookup. The lookup
3324 is then only done if we've skipped past the iterator's
3325 check_charpos'es. This optimization is important because
3326 text property lookups tend to be expensive. */
3327 reseat (it, it->current.pos, 0);
3328 }
3329
3330 CHECK_IT (it);
3331}
3332
3333
3334\f
3335/***********************************************************************
3336 Changing an iterator's position
3337***********************************************************************/
3338
3339/* Change IT's current position to POS in current_buffer. If FORCE_P
3340 is non-zero, always check for text properties at the new position.
3341 Otherwise, text properties are only looked up if POS >=
3342 IT->check_charpos of a property. */
3343
3344static void
3345reseat (it, pos, force_p)
3346 struct it *it;
3347 struct text_pos pos;
3348 int force_p;
3349{
3350 int original_pos = IT_CHARPOS (*it);
3351
3352 reseat_1 (it, pos, 0);
3353
3354 /* Determine where to check text properties. Avoid doing it
3355 where possible because text property lookup is very expensive. */
3356 if (force_p
3357 || CHARPOS (pos) > it->stop_charpos
3358 || CHARPOS (pos) < original_pos)
3359 handle_stop (it);
3360
3361 CHECK_IT (it);
3362}
3363
3364
3365/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
3366 IT->stop_pos to POS, also. */
3367
3368static void
3369reseat_1 (it, pos, set_stop_p)
3370 struct it *it;
3371 struct text_pos pos;
3372 int set_stop_p;
3373{
3374 /* Don't call this function when scanning a C string. */
3375 xassert (it->s == NULL);
3376
3377 /* POS must be a reasonable value. */
3378 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
3379
3380 it->current.pos = it->position = pos;
3381 XSETBUFFER (it->object, current_buffer);
3382 it->dpvec = NULL;
3383 it->current.dpvec_index = -1;
3384 it->current.overlay_string_index = -1;
3385 IT_STRING_CHARPOS (*it) = -1;
3386 IT_STRING_BYTEPOS (*it) = -1;
3387 it->string = Qnil;
3388 it->method = next_element_from_buffer;
3389 it->sp = 0;
3390
3391 if (set_stop_p)
3392 it->stop_charpos = CHARPOS (pos);
3393}
3394
3395
3396/* Set up IT for displaying a string, starting at CHARPOS in window W.
3397 If S is non-null, it is a C string to iterate over. Otherwise,
3398 STRING gives a Lisp string to iterate over.
3399
3400 If PRECISION > 0, don't return more then PRECISION number of
3401 characters from the string.
3402
3403 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
3404 characters have been returned. FIELD_WIDTH < 0 means an infinite
3405 field width.
3406
3407 MULTIBYTE = 0 means disable processing of multibyte characters,
3408 MULTIBYTE > 0 means enable it,
3409 MULTIBYTE < 0 means use IT->multibyte_p.
3410
3411 IT must be initialized via a prior call to init_iterator before
3412 calling this function. */
3413
3414static void
3415reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
3416 struct it *it;
3417 unsigned char *s;
3418 Lisp_Object string;
3419 int charpos;
3420 int precision, field_width, multibyte;
3421{
3422 /* No region in strings. */
3423 it->region_beg_charpos = it->region_end_charpos = -1;
3424
3425 /* No text property checks performed by default, but see below. */
3426 it->stop_charpos = -1;
3427
3428 /* Set iterator position and end position. */
3429 bzero (&it->current, sizeof it->current);
3430 it->current.overlay_string_index = -1;
3431 it->current.dpvec_index = -1;
5f5c8ee5
GM
3432 xassert (charpos >= 0);
3433
3434 /* Use the setting of MULTIBYTE if specified. */
3435 if (multibyte >= 0)
3436 it->multibyte_p = multibyte > 0;
3437
3438 if (s == NULL)
3439 {
3440 xassert (STRINGP (string));
3441 it->string = string;
3442 it->s = NULL;
3443 it->end_charpos = it->string_nchars = XSTRING (string)->size;
3444 it->method = next_element_from_string;
3445 it->current.string_pos = string_pos (charpos, string);
3446 }
3447 else
3448 {
3449 it->s = s;
3450 it->string = Qnil;
3451
3452 /* Note that we use IT->current.pos, not it->current.string_pos,
3453 for displaying C strings. */
3454 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3455 if (it->multibyte_p)
3456 {
3457 it->current.pos = c_string_pos (charpos, s, 1);
3458 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
3459 }
3460 else
3461 {
3462 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
3463 it->end_charpos = it->string_nchars = strlen (s);
3464 }
3465
3466 it->method = next_element_from_c_string;
3467 }
3468
3469 /* PRECISION > 0 means don't return more than PRECISION characters
3470 from the string. */
3471 if (precision > 0 && it->end_charpos - charpos > precision)
3472 it->end_charpos = it->string_nchars = charpos + precision;
3473
3474 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
3475 characters have been returned. FIELD_WIDTH == 0 means don't pad,
3476 FIELD_WIDTH < 0 means infinite field width. This is useful for
3477 padding with `-' at the end of a mode line. */
3478 if (field_width < 0)
3479 field_width = INFINITY;
3480 if (field_width > it->end_charpos - charpos)
3481 it->end_charpos = charpos + field_width;
3482
3483 /* Use the standard display table for displaying strings. */
3484 if (DISP_TABLE_P (Vstandard_display_table))
3485 it->dp = XCHAR_TABLE (Vstandard_display_table);
3486
3487 it->stop_charpos = charpos;
3488 CHECK_IT (it);
3489}
3490
3491
3492\f
3493/***********************************************************************
3494 Iteration
3495 ***********************************************************************/
3496
3497/* Load IT's display element fields with information about the next
3498 display element from the current position of IT. Value is zero if
3499 end of buffer (or C string) is reached. */
3500
3501int
3502get_next_display_element (it)
3503 struct it *it;
3504{
3505 /* Non-zero means that we found an display element. Zero means that
3506 we hit the end of what we iterate over. Performance note: the
3507 function pointer `method' used here turns out to be faster than
3508 using a sequence of if-statements. */
3509 int success_p = (*it->method) (it);
5f5c8ee5
GM
3510
3511 if (it->what == IT_CHARACTER)
3512 {
3513 /* Map via display table or translate control characters.
3514 IT->c, IT->len etc. have been set to the next character by
3515 the function call above. If we have a display table, and it
3516 contains an entry for IT->c, translate it. Don't do this if
3517 IT->c itself comes from a display table, otherwise we could
3518 end up in an infinite recursion. (An alternative could be to
3519 count the recursion depth of this function and signal an
3520 error when a certain maximum depth is reached.) Is it worth
3521 it? */
3522 if (success_p && it->dpvec == NULL)
3523 {
3524 Lisp_Object dv;
3525
3526 if (it->dp
3527 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
3528 VECTORP (dv)))
3529 {
3530 struct Lisp_Vector *v = XVECTOR (dv);
3531
3532 /* Return the first character from the display table
3533 entry, if not empty. If empty, don't display the
3534 current character. */
3535 if (v->size)
3536 {
3537 it->dpvec_char_len = it->len;
3538 it->dpvec = v->contents;
3539 it->dpend = v->contents + v->size;
3540 it->current.dpvec_index = 0;
3541 it->method = next_element_from_display_vector;
3542 }
3543
3544 success_p = get_next_display_element (it);
3545 }
3546
3547 /* Translate control characters into `\003' or `^C' form.
3548 Control characters coming from a display table entry are
3549 currently not translated because we use IT->dpvec to hold
3550 the translation. This could easily be changed but I
197516c2
KH
3551 don't believe that it is worth doing.
3552
3553 Non-printable multibyte characters are also translated
3554 octal form. */
5f5c8ee5
GM
3555 else if ((it->c < ' '
3556 && (it->area != TEXT_AREA
c6e89d6c 3557 || (it->c != '\n' && it->c != '\t')))
54c85a23 3558 || (it->c >= 127
197516c2
KH
3559 && it->len == 1)
3560 || !CHAR_PRINTABLE_P (it->c))
5f5c8ee5
GM
3561 {
3562 /* IT->c is a control character which must be displayed
3563 either as '\003' or as `^C' where the '\\' and '^'
3564 can be defined in the display table. Fill
3565 IT->ctl_chars with glyphs for what we have to
3566 display. Then, set IT->dpvec to these glyphs. */
3567 GLYPH g;
3568
54c85a23 3569 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
3570 {
3571 /* Set IT->ctl_chars[0] to the glyph for `^'. */
3572 if (it->dp
3573 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
3574 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
3575 g = XINT (DISP_CTRL_GLYPH (it->dp));
3576 else
3577 g = FAST_MAKE_GLYPH ('^', 0);
3578 XSETINT (it->ctl_chars[0], g);
3579
3580 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
3581 XSETINT (it->ctl_chars[1], g);
3582
3583 /* Set up IT->dpvec and return first character from it. */
3584 it->dpvec_char_len = it->len;
3585 it->dpvec = it->ctl_chars;
3586 it->dpend = it->dpvec + 2;
3587 it->current.dpvec_index = 0;
3588 it->method = next_element_from_display_vector;
3589 get_next_display_element (it);
3590 }
3591 else
3592 {
260a86a0 3593 unsigned char str[MAX_MULTIBYTE_LENGTH];
c5924f47 3594 int len;
197516c2
KH
3595 int i;
3596 GLYPH escape_glyph;
3597
5f5c8ee5
GM
3598 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
3599 if (it->dp
3600 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
3601 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 3602 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 3603 else
197516c2
KH
3604 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
3605
c5924f47
KH
3606 if (SINGLE_BYTE_CHAR_P (it->c))
3607 str[0] = it->c, len = 1;
3608 else
3609 len = CHAR_STRING (it->c, str);
3610
197516c2
KH
3611 for (i = 0; i < len; i++)
3612 {
3613 XSETINT (it->ctl_chars[i * 4], escape_glyph);
3614 /* Insert three more glyphs into IT->ctl_chars for
3615 the octal display of the character. */
3616 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
3617 XSETINT (it->ctl_chars[i * 4 + 1], g);
3618 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
3619 XSETINT (it->ctl_chars[i * 4 + 2], g);
3620 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
3621 XSETINT (it->ctl_chars[i * 4 + 3], g);
3622 }
5f5c8ee5
GM
3623
3624 /* Set up IT->dpvec and return the first character
3625 from it. */
3626 it->dpvec_char_len = it->len;
3627 it->dpvec = it->ctl_chars;
197516c2 3628 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
3629 it->current.dpvec_index = 0;
3630 it->method = next_element_from_display_vector;
3631 get_next_display_element (it);
3632 }
3633 }
3634 }
3635
980806b6
KH
3636 /* Adjust face id for a multibyte character. There are no
3637 multibyte character in unibyte text. */
5f5c8ee5
GM
3638 if (it->multibyte_p
3639 && success_p
980806b6 3640 && FRAME_WINDOW_P (it->f))
5f5c8ee5 3641 {
980806b6
KH
3642 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3643 it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
5f5c8ee5
GM
3644 }
3645 }
3646
3647 /* Is this character the last one of a run of characters with
3648 box? If yes, set IT->end_of_box_run_p to 1. */
3649 if (it->face_box_p
3650 && it->s == NULL)
3651 {
3652 int face_id;
3653 struct face *face;
3654
3655 it->end_of_box_run_p
3656 = ((face_id = face_after_it_pos (it),
3657 face_id != it->face_id)
3658 && (face = FACE_FROM_ID (it->f, face_id),
3659 face->box == FACE_NO_BOX));
3660 }
3661
3662 /* Value is 0 if end of buffer or string reached. */
3663 return success_p;
3664}
3665
3666
3667/* Move IT to the next display element.
3668
3669 Functions get_next_display_element and set_iterator_to_next are
3670 separate because I find this arrangement easier to handle than a
3671 get_next_display_element function that also increments IT's
3672 position. The way it is we can first look at an iterator's current
3673 display element, decide whether it fits on a line, and if it does,
3674 increment the iterator position. The other way around we probably
3675 would either need a flag indicating whether the iterator has to be
3676 incremented the next time, or we would have to implement a
3677 decrement position function which would not be easy to write. */
3678
3679void
3680set_iterator_to_next (it)
3681 struct it *it;
3682{
3683 if (it->method == next_element_from_buffer)
3684 {
3685 /* The current display element of IT is a character from
3686 current_buffer. Advance in the buffer, and maybe skip over
3687 invisible lines that are so because of selective display. */
3688 if (ITERATOR_AT_END_OF_LINE_P (it))
312246d1 3689 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
3690 else
3691 {
3692 xassert (it->len != 0);
3693 IT_BYTEPOS (*it) += it->len;
3694 IT_CHARPOS (*it) += 1;
3695 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
3696 }
3697 }
260a86a0
KH
3698 else if (it->method == next_element_from_composition)
3699 {
3700 xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
3701 if (STRINGP (it->string))
3702 {
3703 IT_STRING_BYTEPOS (*it) += it->len;
3704 IT_STRING_CHARPOS (*it) += it->cmp_len;
3705 it->method = next_element_from_string;
3706 goto consider_string_end;
3707 }
3708 else
3709 {
3710 IT_BYTEPOS (*it) += it->len;
3711 IT_CHARPOS (*it) += it->cmp_len;
3712 it->method = next_element_from_buffer;
3713 }
3714 }
5f5c8ee5
GM
3715 else if (it->method == next_element_from_c_string)
3716 {
3717 /* Current display element of IT is from a C string. */
3718 IT_BYTEPOS (*it) += it->len;
3719 IT_CHARPOS (*it) += 1;
3720 }
3721 else if (it->method == next_element_from_display_vector)
3722 {
3723 /* Current display element of IT is from a display table entry.
3724 Advance in the display table definition. Reset it to null if
3725 end reached, and continue with characters from buffers/
3726 strings. */
3727 ++it->current.dpvec_index;
286bcbc9 3728
980806b6
KH
3729 /* Restore face of the iterator to what they were before the
3730 display vector entry (these entries may contain faces). */
5f5c8ee5 3731 it->face_id = it->saved_face_id;
286bcbc9 3732
5f5c8ee5
GM
3733 if (it->dpvec + it->current.dpvec_index == it->dpend)
3734 {
3735 if (it->s)
3736 it->method = next_element_from_c_string;
3737 else if (STRINGP (it->string))
3738 it->method = next_element_from_string;
3739 else
3740 it->method = next_element_from_buffer;
3741
3742 it->dpvec = NULL;
3743 it->current.dpvec_index = -1;
3744
312246d1
GM
3745 /* Skip over characters which were displayed via IT->dpvec. */
3746 if (it->dpvec_char_len < 0)
3747 reseat_at_next_visible_line_start (it, 1);
3748 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
3749 {
3750 it->len = it->dpvec_char_len;
3751 set_iterator_to_next (it);
3752 }
3753 }
3754 }
3755 else if (it->method == next_element_from_string)
3756 {
3757 /* Current display element is a character from a Lisp string. */
3758 xassert (it->s == NULL && STRINGP (it->string));
3759 IT_STRING_BYTEPOS (*it) += it->len;
3760 IT_STRING_CHARPOS (*it) += 1;
3761
3762 consider_string_end:
3763
3764 if (it->current.overlay_string_index >= 0)
3765 {
3766 /* IT->string is an overlay string. Advance to the
3767 next, if there is one. */
3768 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3769 next_overlay_string (it);
3770 }
3771 else
3772 {
3773 /* IT->string is not an overlay string. If we reached
3774 its end, and there is something on IT->stack, proceed
3775 with what is on the stack. This can be either another
3776 string, this time an overlay string, or a buffer. */
3777 if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size
3778 && it->sp > 0)
3779 {
3780 pop_it (it);
3781 if (!STRINGP (it->string))
3782 it->method = next_element_from_buffer;
3783 }
3784 }
3785 }
3786 else if (it->method == next_element_from_image
3787 || it->method == next_element_from_stretch)
3788 {
3789 /* The position etc with which we have to proceed are on
3790 the stack. The position may be at the end of a string,
3791 if the `display' property takes up the whole string. */
3792 pop_it (it);
3793 it->image_id = 0;
3794 if (STRINGP (it->string))
3795 {
3796 it->method = next_element_from_string;
3797 goto consider_string_end;
3798 }
3799 else
3800 it->method = next_element_from_buffer;
3801 }
3802 else
3803 /* There are no other methods defined, so this should be a bug. */
3804 abort ();
3805
3806 /* Reset flags indicating start and end of a sequence of
3807 characters with box. */
3808 it->start_of_box_run_p = it->end_of_box_run_p = 0;
3809
3810 xassert (it->method != next_element_from_string
3811 || (STRINGP (it->string)
3812 && IT_STRING_CHARPOS (*it) >= 0));
3813}
3814
3815
3816/* Load IT's display element fields with information about the next
3817 display element which comes from a display table entry or from the
3818 result of translating a control character to one of the forms `^C'
3819 or `\003'. IT->dpvec holds the glyphs to return as characters. */
3820
3821static int
3822next_element_from_display_vector (it)
3823 struct it *it;
3824{
3825 /* Precondition. */
3826 xassert (it->dpvec && it->current.dpvec_index >= 0);
3827
3828 /* Remember the current face id in case glyphs specify faces.
3829 IT's face is restored in set_iterator_to_next. */
3830 it->saved_face_id = it->face_id;
3831
3832 if (INTEGERP (*it->dpvec)
3833 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
3834 {
3835 int lface_id;
3836 GLYPH g;
3837
3838 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
3839 it->c = FAST_GLYPH_CHAR (g);
c5924f47 3840 it->len = CHAR_BYTES (it->c);
5f5c8ee5
GM
3841
3842 /* The entry may contain a face id to use. Such a face id is
3843 the id of a Lisp face, not a realized face. A face id of
969065c3 3844 zero means no face is specified. */
5f5c8ee5
GM
3845 lface_id = FAST_GLYPH_FACE (g);
3846 if (lface_id)
3847 {
969065c3 3848 /* The function returns -1 if lface_id is invalid. */
5f5c8ee5
GM
3849 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
3850 if (face_id >= 0)
969065c3 3851 it->face_id = face_id;
5f5c8ee5
GM
3852 }
3853 }
3854 else
3855 /* Display table entry is invalid. Return a space. */
3856 it->c = ' ', it->len = 1;
3857
3858 /* Don't change position and object of the iterator here. They are
3859 still the values of the character that had this display table
3860 entry or was translated, and that's what we want. */
3861 it->what = IT_CHARACTER;
3862 return 1;
3863}
3864
3865
3866/* Load IT with the next display element from Lisp string IT->string.
3867 IT->current.string_pos is the current position within the string.
3868 If IT->current.overlay_string_index >= 0, the Lisp string is an
3869 overlay string. */
3870
3871static int
3872next_element_from_string (it)
3873 struct it *it;
3874{
3875 struct text_pos position;
3876
3877 xassert (STRINGP (it->string));
3878 xassert (IT_STRING_CHARPOS (*it) >= 0);
3879 position = it->current.string_pos;
3880
3881 /* Time to check for invisible text? */
3882 if (IT_STRING_CHARPOS (*it) < it->end_charpos
3883 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
3884 {
3885 handle_stop (it);
3886
3887 /* Since a handler may have changed IT->method, we must
3888 recurse here. */
3889 return get_next_display_element (it);
3890 }
3891
3892 if (it->current.overlay_string_index >= 0)
3893 {
3894 /* Get the next character from an overlay string. In overlay
3895 strings, There is no field width or padding with spaces to
3896 do. */
3897 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3898 {
3899 it->what = IT_EOB;
3900 return 0;
3901 }
3902 else if (STRING_MULTIBYTE (it->string))
3903 {
3904 int remaining = (STRING_BYTES (XSTRING (it->string))
3905 - IT_STRING_BYTEPOS (*it));
3906 unsigned char *s = (XSTRING (it->string)->data
3907 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3908 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
3909 }
3910 else
3911 {
3912 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3913 it->len = 1;
3914 }
3915 }
3916 else
3917 {
3918 /* Get the next character from a Lisp string that is not an
3919 overlay string. Such strings come from the mode line, for
3920 example. We may have to pad with spaces, or truncate the
3921 string. See also next_element_from_c_string. */
3922 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
3923 {
3924 it->what = IT_EOB;
3925 return 0;
3926 }
3927 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
3928 {
3929 /* Pad with spaces. */
3930 it->c = ' ', it->len = 1;
3931 CHARPOS (position) = BYTEPOS (position) = -1;
3932 }
3933 else if (STRING_MULTIBYTE (it->string))
3934 {
3935 int maxlen = (STRING_BYTES (XSTRING (it->string))
3936 - IT_STRING_BYTEPOS (*it));
3937 unsigned char *s = (XSTRING (it->string)->data
3938 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3939 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
3940 }
3941 else
3942 {
3943 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3944 it->len = 1;
3945 }
3946 }
3947
3948 /* Record what we have and where it came from. Note that we store a
3949 buffer position in IT->position although it could arguably be a
3950 string position. */
3951 it->what = IT_CHARACTER;
3952 it->object = it->string;
3953 it->position = position;
3954 return 1;
3955}
3956
3957
3958/* Load IT with next display element from C string IT->s.
3959 IT->string_nchars is the maximum number of characters to return
3960 from the string. IT->end_charpos may be greater than
3961 IT->string_nchars when this function is called, in which case we
3962 may have to return padding spaces. Value is zero if end of string
3963 reached, including padding spaces. */
3964
3965static int
3966next_element_from_c_string (it)
3967 struct it *it;
3968{
3969 int success_p = 1;
3970
3971 xassert (it->s);
3972 it->what = IT_CHARACTER;
3973 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
3974 it->object = Qnil;
3975
3976 /* IT's position can be greater IT->string_nchars in case a field
3977 width or precision has been specified when the iterator was
3978 initialized. */
3979 if (IT_CHARPOS (*it) >= it->end_charpos)
3980 {
3981 /* End of the game. */
3982 it->what = IT_EOB;
3983 success_p = 0;
3984 }
3985 else if (IT_CHARPOS (*it) >= it->string_nchars)
3986 {
3987 /* Pad with spaces. */
3988 it->c = ' ', it->len = 1;
3989 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
3990 }
3991 else if (it->multibyte_p)
3992 {
3993 /* Implementation note: The calls to strlen apparently aren't a
3994 performance problem because there is no noticeable performance
3995 difference between Emacs running in unibyte or multibyte mode. */
3996 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
3997 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
3998 maxlen, &it->len);
5f5c8ee5
GM
3999 }
4000 else
4001 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
4002
4003 return success_p;
4004}
4005
4006
4007/* Set up IT to return characters from an ellipsis, if appropriate.
4008 The definition of the ellipsis glyphs may come from a display table
4009 entry. This function Fills IT with the first glyph from the
4010 ellipsis if an ellipsis is to be displayed. */
4011
13f19968 4012static int
5f5c8ee5
GM
4013next_element_from_ellipsis (it)
4014 struct it *it;
4015{
13f19968 4016 if (it->selective_display_ellipsis_p)
5f5c8ee5 4017 {
13f19968
GM
4018 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
4019 {
4020 /* Use the display table definition for `...'. Invalid glyphs
4021 will be handled by the method returning elements from dpvec. */
4022 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
4023 it->dpvec_char_len = it->len;
4024 it->dpvec = v->contents;
4025 it->dpend = v->contents + v->size;
4026 it->current.dpvec_index = 0;
4027 it->method = next_element_from_display_vector;
4028 }
4029 else
4030 {
4031 /* Use default `...' which is stored in default_invis_vector. */
4032 it->dpvec_char_len = it->len;
4033 it->dpvec = default_invis_vector;
4034 it->dpend = default_invis_vector + 3;
4035 it->current.dpvec_index = 0;
4036 it->method = next_element_from_display_vector;
4037 }
5f5c8ee5 4038 }
13f19968
GM
4039 else
4040 reseat_at_next_visible_line_start (it, 1);
4041
4042 return get_next_display_element (it);
5f5c8ee5
GM
4043}
4044
4045
4046/* Deliver an image display element. The iterator IT is already
4047 filled with image information (done in handle_display_prop). Value
4048 is always 1. */
4049
4050
4051static int
4052next_element_from_image (it)
4053 struct it *it;
4054{
4055 it->what = IT_IMAGE;
4056 return 1;
4057}
4058
4059
4060/* Fill iterator IT with next display element from a stretch glyph
4061 property. IT->object is the value of the text property. Value is
4062 always 1. */
4063
4064static int
4065next_element_from_stretch (it)
4066 struct it *it;
4067{
4068 it->what = IT_STRETCH;
4069 return 1;
4070}
4071
4072
4073/* Load IT with the next display element from current_buffer. Value
4074 is zero if end of buffer reached. IT->stop_charpos is the next
4075 position at which to stop and check for text properties or buffer
4076 end. */
4077
4078static int
4079next_element_from_buffer (it)
4080 struct it *it;
4081{
4082 int success_p = 1;
4083
4084 /* Check this assumption, otherwise, we would never enter the
4085 if-statement, below. */
4086 xassert (IT_CHARPOS (*it) >= BEGV
4087 && IT_CHARPOS (*it) <= it->stop_charpos);
4088
4089 if (IT_CHARPOS (*it) >= it->stop_charpos)
4090 {
4091 if (IT_CHARPOS (*it) >= it->end_charpos)
4092 {
4093 int overlay_strings_follow_p;
4094
4095 /* End of the game, except when overlay strings follow that
4096 haven't been returned yet. */
4097 if (it->overlay_strings_at_end_processed_p)
4098 overlay_strings_follow_p = 0;
4099 else
4100 {
4101 it->overlay_strings_at_end_processed_p = 1;
c880678e 4102 overlay_strings_follow_p = get_overlay_strings (it);
5f5c8ee5
GM
4103 }
4104
4105 if (overlay_strings_follow_p)
4106 success_p = get_next_display_element (it);
4107 else
4108 {
4109 it->what = IT_EOB;
4110 it->position = it->current.pos;
4111 success_p = 0;
4112 }
4113 }
4114 else
4115 {
4116 handle_stop (it);
4117 return get_next_display_element (it);
4118 }
4119 }
4120 else
4121 {
4122 /* No face changes, overlays etc. in sight, so just return a
4123 character from current_buffer. */
4124 unsigned char *p;
4125
4126 /* Maybe run the redisplay end trigger hook. Performance note:
4127 This doesn't seem to cost measurable time. */
4128 if (it->redisplay_end_trigger_charpos
4129 && it->glyph_row
4130 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
4131 run_redisplay_end_trigger_hook (it);
4132
4133 /* Get the next character, maybe multibyte. */
4134 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
260a86a0 4135 if (it->multibyte_p && !ASCII_BYTE_P (*p))
5f5c8ee5
GM
4136 {
4137 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
4138 - IT_BYTEPOS (*it));
4fdb80f2 4139 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
4140 }
4141 else
4142 it->c = *p, it->len = 1;
4143
4144 /* Record what we have and where it came from. */
4145 it->what = IT_CHARACTER;;
4146 it->object = it->w->buffer;
4147 it->position = it->current.pos;
4148
4149 /* Normally we return the character found above, except when we
4150 really want to return an ellipsis for selective display. */
4151 if (it->selective)
4152 {
4153 if (it->c == '\n')
4154 {
4155 /* A value of selective > 0 means hide lines indented more
4156 than that number of columns. */
4157 if (it->selective > 0
4158 && IT_CHARPOS (*it) + 1 < ZV
4159 && indented_beyond_p (IT_CHARPOS (*it) + 1,
4160 IT_BYTEPOS (*it) + 1,
4161 it->selective))
312246d1 4162 {
13f19968 4163 success_p = next_element_from_ellipsis (it);
312246d1
GM
4164 it->dpvec_char_len = -1;
4165 }
5f5c8ee5
GM
4166 }
4167 else if (it->c == '\r' && it->selective == -1)
4168 {
4169 /* A value of selective == -1 means that everything from the
4170 CR to the end of the line is invisible, with maybe an
4171 ellipsis displayed for it. */
13f19968 4172 success_p = next_element_from_ellipsis (it);
312246d1 4173 it->dpvec_char_len = -1;
5f5c8ee5
GM
4174 }
4175 }
4176 }
4177
4178 /* Value is zero if end of buffer reached. */
c880678e 4179 xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
5f5c8ee5
GM
4180 return success_p;
4181}
4182
4183
4184/* Run the redisplay end trigger hook for IT. */
4185
4186static void
4187run_redisplay_end_trigger_hook (it)
4188 struct it *it;
4189{
4190 Lisp_Object args[3];
4191
4192 /* IT->glyph_row should be non-null, i.e. we should be actually
4193 displaying something, or otherwise we should not run the hook. */
4194 xassert (it->glyph_row);
4195
4196 /* Set up hook arguments. */
4197 args[0] = Qredisplay_end_trigger_functions;
4198 args[1] = it->window;
4199 XSETINT (args[2], it->redisplay_end_trigger_charpos);
4200 it->redisplay_end_trigger_charpos = 0;
4201
4202 /* Since we are *trying* to run these functions, don't try to run
4203 them again, even if they get an error. */
4204 it->w->redisplay_end_trigger = Qnil;
4205 Frun_hook_with_args (3, args);
4206
4207 /* Notice if it changed the face of the character we are on. */
4208 handle_face_prop (it);
4209}
4210
4211
260a86a0
KH
4212/* Deliver a composition display element. The iterator IT is already
4213 filled with composition information (done in
4214 handle_composition_prop). Value is always 1. */
4215
4216static int
4217next_element_from_composition (it)
4218 struct it *it;
4219{
4220 it->what = IT_COMPOSITION;
4221 it->position = (STRINGP (it->string)
4222 ? it->current.string_pos
4223 : it->current.pos);
4224 return 1;
4225}
4226
4227
5f5c8ee5
GM
4228\f
4229/***********************************************************************
4230 Moving an iterator without producing glyphs
4231 ***********************************************************************/
4232
4233/* Move iterator IT to a specified buffer or X position within one
4234 line on the display without producing glyphs.
4235
4236 Begin to skip at IT's current position. Skip to TO_CHARPOS or TO_X
4237 whichever is reached first.
4238
4239 TO_CHARPOS <= 0 means no TO_CHARPOS is specified.
4240
4241 TO_X < 0 means that no TO_X is specified. TO_X is normally a value
4242 0 <= TO_X <= IT->last_visible_x. This means in particular, that
4243 TO_X includes the amount by which a window is horizontally
4244 scrolled.
4245
4246 Value is
4247
4248 MOVE_POS_MATCH_OR_ZV
4249 - when TO_POS or ZV was reached.
4250
4251 MOVE_X_REACHED
4252 -when TO_X was reached before TO_POS or ZV were reached.
4253
4254 MOVE_LINE_CONTINUED
4255 - when we reached the end of the display area and the line must
4256 be continued.
4257
4258 MOVE_LINE_TRUNCATED
4259 - when we reached the end of the display area and the line is
4260 truncated.
4261
4262 MOVE_NEWLINE_OR_CR
4263 - when we stopped at a line end, i.e. a newline or a CR and selective
4264 display is on. */
4265
701552dd 4266static enum move_it_result
5f5c8ee5
GM
4267move_it_in_display_line_to (it, to_charpos, to_x, op)
4268 struct it *it;
4269 int to_charpos, to_x, op;
4270{
4271 enum move_it_result result = MOVE_UNDEFINED;
4272 struct glyph_row *saved_glyph_row;
4273
4274 /* Don't produce glyphs in produce_glyphs. */
4275 saved_glyph_row = it->glyph_row;
4276 it->glyph_row = NULL;
4277
5f5c8ee5
GM
4278 while (1)
4279 {
47589c8c 4280 int x, i, ascent, descent;
5f5c8ee5
GM
4281
4282 /* Stop when ZV or TO_CHARPOS reached. */
4283 if (!get_next_display_element (it)
4284 || ((op & MOVE_TO_POS) != 0
4285 && BUFFERP (it->object)
4286 && IT_CHARPOS (*it) >= to_charpos))
4287 {
4288 result = MOVE_POS_MATCH_OR_ZV;
4289 break;
4290 }
4291
4292 /* The call to produce_glyphs will get the metrics of the
4293 display element IT is loaded with. We record in x the
4294 x-position before this display element in case it does not
4295 fit on the line. */
4296 x = it->current_x;
47589c8c
GM
4297
4298 /* Remember the line height so far in case the next element doesn't
4299 fit on the line. */
4300 if (!it->truncate_lines_p)
4301 {
4302 ascent = it->max_ascent;
4303 descent = it->max_descent;
4304 }
4305
5f5c8ee5
GM
4306 PRODUCE_GLYPHS (it);
4307
4308 if (it->area != TEXT_AREA)
4309 {
4310 set_iterator_to_next (it);
4311 continue;
4312 }
4313
4314 /* The number of glyphs we get back in IT->nglyphs will normally
4315 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
4316 character on a terminal frame, or (iii) a line end. For the
4317 second case, IT->nglyphs - 1 padding glyphs will be present
4318 (on X frames, there is only one glyph produced for a
4319 composite character.
4320
4321 The behavior implemented below means, for continuation lines,
4322 that as many spaces of a TAB as fit on the current line are
4323 displayed there. For terminal frames, as many glyphs of a
4324 multi-glyph character are displayed in the current line, too.
4325 This is what the old redisplay code did, and we keep it that
4326 way. Under X, the whole shape of a complex character must
4327 fit on the line or it will be completely displayed in the
4328 next line.
4329
4330 Note that both for tabs and padding glyphs, all glyphs have
4331 the same width. */
4332 if (it->nglyphs)
4333 {
4334 /* More than one glyph or glyph doesn't fit on line. All
4335 glyphs have the same width. */
4336 int single_glyph_width = it->pixel_width / it->nglyphs;
4337 int new_x;
4338
4339 for (i = 0; i < it->nglyphs; ++i, x = new_x)
4340 {
4341 new_x = x + single_glyph_width;
4342
4343 /* We want to leave anything reaching TO_X to the caller. */
4344 if ((op & MOVE_TO_X) && new_x > to_x)
4345 {
4346 it->current_x = x;
4347 result = MOVE_X_REACHED;
4348 break;
4349 }
4350 else if (/* Lines are continued. */
4351 !it->truncate_lines_p
4352 && (/* And glyph doesn't fit on the line. */
4353 new_x > it->last_visible_x
4354 /* Or it fits exactly and we're on a window
4355 system frame. */
4356 || (new_x == it->last_visible_x
4357 && FRAME_WINDOW_P (it->f))))
4358 {
4359 if (/* IT->hpos == 0 means the very first glyph
4360 doesn't fit on the line, e.g. a wide image. */
4361 it->hpos == 0
4362 || (new_x == it->last_visible_x
4363 && FRAME_WINDOW_P (it->f)))
4364 {
4365 ++it->hpos;
4366 it->current_x = new_x;
4367 if (i == it->nglyphs - 1)
4368 set_iterator_to_next (it);
4369 }
4370 else
47589c8c
GM
4371 {
4372 it->current_x = x;
4373 it->max_ascent = ascent;
4374 it->max_descent = descent;
4375 }
4376
4377 TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
4378 IT_CHARPOS (*it)));
5f5c8ee5
GM
4379 result = MOVE_LINE_CONTINUED;
4380 break;
4381 }
4382 else if (new_x > it->first_visible_x)
4383 {
4384 /* Glyph is visible. Increment number of glyphs that
4385 would be displayed. */
4386 ++it->hpos;
4387 }
4388 else
4389 {
4390 /* Glyph is completely off the left margin of the display
4391 area. Nothing to do. */
4392 }
4393 }
4394
4395 if (result != MOVE_UNDEFINED)
4396 break;
4397 }
4398 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
4399 {
4400 /* Stop when TO_X specified and reached. This check is
4401 necessary here because of lines consisting of a line end,
4402 only. The line end will not produce any glyphs and we
4403 would never get MOVE_X_REACHED. */
4404 xassert (it->nglyphs == 0);
4405 result = MOVE_X_REACHED;
4406 break;
4407 }
4408
4409 /* Is this a line end? If yes, we're done. */
4410 if (ITERATOR_AT_END_OF_LINE_P (it))
4411 {
4412 result = MOVE_NEWLINE_OR_CR;
4413 break;
4414 }
4415
4416 /* The current display element has been consumed. Advance
4417 to the next. */
4418 set_iterator_to_next (it);
4419
4420 /* Stop if lines are truncated and IT's current x-position is
4421 past the right edge of the window now. */
4422 if (it->truncate_lines_p
4423 && it->current_x >= it->last_visible_x)
4424 {
4425 result = MOVE_LINE_TRUNCATED;
4426 break;
4427 }
4428 }
4429
4430 /* Restore the iterator settings altered at the beginning of this
4431 function. */
4432 it->glyph_row = saved_glyph_row;
4433 return result;
4434}
4435
4436
4437/* Move IT forward to a specified buffer position TO_CHARPOS, TO_X,
4438 TO_Y, TO_VPOS. OP is a bit-mask that specifies where to stop. See
4439 the description of enum move_operation_enum.
4440
4441 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
4442 screen line, this function will set IT to the next position >
4443 TO_CHARPOS. */
4444
4445void
4446move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
4447 struct it *it;
4448 int to_charpos, to_x, to_y, to_vpos;
4449 int op;
4450{
4451 enum move_it_result skip, skip2 = MOVE_X_REACHED;
4452 int line_height;
47589c8c 4453 int reached = 0;
5f5c8ee5 4454
47589c8c 4455 for (;;)
5f5c8ee5
GM
4456 {
4457 if (op & MOVE_TO_VPOS)
4458 {
4459 /* If no TO_CHARPOS and no TO_X specified, stop at the
4460 start of the line TO_VPOS. */
4461 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
4462 {
4463 if (it->vpos == to_vpos)
47589c8c
GM
4464 {
4465 reached = 1;
4466 break;
4467 }
4468 else
4469 skip = move_it_in_display_line_to (it, -1, -1, 0);
5f5c8ee5
GM
4470 }
4471 else
4472 {
4473 /* TO_VPOS >= 0 means stop at TO_X in the line at
4474 TO_VPOS, or at TO_POS, whichever comes first. */
47589c8c
GM
4475 if (it->vpos == to_vpos)
4476 {
4477 reached = 2;
4478 break;
4479 }
4480
5f5c8ee5
GM
4481 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
4482
4483 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
47589c8c
GM
4484 {
4485 reached = 3;
4486 break;
4487 }
5f5c8ee5
GM
4488 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
4489 {
4490 /* We have reached TO_X but not in the line we want. */
4491 skip = move_it_in_display_line_to (it, to_charpos,
4492 -1, MOVE_TO_POS);
4493 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
4494 {
4495 reached = 4;
4496 break;
4497 }
5f5c8ee5
GM
4498 }
4499 }
4500 }
4501 else if (op & MOVE_TO_Y)
4502 {
4503 struct it it_backup;
5f5c8ee5
GM
4504
4505 /* TO_Y specified means stop at TO_X in the line containing
4506 TO_Y---or at TO_CHARPOS if this is reached first. The
4507 problem is that we can't really tell whether the line
4508 contains TO_Y before we have completely scanned it, and
4509 this may skip past TO_X. What we do is to first scan to
4510 TO_X.
4511
4512 If TO_X is not specified, use a TO_X of zero. The reason
4513 is to make the outcome of this function more predictable.
4514 If we didn't use TO_X == 0, we would stop at the end of
4515 the line which is probably not what a caller would expect
4516 to happen. */
4517 skip = move_it_in_display_line_to (it, to_charpos,
4518 ((op & MOVE_TO_X)
4519 ? to_x : 0),
4520 (MOVE_TO_X
4521 | (op & MOVE_TO_POS)));
4522
4523 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
4524 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
4525 {
4526 reached = 5;
4527 break;
4528 }
5f5c8ee5
GM
4529
4530 /* If TO_X was reached, we would like to know whether TO_Y
4531 is in the line. This can only be said if we know the
4532 total line height which requires us to scan the rest of
4533 the line. */
5f5c8ee5
GM
4534 if (skip == MOVE_X_REACHED)
4535 {
4536 it_backup = *it;
47589c8c 4537 TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
4538 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
4539 op & MOVE_TO_POS);
47589c8c 4540 TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
4541 }
4542
4543 /* Now, decide whether TO_Y is in this line. */
4544 line_height = it->max_ascent + it->max_descent;
47589c8c 4545 TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
5f5c8ee5
GM
4546
4547 if (to_y >= it->current_y
4548 && to_y < it->current_y + line_height)
4549 {
4550 if (skip == MOVE_X_REACHED)
4551 /* If TO_Y is in this line and TO_X was reached above,
4552 we scanned too far. We have to restore IT's settings
4553 to the ones before skipping. */
4554 *it = it_backup;
47589c8c 4555 reached = 6;
5f5c8ee5
GM
4556 }
4557 else if (skip == MOVE_X_REACHED)
4558 {
4559 skip = skip2;
4560 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c 4561 reached = 7;
5f5c8ee5
GM
4562 }
4563
47589c8c 4564 if (reached)
5f5c8ee5
GM
4565 break;
4566 }
4567 else
4568 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
4569
4570 switch (skip)
4571 {
4572 case MOVE_POS_MATCH_OR_ZV:
47589c8c
GM
4573 reached = 8;
4574 goto out;
5f5c8ee5
GM
4575
4576 case MOVE_NEWLINE_OR_CR:
4577 set_iterator_to_next (it);
4578 it->continuation_lines_width = 0;
4579 break;
4580
4581 case MOVE_LINE_TRUNCATED:
4582 it->continuation_lines_width = 0;
312246d1 4583 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4584 if ((op & MOVE_TO_POS) != 0
4585 && IT_CHARPOS (*it) > to_charpos)
47589c8c
GM
4586 {
4587 reached = 9;
4588 goto out;
4589 }
5f5c8ee5
GM
4590 break;
4591
4592 case MOVE_LINE_CONTINUED:
4593 it->continuation_lines_width += it->current_x;
4594 break;
4595
4596 default:
4597 abort ();
4598 }
4599
4600 /* Reset/increment for the next run. */
4601 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
4602 it->current_x = it->hpos = 0;
4603 it->current_y += it->max_ascent + it->max_descent;
4604 ++it->vpos;
4605 last_height = it->max_ascent + it->max_descent;
4606 last_max_ascent = it->max_ascent;
4607 it->max_ascent = it->max_descent = 0;
4608 }
47589c8c
GM
4609
4610 out:
4611
4612 TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
5f5c8ee5
GM
4613}
4614
4615
4616/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
4617
4618 If DY > 0, move IT backward at least that many pixels. DY = 0
4619 means move IT backward to the preceding line start or BEGV. This
4620 function may move over more than DY pixels if IT->current_y - DY
4621 ends up in the middle of a line; in this case IT->current_y will be
4622 set to the top of the line moved to. */
4623
4624void
4625move_it_vertically_backward (it, dy)
4626 struct it *it;
4627 int dy;
4628{
4629 int nlines, h, line_height;
4630 struct it it2;
4631 int start_pos = IT_CHARPOS (*it);
4632
4633 xassert (dy >= 0);
4634
4635 /* Estimate how many newlines we must move back. */
4636 nlines = max (1, dy / CANON_Y_UNIT (it->f));
4637
4638 /* Set the iterator's position that many lines back. */
4639 while (nlines-- && IT_CHARPOS (*it) > BEGV)
4640 back_to_previous_visible_line_start (it);
4641
4642 /* Reseat the iterator here. When moving backward, we don't want
4643 reseat to skip forward over invisible text, set up the iterator
4644 to deliver from overlay strings at the new position etc. So,
4645 use reseat_1 here. */
4646 reseat_1 (it, it->current.pos, 1);
4647
4648 /* We are now surely at a line start. */
4649 it->current_x = it->hpos = 0;
4650
4651 /* Move forward and see what y-distance we moved. First move to the
4652 start of the next line so that we get its height. We need this
4653 height to be able to tell whether we reached the specified
4654 y-distance. */
4655 it2 = *it;
4656 it2.max_ascent = it2.max_descent = 0;
4657 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
4658 MOVE_TO_POS | MOVE_TO_VPOS);
4659 xassert (IT_CHARPOS (*it) >= BEGV);
4660 line_height = it2.max_ascent + it2.max_descent;
47589c8c 4661
5f5c8ee5
GM
4662 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
4663 xassert (IT_CHARPOS (*it) >= BEGV);
4664 h = it2.current_y - it->current_y;
4665 nlines = it2.vpos - it->vpos;
4666
4667 /* Correct IT's y and vpos position. */
4668 it->vpos -= nlines;
4669 it->current_y -= h;
4670
4671 if (dy == 0)
4672 {
4673 /* DY == 0 means move to the start of the screen line. The
4674 value of nlines is > 0 if continuation lines were involved. */
4675 if (nlines > 0)
4676 move_it_by_lines (it, nlines, 1);
4677 xassert (IT_CHARPOS (*it) <= start_pos);
4678 }
4679 else if (nlines)
4680 {
4681 /* The y-position we try to reach. Note that h has been
4682 subtracted in front of the if-statement. */
4683 int target_y = it->current_y + h - dy;
4684
4685 /* If we did not reach target_y, try to move further backward if
4686 we can. If we moved too far backward, try to move forward. */
4687 if (target_y < it->current_y
4688 && IT_CHARPOS (*it) > BEGV)
4689 {
4690 move_it_vertically (it, target_y - it->current_y);
4691 xassert (IT_CHARPOS (*it) >= BEGV);
4692 }
4693 else if (target_y >= it->current_y + line_height
4694 && IT_CHARPOS (*it) < ZV)
4695 {
4696 move_it_vertically (it, target_y - (it->current_y + line_height));
4697 xassert (IT_CHARPOS (*it) >= BEGV);
4698 }
4699 }
4700}
4701
4702
4703/* Move IT by a specified amount of pixel lines DY. DY negative means
4704 move backwards. DY = 0 means move to start of screen line. At the
4705 end, IT will be on the start of a screen line. */
4706
4707void
4708move_it_vertically (it, dy)
4709 struct it *it;
4710 int dy;
4711{
4712 if (dy <= 0)
4713 move_it_vertically_backward (it, -dy);
4714 else if (dy > 0)
4715 {
47589c8c 4716 TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
5f5c8ee5
GM
4717 move_it_to (it, ZV, -1, it->current_y + dy, -1,
4718 MOVE_TO_POS | MOVE_TO_Y);
47589c8c 4719 TRACE_MOVE ((stderr, "move_it_v: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
4720
4721 /* If buffer ends in ZV without a newline, move to the start of
4722 the line to satisfy the post-condition. */
4723 if (IT_CHARPOS (*it) == ZV
4724 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
4725 move_it_by_lines (it, 0, 0);
4726 }
4727}
4728
4729
4730/* Return non-zero if some text between buffer positions START_CHARPOS
4731 and END_CHARPOS is invisible. IT->window is the window for text
4732 property lookup. */
4733
4734static int
4735invisible_text_between_p (it, start_charpos, end_charpos)
4736 struct it *it;
4737 int start_charpos, end_charpos;
4738{
5f5c8ee5
GM
4739 Lisp_Object prop, limit;
4740 int invisible_found_p;
4741
4742 xassert (it != NULL && start_charpos <= end_charpos);
4743
4744 /* Is text at START invisible? */
4745 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
4746 it->window);
4747 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4748 invisible_found_p = 1;
4749 else
4750 {
016b5642
MB
4751 limit = Fnext_single_char_property_change (make_number (start_charpos),
4752 Qinvisible, Qnil,
4753 make_number (end_charpos));
5f5c8ee5
GM
4754 invisible_found_p = XFASTINT (limit) < end_charpos;
4755 }
4756
4757 return invisible_found_p;
5f5c8ee5
GM
4758}
4759
4760
4761/* Move IT by a specified number DVPOS of screen lines down. DVPOS
4762 negative means move up. DVPOS == 0 means move to the start of the
4763 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
4764 NEED_Y_P is zero, IT->current_y will be left unchanged.
4765
4766 Further optimization ideas: If we would know that IT->f doesn't use
4767 a face with proportional font, we could be faster for
4768 truncate-lines nil. */
4769
4770void
4771move_it_by_lines (it, dvpos, need_y_p)
4772 struct it *it;
4773 int dvpos, need_y_p;
4774{
4775 struct position pos;
4776
4777 if (!FRAME_WINDOW_P (it->f))
4778 {
4779 struct text_pos textpos;
4780
4781 /* We can use vmotion on frames without proportional fonts. */
4782 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
4783 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
4784 reseat (it, textpos, 1);
4785 it->vpos += pos.vpos;
4786 it->current_y += pos.vpos;
4787 }
4788 else if (dvpos == 0)
4789 {
4790 /* DVPOS == 0 means move to the start of the screen line. */
4791 move_it_vertically_backward (it, 0);
4792 xassert (it->current_x == 0 && it->hpos == 0);
4793 }
4794 else if (dvpos > 0)
4795 {
4796 /* If there are no continuation lines, and if there is no
4797 selective display, try the simple method of moving forward
4798 DVPOS newlines, then see where we are. */
4799 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4800 {
4801 int shortage = 0, charpos;
4802
4803 if (FETCH_BYTE (IT_BYTEPOS (*it) == '\n'))
4804 charpos = IT_CHARPOS (*it) + 1;
4805 else
4806 charpos = scan_buffer ('\n', IT_CHARPOS (*it), 0, dvpos,
4807 &shortage, 0);
4808
4809 if (!invisible_text_between_p (it, IT_CHARPOS (*it), charpos))
4810 {
4811 struct text_pos pos;
4812 CHARPOS (pos) = charpos;
4813 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4814 reseat (it, pos, 1);
4815 it->vpos += dvpos - shortage;
4816 it->hpos = it->current_x = 0;
4817 return;
4818 }
4819 }
4820
4821 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
4822 }
4823 else
4824 {
4825 struct it it2;
4826 int start_charpos, i;
4827
4828 /* If there are no continuation lines, and if there is no
4829 selective display, try the simple method of moving backward
4830 -DVPOS newlines. */
4831 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4832 {
4833 int shortage;
4834 int charpos = IT_CHARPOS (*it);
4835 int bytepos = IT_BYTEPOS (*it);
4836
4837 /* If in the middle of a line, go to its start. */
4838 if (charpos > BEGV && FETCH_BYTE (bytepos - 1) != '\n')
4839 {
4840 charpos = find_next_newline_no_quit (charpos, -1);
4841 bytepos = CHAR_TO_BYTE (charpos);
4842 }
4843
4844 if (charpos == BEGV)
4845 {
4846 struct text_pos pos;
4847 CHARPOS (pos) = charpos;
4848 BYTEPOS (pos) = bytepos;
4849 reseat (it, pos, 1);
4850 it->hpos = it->current_x = 0;
4851 return;
4852 }
4853 else
4854 {
4855 charpos = scan_buffer ('\n', charpos - 1, 0, dvpos, &shortage, 0);
4856 if (!invisible_text_between_p (it, charpos, IT_CHARPOS (*it)))
4857 {
4858 struct text_pos pos;
4859 CHARPOS (pos) = charpos;
4860 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4861 reseat (it, pos, 1);
4862 it->vpos += dvpos + (shortage ? shortage - 1 : 0);
4863 it->hpos = it->current_x = 0;
4864 return;
4865 }
4866 }
4867 }
4868
4869 /* Go back -DVPOS visible lines and reseat the iterator there. */
4870 start_charpos = IT_CHARPOS (*it);
4871 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
4872 back_to_previous_visible_line_start (it);
4873 reseat (it, it->current.pos, 1);
4874 it->current_x = it->hpos = 0;
4875
4876 /* Above call may have moved too far if continuation lines
4877 are involved. Scan forward and see if it did. */
4878 it2 = *it;
4879 it2.vpos = it2.current_y = 0;
4880 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
4881 it->vpos -= it2.vpos;
4882 it->current_y -= it2.current_y;
4883 it->current_x = it->hpos = 0;
4884
4885 /* If we moved too far, move IT some lines forward. */
4886 if (it2.vpos > -dvpos)
4887 {
4888 int delta = it2.vpos + dvpos;
4889 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
4890 }
4891 }
4892}
4893
4894
4895\f
4896/***********************************************************************
4897 Messages
4898 ***********************************************************************/
4899
4900
937248bc
GM
4901/* Add a message with format string FORMAT and arguments ARG1 and ARG2
4902 to *Messages*. */
4903
4904void
4905add_to_log (format, arg1, arg2)
4906 char *format;
4907 Lisp_Object arg1, arg2;
4908{
4909 Lisp_Object args[3];
4910 Lisp_Object msg, fmt;
4911 char *buffer;
4912 int len;
4913 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4914
4915 fmt = msg = Qnil;
4916 GCPRO4 (fmt, msg, arg1, arg2);
4917
4918 args[0] = fmt = build_string (format);
4919 args[1] = arg1;
4920 args[2] = arg2;
6fc556fd 4921 msg = Fformat (3, args);
937248bc
GM
4922
4923 len = STRING_BYTES (XSTRING (msg)) + 1;
4924 buffer = (char *) alloca (len);
4925 strcpy (buffer, XSTRING (msg)->data);
4926
796184bc 4927 message_dolog (buffer, len - 1, 1, 0);
937248bc
GM
4928 UNGCPRO;
4929}
4930
4931
5f5c8ee5
GM
4932/* Output a newline in the *Messages* buffer if "needs" one. */
4933
4934void
4935message_log_maybe_newline ()
4936{
4937 if (message_log_need_newline)
4938 message_dolog ("", 0, 1, 0);
4939}
4940
4941
4942/* Add a string M of length LEN to the message log, optionally
4943 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
4944 nonzero, means interpret the contents of M as multibyte. This
4945 function calls low-level routines in order to bypass text property
4946 hooks, etc. which might not be safe to run. */
4947
4948void
4949message_dolog (m, len, nlflag, multibyte)
4950 char *m;
4951 int len, nlflag, multibyte;
4952{
4953 if (!NILP (Vmessage_log_max))
4954 {
4955 struct buffer *oldbuf;
4956 Lisp_Object oldpoint, oldbegv, oldzv;
4957 int old_windows_or_buffers_changed = windows_or_buffers_changed;
4958 int point_at_end = 0;
4959 int zv_at_end = 0;
4960 Lisp_Object old_deactivate_mark, tem;
4961 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4962
4963 old_deactivate_mark = Vdeactivate_mark;
4964 oldbuf = current_buffer;
6a94510a 4965 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
5f5c8ee5
GM
4966 current_buffer->undo_list = Qt;
4967
4968 oldpoint = Fpoint_marker ();
4969 oldbegv = Fpoint_min_marker ();
4970 oldzv = Fpoint_max_marker ();
4971 GCPRO4 (oldpoint, oldbegv, oldzv, old_deactivate_mark);
4972
4973 if (PT == Z)
4974 point_at_end = 1;
4975 if (ZV == Z)
4976 zv_at_end = 1;
4977
4978 BEGV = BEG;
4979 BEGV_BYTE = BEG_BYTE;
4980 ZV = Z;
4981 ZV_BYTE = Z_BYTE;
4982 TEMP_SET_PT_BOTH (Z, Z_BYTE);
4983
4984 /* Insert the string--maybe converting multibyte to single byte
4985 or vice versa, so that all the text fits the buffer. */
4986 if (multibyte
4987 && NILP (current_buffer->enable_multibyte_characters))
4988 {
4989 int i, c, nbytes;
4990 unsigned char work[1];
4991
4992 /* Convert a multibyte string to single-byte
4993 for the *Message* buffer. */
4994 for (i = 0; i < len; i += nbytes)
4995 {
4fdb80f2 4996 c = string_char_and_length (m + i, len - i, &nbytes);
5f5c8ee5
GM
4997 work[0] = (SINGLE_BYTE_CHAR_P (c)
4998 ? c
4999 : multibyte_char_to_unibyte (c, Qnil));
5000 insert_1_both (work, 1, 1, 1, 0, 0);
5001 }
5002 }
5003 else if (! multibyte
5004 && ! NILP (current_buffer->enable_multibyte_characters))
5005 {
5006 int i, c, nbytes;
5007 unsigned char *msg = (unsigned char *) m;
260a86a0 5008 unsigned char str[MAX_MULTIBYTE_LENGTH];
5f5c8ee5
GM
5009 /* Convert a single-byte string to multibyte
5010 for the *Message* buffer. */
5011 for (i = 0; i < len; i++)
5012 {
5013 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
5014 nbytes = CHAR_STRING (c, str);
5015 insert_1_both (str, 1, nbytes, 1, 0, 0);
5f5c8ee5
GM
5016 }
5017 }
5018 else if (len)
5019 insert_1 (m, len, 1, 0, 0);
5020
5021 if (nlflag)
5022 {
5023 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
5024 insert_1 ("\n", 1, 1, 0, 0);
5025
5026 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
5027 this_bol = PT;
5028 this_bol_byte = PT_BYTE;
5029
5030 if (this_bol > BEG)
5031 {
5032 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
5033 prev_bol = PT;
5034 prev_bol_byte = PT_BYTE;
5035
5036 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
5037 this_bol, this_bol_byte);
5038 if (dup)
5039 {
5040 del_range_both (prev_bol, prev_bol_byte,
5041 this_bol, this_bol_byte, 0);
5042 if (dup > 1)
5043 {
5044 char dupstr[40];
5045 int duplen;
5046
5047 /* If you change this format, don't forget to also
5048 change message_log_check_duplicate. */
5049 sprintf (dupstr, " [%d times]", dup);
5050 duplen = strlen (dupstr);
5051 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
5052 insert_1 (dupstr, duplen, 1, 0, 1);
5053 }
5054 }
5055 }
5056
5057 if (NATNUMP (Vmessage_log_max))
5058 {
5059 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
5060 -XFASTINT (Vmessage_log_max) - 1, 0);
5061 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
5062 }
5063 }
5064 BEGV = XMARKER (oldbegv)->charpos;
5065 BEGV_BYTE = marker_byte_position (oldbegv);
5066
5067 if (zv_at_end)
5068 {
5069 ZV = Z;
5070 ZV_BYTE = Z_BYTE;
5071 }
5072 else
5073 {
5074 ZV = XMARKER (oldzv)->charpos;
5075 ZV_BYTE = marker_byte_position (oldzv);
5076 }
5077
5078 if (point_at_end)
5079 TEMP_SET_PT_BOTH (Z, Z_BYTE);
5080 else
5081 /* We can't do Fgoto_char (oldpoint) because it will run some
5082 Lisp code. */
5083 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
5084 XMARKER (oldpoint)->bytepos);
5085
5086 UNGCPRO;
5087 free_marker (oldpoint);
5088 free_marker (oldbegv);
5089 free_marker (oldzv);
5090
5091 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
5092 set_buffer_internal (oldbuf);
5093 if (NILP (tem))
5094 windows_or_buffers_changed = old_windows_or_buffers_changed;
5095 message_log_need_newline = !nlflag;
5096 Vdeactivate_mark = old_deactivate_mark;
5097 }
5098}
5099
5100
5101/* We are at the end of the buffer after just having inserted a newline.
5102 (Note: We depend on the fact we won't be crossing the gap.)
5103 Check to see if the most recent message looks a lot like the previous one.
5104 Return 0 if different, 1 if the new one should just replace it, or a
5105 value N > 1 if we should also append " [N times]". */
5106
5107static int
5108message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
5109 int prev_bol, this_bol;
5110 int prev_bol_byte, this_bol_byte;
5111{
5112 int i;
5113 int len = Z_BYTE - 1 - this_bol_byte;
5114 int seen_dots = 0;
5115 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
5116 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
5117
5118 for (i = 0; i < len; i++)
5119 {
5120 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
5121 && p1[i] != '\n')
5122 seen_dots = 1;
5123 if (p1[i] != p2[i])
5124 return seen_dots;
5125 }
5126 p1 += len;
5127 if (*p1 == '\n')
5128 return 2;
5129 if (*p1++ == ' ' && *p1++ == '[')
5130 {
5131 int n = 0;
5132 while (*p1 >= '0' && *p1 <= '9')
5133 n = n * 10 + *p1++ - '0';
5134 if (strncmp (p1, " times]\n", 8) == 0)
5135 return n+1;
5136 }
5137 return 0;
5138}
5139
5140
5141/* Display an echo area message M with a specified length of LEN
5142 chars. The string may include null characters. If M is 0, clear
5143 out any existing message, and let the mini-buffer text show through.
5144
5145 The buffer M must continue to exist until after the echo area gets
5146 cleared or some other message gets displayed there. This means do
5147 not pass text that is stored in a Lisp string; do not pass text in
5148 a buffer that was alloca'd. */
5149
5150void
5151message2 (m, len, multibyte)
5152 char *m;
5153 int len;
5154 int multibyte;
5155{
5156 /* First flush out any partial line written with print. */
5157 message_log_maybe_newline ();
5158 if (m)
5159 message_dolog (m, len, 1, multibyte);
5160 message2_nolog (m, len, multibyte);
5161}
5162
5163
5164/* The non-logging counterpart of message2. */
5165
5166void
5167message2_nolog (m, len, multibyte)
5168 char *m;
5169 int len;
5170{
886bd6f2 5171 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5172 message_enable_multibyte = multibyte;
5173
5174 if (noninteractive)
5175 {
5176 if (noninteractive_need_newline)
5177 putc ('\n', stderr);
5178 noninteractive_need_newline = 0;
5179 if (m)
5180 fwrite (m, len, 1, stderr);
5181 if (cursor_in_echo_area == 0)
5182 fprintf (stderr, "\n");
5183 fflush (stderr);
5184 }
5185 /* A null message buffer means that the frame hasn't really been
5186 initialized yet. Error messages get reported properly by
5187 cmd_error, so this must be just an informative message; toss it. */
5188 else if (INTERACTIVE
886bd6f2
GM
5189 && sf->glyphs_initialized_p
5190 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
5191 {
5192 Lisp_Object mini_window;
5193 struct frame *f;
5194
5195 /* Get the frame containing the mini-buffer
5196 that the selected frame is using. */
886bd6f2 5197 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5198 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5199
5200 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 5201 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
5202 && ! FRAME_VISIBLE_P (f))
5203 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
5204
5205 if (m)
5206 {
c6e89d6c 5207 set_message (m, Qnil, len, multibyte);
5f5c8ee5
GM
5208 if (minibuffer_auto_raise)
5209 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5210 }
5211 else
c6e89d6c 5212 clear_message (1, 1);
5f5c8ee5 5213
c6e89d6c 5214 do_pending_window_change (0);
5f5c8ee5 5215 echo_area_display (1);
c6e89d6c 5216 do_pending_window_change (0);
5f5c8ee5
GM
5217 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
5218 (*frame_up_to_date_hook) (f);
5219 }
5220}
5221
5222
c6e89d6c
GM
5223/* Display an echo area message M with a specified length of NBYTES
5224 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
5225 string, clear out any existing message, and let the mini-buffer
5226 text show through. */
5227
5228void
c6e89d6c 5229message3 (m, nbytes, multibyte)
5f5c8ee5 5230 Lisp_Object m;
c6e89d6c 5231 int nbytes;
5f5c8ee5
GM
5232 int multibyte;
5233{
5234 struct gcpro gcpro1;
5235
5236 GCPRO1 (m);
5237
5238 /* First flush out any partial line written with print. */
5239 message_log_maybe_newline ();
5240 if (STRINGP (m))
c6e89d6c
GM
5241 message_dolog (XSTRING (m)->data, nbytes, 1, multibyte);
5242 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
5243
5244 UNGCPRO;
5245}
5246
5247
5248/* The non-logging version of message3. */
5249
5250void
c6e89d6c 5251message3_nolog (m, nbytes, multibyte)
5f5c8ee5 5252 Lisp_Object m;
c6e89d6c 5253 int nbytes, multibyte;
5f5c8ee5 5254{
886bd6f2 5255 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5256 message_enable_multibyte = multibyte;
5257
5258 if (noninteractive)
5259 {
5260 if (noninteractive_need_newline)
5261 putc ('\n', stderr);
5262 noninteractive_need_newline = 0;
5263 if (STRINGP (m))
c6e89d6c 5264 fwrite (XSTRING (m)->data, nbytes, 1, stderr);
5f5c8ee5
GM
5265 if (cursor_in_echo_area == 0)
5266 fprintf (stderr, "\n");
5267 fflush (stderr);
5268 }
5269 /* A null message buffer means that the frame hasn't really been
5270 initialized yet. Error messages get reported properly by
5271 cmd_error, so this must be just an informative message; toss it. */
5272 else if (INTERACTIVE
886bd6f2
GM
5273 && sf->glyphs_initialized_p
5274 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
5275 {
5276 Lisp_Object mini_window;
c6e89d6c 5277 Lisp_Object frame;
5f5c8ee5
GM
5278 struct frame *f;
5279
5280 /* Get the frame containing the mini-buffer
5281 that the selected frame is using. */
886bd6f2 5282 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5283 frame = XWINDOW (mini_window)->frame;
5284 f = XFRAME (frame);
5f5c8ee5
GM
5285
5286 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 5287 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
5288 && !FRAME_VISIBLE_P (f))
5289 Fmake_frame_visible (frame);
5f5c8ee5 5290
c6e89d6c 5291 if (STRINGP (m) && XSTRING (m)->size)
5f5c8ee5 5292 {
c6e89d6c 5293 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
5294 if (minibuffer_auto_raise)
5295 Fraise_frame (frame);
5f5c8ee5
GM
5296 }
5297 else
c6e89d6c 5298 clear_message (1, 1);
5f5c8ee5 5299
c6e89d6c 5300 do_pending_window_change (0);
5f5c8ee5 5301 echo_area_display (1);
c6e89d6c 5302 do_pending_window_change (0);
5f5c8ee5
GM
5303 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
5304 (*frame_up_to_date_hook) (f);
5305 }
5306}
5307
5308
5309/* Display a null-terminated echo area message M. If M is 0, clear
5310 out any existing message, and let the mini-buffer text show through.
5311
5312 The buffer M must continue to exist until after the echo area gets
5313 cleared or some other message gets displayed there. Do not pass
5314 text that is stored in a Lisp string. Do not pass text in a buffer
5315 that was alloca'd. */
5316
5317void
5318message1 (m)
5319 char *m;
5320{
5321 message2 (m, (m ? strlen (m) : 0), 0);
5322}
5323
5324
5325/* The non-logging counterpart of message1. */
5326
5327void
5328message1_nolog (m)
5329 char *m;
5330{
5331 message2_nolog (m, (m ? strlen (m) : 0), 0);
5332}
5333
5334/* Display a message M which contains a single %s
5335 which gets replaced with STRING. */
5336
5337void
5338message_with_string (m, string, log)
5339 char *m;
5340 Lisp_Object string;
5341 int log;
5342{
5343 if (noninteractive)
5344 {
5345 if (m)
5346 {
5347 if (noninteractive_need_newline)
5348 putc ('\n', stderr);
5349 noninteractive_need_newline = 0;
5350 fprintf (stderr, m, XSTRING (string)->data);
5351 if (cursor_in_echo_area == 0)
5352 fprintf (stderr, "\n");
5353 fflush (stderr);
5354 }
5355 }
5356 else if (INTERACTIVE)
5357 {
5358 /* The frame whose minibuffer we're going to display the message on.
5359 It may be larger than the selected frame, so we need
5360 to use its buffer, not the selected frame's buffer. */
5361 Lisp_Object mini_window;
886bd6f2 5362 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5363
5364 /* Get the frame containing the minibuffer
5365 that the selected frame is using. */
886bd6f2 5366 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5367 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5368
5369 /* A null message buffer means that the frame hasn't really been
5370 initialized yet. Error messages get reported properly by
5371 cmd_error, so this must be just an informative message; toss it. */
5372 if (FRAME_MESSAGE_BUF (f))
5373 {
5374 int len;
5375 char *a[1];
5376 a[0] = (char *) XSTRING (string)->data;
5377
5378 len = doprnt (FRAME_MESSAGE_BUF (f),
5379 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5380
5381 if (log)
5382 message2 (FRAME_MESSAGE_BUF (f), len,
5383 STRING_MULTIBYTE (string));
5384 else
5385 message2_nolog (FRAME_MESSAGE_BUF (f), len,
5386 STRING_MULTIBYTE (string));
5387
5388 /* Print should start at the beginning of the message
5389 buffer next time. */
5390 message_buf_print = 0;
5391 }
5392 }
5393}
5394
5395
5f5c8ee5
GM
5396/* Dump an informative message to the minibuf. If M is 0, clear out
5397 any existing message, and let the mini-buffer text show through. */
5398
5399/* VARARGS 1 */
5400void
5401message (m, a1, a2, a3)
5402 char *m;
5403 EMACS_INT a1, a2, a3;
5404{
5405 if (noninteractive)
5406 {
5407 if (m)
5408 {
5409 if (noninteractive_need_newline)
5410 putc ('\n', stderr);
5411 noninteractive_need_newline = 0;
5412 fprintf (stderr, m, a1, a2, a3);
5413 if (cursor_in_echo_area == 0)
5414 fprintf (stderr, "\n");
5415 fflush (stderr);
5416 }
5417 }
5418 else if (INTERACTIVE)
5419 {
5420 /* The frame whose mini-buffer we're going to display the message
5421 on. It may be larger than the selected frame, so we need to
5422 use its buffer, not the selected frame's buffer. */
5423 Lisp_Object mini_window;
886bd6f2 5424 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5425
5426 /* Get the frame containing the mini-buffer
5427 that the selected frame is using. */
886bd6f2 5428 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5429 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5430
5431 /* A null message buffer means that the frame hasn't really been
5432 initialized yet. Error messages get reported properly by
5433 cmd_error, so this must be just an informative message; toss
5434 it. */
5435 if (FRAME_MESSAGE_BUF (f))
5436 {
5437 if (m)
5438 {
5439 int len;
5440#ifdef NO_ARG_ARRAY
5441 char *a[3];
5442 a[0] = (char *) a1;
5443 a[1] = (char *) a2;
5444 a[2] = (char *) a3;
5445
5446 len = doprnt (FRAME_MESSAGE_BUF (f),
5447 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5448#else
5449 len = doprnt (FRAME_MESSAGE_BUF (f),
5450 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
5451 (char **) &a1);
5452#endif /* NO_ARG_ARRAY */
5453
5454 message2 (FRAME_MESSAGE_BUF (f), len, 0);
5455 }
5456 else
5457 message1 (0);
5458
5459 /* Print should start at the beginning of the message
5460 buffer next time. */
5461 message_buf_print = 0;
5462 }
5463 }
5464}
5465
5466
5467/* The non-logging version of message. */
5468
5469void
5470message_nolog (m, a1, a2, a3)
5471 char *m;
5472 EMACS_INT a1, a2, a3;
5473{
5474 Lisp_Object old_log_max;
5475 old_log_max = Vmessage_log_max;
5476 Vmessage_log_max = Qnil;
5477 message (m, a1, a2, a3);
5478 Vmessage_log_max = old_log_max;
5479}
5480
5481
c6e89d6c
GM
5482/* Display the current message in the current mini-buffer. This is
5483 only called from error handlers in process.c, and is not time
5484 critical. */
5f5c8ee5
GM
5485
5486void
5487update_echo_area ()
5488{
c6e89d6c
GM
5489 if (!NILP (echo_area_buffer[0]))
5490 {
5491 Lisp_Object string;
5492 string = Fcurrent_message ();
5493 message3 (string, XSTRING (string)->size,
5494 !NILP (current_buffer->enable_multibyte_characters));
5495 }
5496}
5497
5498
5bcfeb49
GM
5499/* Make sure echo area buffers in echo_buffers[] are life. If they
5500 aren't, make new ones. */
5501
5502static void
5503ensure_echo_area_buffers ()
5504{
5505 int i;
5506
5507 for (i = 0; i < 2; ++i)
5508 if (!BUFFERP (echo_buffer[i])
5509 || NILP (XBUFFER (echo_buffer[i])->name))
5510 {
5511 char name[30];
ff3d9573
GM
5512 Lisp_Object old_buffer;
5513 int j;
5514
5515 old_buffer = echo_buffer[i];
5bcfeb49
GM
5516 sprintf (name, " *Echo Area %d*", i);
5517 echo_buffer[i] = Fget_buffer_create (build_string (name));
ad4f174e 5518 XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
ff3d9573
GM
5519
5520 for (j = 0; j < 2; ++j)
5521 if (EQ (old_buffer, echo_area_buffer[j]))
5522 echo_area_buffer[j] = echo_buffer[i];
5bcfeb49
GM
5523 }
5524}
5525
5526
23a96c77 5527/* Call FN with args A1..A4 with either the current or last displayed
c6e89d6c
GM
5528 echo_area_buffer as current buffer.
5529
5530 WHICH zero means use the current message buffer
5531 echo_area_buffer[0]. If that is nil, choose a suitable buffer
5532 from echo_buffer[] and clear it.
5533
5534 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
5535 suitable buffer from echo_buffer[] and clear it.
5536
5537 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
5538 that the current message becomes the last displayed one, make
5539 choose a suitable buffer for echo_area_buffer[0], and clear it.
5540
5541 Value is what FN returns. */
5542
5543static int
23a96c77 5544with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
c6e89d6c
GM
5545 struct window *w;
5546 int which;
23dd2d97
KR
5547 int (*fn) P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
5548 EMACS_INT a1;
5549 Lisp_Object a2;
5550 EMACS_INT a3, a4;
c6e89d6c
GM
5551{
5552 Lisp_Object buffer;
15e26c76 5553 int this_one, the_other, clear_buffer_p, rc;
c6e89d6c
GM
5554 int count = specpdl_ptr - specpdl;
5555
5556 /* If buffers aren't life, make new ones. */
5bcfeb49 5557 ensure_echo_area_buffers ();
c6e89d6c
GM
5558
5559 clear_buffer_p = 0;
5560
5561 if (which == 0)
5562 this_one = 0, the_other = 1;
5563 else if (which > 0)
5564 this_one = 1, the_other = 0;
5f5c8ee5 5565 else
c6e89d6c
GM
5566 {
5567 this_one = 0, the_other = 1;
5568 clear_buffer_p = 1;
5569
5570 /* We need a fresh one in case the current echo buffer equals
5571 the one containing the last displayed echo area message. */
5572 if (!NILP (echo_area_buffer[this_one])
5573 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
5574 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
5575 }
5576
5577 /* Choose a suitable buffer from echo_buffer[] is we don't
5578 have one. */
5579 if (NILP (echo_area_buffer[this_one]))
5580 {
5581 echo_area_buffer[this_one]
5582 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
5583 ? echo_buffer[the_other]
5584 : echo_buffer[this_one]);
5585 clear_buffer_p = 1;
5586 }
5587
5588 buffer = echo_area_buffer[this_one];
5589
5590 record_unwind_protect (unwind_with_echo_area_buffer,
5591 with_echo_area_buffer_unwind_data (w));
5592
5593 /* Make the echo area buffer current. Note that for display
5594 purposes, it is not necessary that the displayed window's buffer
5595 == current_buffer, except for text property lookup. So, let's
5596 only set that buffer temporarily here without doing a full
5597 Fset_window_buffer. We must also change w->pointm, though,
5598 because otherwise an assertions in unshow_buffer fails, and Emacs
5599 aborts. */
9142dd5b 5600 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
5601 if (w)
5602 {
5603 w->buffer = buffer;
5604 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
5605 }
ad4f174e 5606
c6e89d6c
GM
5607 current_buffer->undo_list = Qt;
5608 current_buffer->read_only = Qnil;
5609
5610 if (clear_buffer_p && Z > BEG)
5611 del_range (BEG, Z);
5612
5613 xassert (BEGV >= BEG);
5614 xassert (ZV <= Z && ZV >= BEGV);
5615
23a96c77 5616 rc = fn (a1, a2, a3, a4);
c6e89d6c
GM
5617
5618 xassert (BEGV >= BEG);
5619 xassert (ZV <= Z && ZV >= BEGV);
5620
5621 unbind_to (count, Qnil);
5622 return rc;
5f5c8ee5
GM
5623}
5624
5625
c6e89d6c
GM
5626/* Save state that should be preserved around the call to the function
5627 FN called in with_echo_area_buffer. */
5f5c8ee5 5628
c6e89d6c
GM
5629static Lisp_Object
5630with_echo_area_buffer_unwind_data (w)
5631 struct window *w;
5f5c8ee5 5632{
c6e89d6c
GM
5633 int i = 0;
5634 Lisp_Object vector;
5f5c8ee5 5635
c6e89d6c
GM
5636 /* Reduce consing by keeping one vector in
5637 Vwith_echo_area_save_vector. */
5638 vector = Vwith_echo_area_save_vector;
5639 Vwith_echo_area_save_vector = Qnil;
5640
5641 if (NILP (vector))
9142dd5b 5642 vector = Fmake_vector (make_number (7), Qnil);
c6e89d6c
GM
5643
5644 XSETBUFFER (XVECTOR (vector)->contents[i], current_buffer); ++i;
5645 XVECTOR (vector)->contents[i++] = Vdeactivate_mark;
5646 XVECTOR (vector)->contents[i++] = make_number (windows_or_buffers_changed);
c6e89d6c
GM
5647
5648 if (w)
5649 {
5650 XSETWINDOW (XVECTOR (vector)->contents[i], w); ++i;
5651 XVECTOR (vector)->contents[i++] = w->buffer;
5652 XVECTOR (vector)->contents[i++]
5653 = make_number (XMARKER (w->pointm)->charpos);
5654 XVECTOR (vector)->contents[i++]
5655 = make_number (XMARKER (w->pointm)->bytepos);
5656 }
5657 else
5658 {
5659 int end = i + 4;
5660 while (i < end)
5661 XVECTOR (vector)->contents[i++] = Qnil;
5662 }
5f5c8ee5 5663
c6e89d6c
GM
5664 xassert (i == XVECTOR (vector)->size);
5665 return vector;
5666}
5f5c8ee5 5667
5f5c8ee5 5668
c6e89d6c
GM
5669/* Restore global state from VECTOR which was created by
5670 with_echo_area_buffer_unwind_data. */
5671
5672static Lisp_Object
5673unwind_with_echo_area_buffer (vector)
5674 Lisp_Object vector;
5675{
5676 int i = 0;
5677
9142dd5b 5678 set_buffer_internal_1 (XBUFFER (XVECTOR (vector)->contents[i])); ++i;
c6e89d6c
GM
5679 Vdeactivate_mark = XVECTOR (vector)->contents[i]; ++i;
5680 windows_or_buffers_changed = XFASTINT (XVECTOR (vector)->contents[i]); ++i;
c6e89d6c
GM
5681
5682 if (WINDOWP (XVECTOR (vector)->contents[i]))
5683 {
5684 struct window *w;
5685 Lisp_Object buffer, charpos, bytepos;
5686
5687 w = XWINDOW (XVECTOR (vector)->contents[i]); ++i;
5688 buffer = XVECTOR (vector)->contents[i]; ++i;
5689 charpos = XVECTOR (vector)->contents[i]; ++i;
5690 bytepos = XVECTOR (vector)->contents[i]; ++i;
5691
5692 w->buffer = buffer;
5693 set_marker_both (w->pointm, buffer,
5694 XFASTINT (charpos), XFASTINT (bytepos));
5695 }
5696
5697 Vwith_echo_area_save_vector = vector;
5698 return Qnil;
5699}
5700
5701
5702/* Set up the echo area for use by print functions. MULTIBYTE_P
5703 non-zero means we will print multibyte. */
5704
5705void
5706setup_echo_area_for_printing (multibyte_p)
5707 int multibyte_p;
5708{
5bcfeb49
GM
5709 ensure_echo_area_buffers ();
5710
c6e89d6c
GM
5711 if (!message_buf_print)
5712 {
5713 /* A message has been output since the last time we printed.
5714 Choose a fresh echo area buffer. */
5715 if (EQ (echo_area_buffer[1], echo_buffer[0]))
5716 echo_area_buffer[0] = echo_buffer[1];
5717 else
5718 echo_area_buffer[0] = echo_buffer[0];
5719
5720 /* Switch to that buffer and clear it. */
5721 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5722 if (Z > BEG)
5723 del_range (BEG, Z);
5724 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5725
5726 /* Set up the buffer for the multibyteness we need. */
5727 if (multibyte_p
5728 != !NILP (current_buffer->enable_multibyte_characters))
5729 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
5730
5731 /* Raise the frame containing the echo area. */
5732 if (minibuffer_auto_raise)
5733 {
886bd6f2 5734 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5735 Lisp_Object mini_window;
886bd6f2 5736 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5737 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5738 }
5739
8a4e3c0c 5740 message_log_maybe_newline ();
c6e89d6c
GM
5741 message_buf_print = 1;
5742 }
fa77249f
GM
5743 else
5744 {
5745 if (NILP (echo_area_buffer[0]))
5746 {
5747 if (EQ (echo_area_buffer[1], echo_buffer[0]))
5748 echo_area_buffer[0] = echo_buffer[1];
5749 else
5750 echo_area_buffer[0] = echo_buffer[0];
5751 }
5752
5753 if (current_buffer != XBUFFER (echo_area_buffer[0]))
5754 /* Someone switched buffers between print requests. */
5755 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5756 }
c6e89d6c
GM
5757}
5758
5759
dd2eb166
GM
5760/* Display an echo area message in window W. Value is non-zero if W's
5761 height is changed. If display_last_displayed_message_p is
5762 non-zero, display the message that was last displayed, otherwise
5763 display the current message. */
c6e89d6c
GM
5764
5765static int
5766display_echo_area (w)
5767 struct window *w;
5768{
25edb08f
GM
5769 int i, no_message_p, window_height_changed_p, count;
5770
5771 /* Temporarily disable garbage collections while displaying the echo
5772 area. This is done because a GC can print a message itself.
5773 That message would modify the echo area buffer's contents while a
5774 redisplay of the buffer is going on, and seriously confuse
5775 redisplay. */
5776 count = inhibit_garbage_collection ();
dd2eb166
GM
5777
5778 /* If there is no message, we must call display_echo_area_1
5779 nevertheless because it resizes the window. But we will have to
5780 reset the echo_area_buffer in question to nil at the end because
5781 with_echo_area_buffer will sets it to an empty buffer. */
5782 i = display_last_displayed_message_p ? 1 : 0;
5783 no_message_p = NILP (echo_area_buffer[i]);
5784
5785 window_height_changed_p
5786 = with_echo_area_buffer (w, display_last_displayed_message_p,
23a96c77 5787 display_echo_area_1,
23dd2d97 5788 (EMACS_INT) w, Qnil, 0, 0);
dd2eb166
GM
5789
5790 if (no_message_p)
5791 echo_area_buffer[i] = Qnil;
25edb08f
GM
5792
5793 unbind_to (count, Qnil);
dd2eb166 5794 return window_height_changed_p;
c6e89d6c
GM
5795}
5796
5797
5798/* Helper for display_echo_area. Display the current buffer which
23a96c77
GM
5799 contains the current echo area message in window W, a mini-window,
5800 a pointer to which is passed in A1. A2..A4 are currently not used.
c6e89d6c
GM
5801 Change the height of W so that all of the message is displayed.
5802 Value is non-zero if height of W was changed. */
5803
5804static int
23a96c77 5805display_echo_area_1 (a1, a2, a3, a4)
23dd2d97
KR
5806 EMACS_INT a1;
5807 Lisp_Object a2;
5808 EMACS_INT a3, a4;
c6e89d6c 5809{
23a96c77 5810 struct window *w = (struct window *) a1;
c6e89d6c 5811 Lisp_Object window;
c6e89d6c
GM
5812 struct text_pos start;
5813 int window_height_changed_p = 0;
5814
5815 /* Do this before displaying, so that we have a large enough glyph
5816 matrix for the display. */
92a90e89 5817 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
5818
5819 /* Display. */
5820 clear_glyph_matrix (w->desired_matrix);
5821 XSETWINDOW (window, w);
5822 SET_TEXT_POS (start, BEG, BEG_BYTE);
5823 try_window (window, start);
5824
c6e89d6c
GM
5825 return window_height_changed_p;
5826}
5827
5828
92a90e89
GM
5829/* Resize the echo area window to exactly the size needed for the
5830 currently displayed message, if there is one. */
5831
5832void
5833resize_echo_area_axactly ()
5834{
5835 if (BUFFERP (echo_area_buffer[0])
5836 && WINDOWP (echo_area_window))
5837 {
5838 struct window *w = XWINDOW (echo_area_window);
5839 int resized_p;
5840
23a96c77 5841 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
23dd2d97 5842 (EMACS_INT) w, Qnil, 0, 0);
92a90e89
GM
5843 if (resized_p)
5844 {
5845 ++windows_or_buffers_changed;
5846 ++update_mode_lines;
5847 redisplay_internal (0);
5848 }
5849 }
5850}
5851
5852
23a96c77
GM
5853/* Callback function for with_echo_area_buffer, when used from
5854 resize_echo_area_axactly. A1 contains a pointer to the window to
5855 resize, A2 to A4 are not used. Value is what resize_mini_window
5856 returns. */
5857
5858static int
5859resize_mini_window_1 (a1, a2, a3, a4)
23dd2d97
KR
5860 EMACS_INT a1;
5861 Lisp_Object a2;
5862 EMACS_INT a3, a4;
23a96c77
GM
5863{
5864 return resize_mini_window ((struct window *) a1, 1);
5865}
5866
5867
92a90e89
GM
5868/* Resize mini-window W to fit the size of its contents. EXACT:P
5869 means size the window exactly to the size needed. Otherwise, it's
5870 only enlarged until W's buffer is empty. Value is non-zero if
5871 the window height has been changed. */
c6e89d6c 5872
9472f927 5873int
92a90e89 5874resize_mini_window (w, exact_p)
c6e89d6c 5875 struct window *w;
92a90e89 5876 int exact_p;
c6e89d6c
GM
5877{
5878 struct frame *f = XFRAME (w->frame);
5879 int window_height_changed_p = 0;
5880
5881 xassert (MINI_WINDOW_P (w));
97cafc0f
GM
5882
5883 /* Nil means don't try to resize. */
00f6d59e
GM
5884 if (NILP (Vmax_mini_window_height)
5885 || (FRAME_X_P (f) && f->output_data.x == NULL))
97cafc0f 5886 return 0;
c6e89d6c
GM
5887
5888 if (!FRAME_MINIBUF_ONLY_P (f))
5889 {
5890 struct it it;
dd2eb166
GM
5891 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
5892 int total_height = XFASTINT (root->height) + XFASTINT (w->height);
5893 int height, max_height;
5894 int unit = CANON_Y_UNIT (f);
5895 struct text_pos start;
9142dd5b 5896
c6e89d6c 5897 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 5898
dd2eb166
GM
5899 /* Compute the max. number of lines specified by the user. */
5900 if (FLOATP (Vmax_mini_window_height))
5901 max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
5902 else if (INTEGERP (Vmax_mini_window_height))
5903 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
5904 else
5905 max_height = total_height / 4;
dd2eb166
GM
5906
5907 /* Correct that max. height if it's bogus. */
5908 max_height = max (1, max_height);
5909 max_height = min (total_height, max_height);
5910
5911 /* Find out the height of the text in the window. */
ad4f174e
GM
5912 if (it.truncate_lines_p)
5913 height = 1;
55b064bd 5914 else
ad4f174e
GM
5915 {
5916 last_height = 0;
5917 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
5918 if (it.max_ascent == 0 && it.max_descent == 0)
5919 height = it.current_y + last_height;
5920 else
5921 height = it.current_y + it.max_ascent + it.max_descent;
3c4b7685 5922 height -= it.extra_line_spacing;
ad4f174e
GM
5923 height = (height + unit - 1) / unit;
5924 }
dd2eb166
GM
5925
5926 /* Compute a suitable window start. */
5927 if (height > max_height)
5928 {
5929 height = max_height;
5930 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5931 move_it_vertically_backward (&it, (height - 1) * unit);
5932 start = it.current.pos;
5933 }
5934 else
5935 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5936 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 5937
9472f927
GM
5938 /* Let it grow only, until we display an empty message, in which
5939 case the window shrinks again. */
da448723 5940 if (height > XFASTINT (w->height))
dd2eb166 5941 {
d2c48e86 5942 int old_height = XFASTINT (w->height);
da448723
GM
5943 freeze_window_starts (f, 1);
5944 grow_mini_window (w, height - XFASTINT (w->height));
5945 window_height_changed_p = XFASTINT (w->height) != old_height;
5946 }
5947 else if (height < XFASTINT (w->height)
5948 && (exact_p || BEGV == ZV))
5949 {
5950 int old_height = XFASTINT (w->height);
5951 freeze_window_starts (f, 0);
5952 shrink_mini_window (w);
d2c48e86 5953 window_height_changed_p = XFASTINT (w->height) != old_height;
9142dd5b 5954 }
c6e89d6c
GM
5955 }
5956
5957 return window_height_changed_p;
5958}
5959
5960
5961/* Value is the current message, a string, or nil if there is no
5962 current message. */
5963
5964Lisp_Object
5965current_message ()
5966{
5967 Lisp_Object msg;
5968
5969 if (NILP (echo_area_buffer[0]))
5970 msg = Qnil;
5971 else
5972 {
23a96c77 5973 with_echo_area_buffer (0, 0, current_message_1,
23dd2d97 5974 (EMACS_INT) &msg, Qnil, 0, 0);
c6e89d6c
GM
5975 if (NILP (msg))
5976 echo_area_buffer[0] = Qnil;
5977 }
5978
5979 return msg;
5980}
5981
5982
5983static int
23a96c77 5984current_message_1 (a1, a2, a3, a4)
23dd2d97
KR
5985 EMACS_INT a1;
5986 Lisp_Object a2;
5987 EMACS_INT a3, a4;
c6e89d6c 5988{
23a96c77
GM
5989 Lisp_Object *msg = (Lisp_Object *) a1;
5990
c6e89d6c
GM
5991 if (Z > BEG)
5992 *msg = make_buffer_string (BEG, Z, 1);
5993 else
5994 *msg = Qnil;
5995 return 0;
5996}
5997
5998
5999/* Push the current message on Vmessage_stack for later restauration
6000 by restore_message. Value is non-zero if the current message isn't
6001 empty. This is a relatively infrequent operation, so it's not
6002 worth optimizing. */
6003
6004int
6005push_message ()
6006{
6007 Lisp_Object msg;
6008 msg = current_message ();
6009 Vmessage_stack = Fcons (msg, Vmessage_stack);
6010 return STRINGP (msg);
6011}
6012
6013
6014/* Restore message display from the top of Vmessage_stack. */
6015
6016void
6017restore_message ()
6018{
6019 Lisp_Object msg;
6020
6021 xassert (CONSP (Vmessage_stack));
6022 msg = XCAR (Vmessage_stack);
6023 if (STRINGP (msg))
6024 message3_nolog (msg, STRING_BYTES (XSTRING (msg)), STRING_MULTIBYTE (msg));
6025 else
6026 message3_nolog (msg, 0, 0);
6027}
6028
6029
6030/* Pop the top-most entry off Vmessage_stack. */
6031
6032void
6033pop_message ()
6034{
6035 xassert (CONSP (Vmessage_stack));
6036 Vmessage_stack = XCDR (Vmessage_stack);
6037}
6038
6039
6040/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
6041 exits. If the stack is not empty, we have a missing pop_message
6042 somewhere. */
6043
6044void
6045check_message_stack ()
6046{
6047 if (!NILP (Vmessage_stack))
6048 abort ();
6049}
6050
6051
6052/* Truncate to NCHARS what will be displayed in the echo area the next
6053 time we display it---but don't redisplay it now. */
6054
6055void
6056truncate_echo_area (nchars)
6057 int nchars;
6058{
6059 if (nchars == 0)
6060 echo_area_buffer[0] = Qnil;
6061 /* A null message buffer means that the frame hasn't really been
6062 initialized yet. Error messages get reported properly by
6063 cmd_error, so this must be just an informative message; toss it. */
6064 else if (!noninteractive
6065 && INTERACTIVE
c6e89d6c 6066 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
6067 {
6068 struct frame *sf = SELECTED_FRAME ();
6069 if (FRAME_MESSAGE_BUF (sf))
23dd2d97 6070 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0);
886bd6f2 6071 }
c6e89d6c
GM
6072}
6073
6074
6075/* Helper function for truncate_echo_area. Truncate the current
6076 message to at most NCHARS characters. */
6077
6078static int
23a96c77 6079truncate_message_1 (nchars, a2, a3, a4)
23dd2d97
KR
6080 EMACS_INT nchars;
6081 Lisp_Object a2;
6082 EMACS_INT a3, a4;
c6e89d6c
GM
6083{
6084 if (BEG + nchars < Z)
6085 del_range (BEG + nchars, Z);
6086 if (Z == BEG)
6087 echo_area_buffer[0] = Qnil;
6088 return 0;
6089}
6090
6091
6092/* Set the current message to a substring of S or STRING.
6093
6094 If STRING is a Lisp string, set the message to the first NBYTES
6095 bytes from STRING. NBYTES zero means use the whole string. If
6096 STRING is multibyte, the message will be displayed multibyte.
6097
6098 If S is not null, set the message to the first LEN bytes of S. LEN
6099 zero means use the whole string. MULTIBYTE_P non-zero means S is
6100 multibyte. Display the message multibyte in that case. */
6101
6102void
6103set_message (s, string, nbytes, multibyte_p)
6104 char *s;
6105 Lisp_Object string;
6106 int nbytes;
6107{
6108 message_enable_multibyte
6109 = ((s && multibyte_p)
6110 || (STRINGP (string) && STRING_MULTIBYTE (string)));
6111
23a96c77
GM
6112 with_echo_area_buffer (0, -1, set_message_1,
6113 (EMACS_INT) s, string, nbytes, multibyte_p);
c6e89d6c
GM
6114 message_buf_print = 0;
6115}
6116
6117
6118/* Helper function for set_message. Arguments have the same meaning
23a96c77
GM
6119 as there, with A1 corresponding to S and A2 corresponding to STRING
6120 This function is called with the echo area buffer being
c6e89d6c
GM
6121 current. */
6122
6123static int
23a96c77 6124set_message_1 (a1, a2, nbytes, multibyte_p)
23dd2d97
KR
6125 EMACS_INT a1;
6126 Lisp_Object a2;
6127 EMACS_INT nbytes, multibyte_p;
c6e89d6c 6128{
23a96c77 6129 char *s = (char *) a1;
23dd2d97 6130 Lisp_Object string = a2;
23a96c77 6131
c6e89d6c
GM
6132 xassert (BEG == Z);
6133
6134 /* Change multibyteness of the echo buffer appropriately. */
6135 if (message_enable_multibyte
6136 != !NILP (current_buffer->enable_multibyte_characters))
6137 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
6138
ad4f174e
GM
6139 current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
6140
c6e89d6c
GM
6141 /* Insert new message at BEG. */
6142 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
6143
6144 if (STRINGP (string))
6145 {
6146 int nchars;
6147
6148 if (nbytes == 0)
6149 nbytes = XSTRING (string)->size_byte;
6150 nchars = string_byte_to_char (string, nbytes);
6151
6152 /* This function takes care of single/multibyte conversion. We
6153 just have to ensure that the echo area buffer has the right
6154 setting of enable_multibyte_characters. */
6155 insert_from_string (string, 0, 0, nchars, nbytes, 1);
6156 }
6157 else if (s)
6158 {
6159 if (nbytes == 0)
6160 nbytes = strlen (s);
6161
6162 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
6163 {
6164 /* Convert from multi-byte to single-byte. */
6165 int i, c, n;
6166 unsigned char work[1];
6167
6168 /* Convert a multibyte string to single-byte. */
6169 for (i = 0; i < nbytes; i += n)
6170 {
6171 c = string_char_and_length (s + i, nbytes - i, &n);
6172 work[0] = (SINGLE_BYTE_CHAR_P (c)
6173 ? c
6174 : multibyte_char_to_unibyte (c, Qnil));
6175 insert_1_both (work, 1, 1, 1, 0, 0);
6176 }
6177 }
6178 else if (!multibyte_p
6179 && !NILP (current_buffer->enable_multibyte_characters))
6180 {
6181 /* Convert from single-byte to multi-byte. */
6182 int i, c, n;
6183 unsigned char *msg = (unsigned char *) s;
260a86a0 6184 unsigned char str[MAX_MULTIBYTE_LENGTH];
c6e89d6c
GM
6185
6186 /* Convert a single-byte string to multibyte. */
6187 for (i = 0; i < nbytes; i++)
6188 {
6189 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
6190 n = CHAR_STRING (c, str);
6191 insert_1_both (str, 1, n, 1, 0, 0);
c6e89d6c
GM
6192 }
6193 }
6194 else
6195 insert_1 (s, nbytes, 1, 0, 0);
6196 }
6197
6198 return 0;
6199}
6200
6201
6202/* Clear messages. CURRENT_P non-zero means clear the current
6203 message. LAST_DISPLAYED_P non-zero means clear the message
6204 last displayed. */
6205
6206void
6207clear_message (current_p, last_displayed_p)
6208 int current_p, last_displayed_p;
6209{
6210 if (current_p)
6211 echo_area_buffer[0] = Qnil;
6212
6213 if (last_displayed_p)
6214 echo_area_buffer[1] = Qnil;
6215
6216 message_buf_print = 0;
6217}
6218
6219/* Clear garbaged frames.
6220
6221 This function is used where the old redisplay called
6222 redraw_garbaged_frames which in turn called redraw_frame which in
6223 turn called clear_frame. The call to clear_frame was a source of
6224 flickering. I believe a clear_frame is not necessary. It should
6225 suffice in the new redisplay to invalidate all current matrices,
6226 and ensure a complete redisplay of all windows. */
6227
6228static void
6229clear_garbaged_frames ()
6230{
5f5c8ee5
GM
6231 if (frame_garbaged)
6232 {
5f5c8ee5
GM
6233 Lisp_Object tail, frame;
6234
6235 FOR_EACH_FRAME (tail, frame)
6236 {
6237 struct frame *f = XFRAME (frame);
6238
6239 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
6240 {
6241 clear_current_matrices (f);
6242 f->garbaged = 0;
6243 }
6244 }
6245
6246 frame_garbaged = 0;
6247 ++windows_or_buffers_changed;
6248 }
c6e89d6c 6249}
5f5c8ee5 6250
5f5c8ee5 6251
886bd6f2
GM
6252/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
6253 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 6254 mini-windows height has been changed. */
5f5c8ee5 6255
c6e89d6c
GM
6256static int
6257echo_area_display (update_frame_p)
6258 int update_frame_p;
6259{
6260 Lisp_Object mini_window;
6261 struct window *w;
6262 struct frame *f;
6263 int window_height_changed_p = 0;
886bd6f2 6264 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 6265
886bd6f2 6266 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6267 w = XWINDOW (mini_window);
6268 f = XFRAME (WINDOW_FRAME (w));
6269
6270 /* Don't display if frame is invisible or not yet initialized. */
6271 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
6272 return 0;
5f5c8ee5 6273
1ab3e082 6274#ifdef HAVE_WINDOW_SYSTEM
c6e89d6c
GM
6275 /* When Emacs starts, selected_frame may be a visible terminal
6276 frame, even if we run under a window system. If we let this
6277 through, a message would be displayed on the terminal. */
622e3754
GM
6278 if (EQ (selected_frame, Vterminal_frame)
6279 && !NILP (Vwindow_system))
c6e89d6c 6280 return 0;
1ab3e082 6281#endif /* HAVE_WINDOW_SYSTEM */
c6e89d6c
GM
6282
6283 /* Redraw garbaged frames. */
6284 if (frame_garbaged)
6285 clear_garbaged_frames ();
6286
6287 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
6288 {
6289 echo_area_window = mini_window;
6290 window_height_changed_p = display_echo_area (w);
5f5c8ee5 6291 w->must_be_updated_p = 1;
c59c668a 6292
5f5c8ee5
GM
6293 if (update_frame_p)
6294 {
9f50252b
GM
6295 /* Not called from redisplay_internal. If we changed window
6296 configuration, we must redisplay thoroughly, of course.
6297
6298 Likewise if input is pending, because the pending input
6299 can have interrupted a previous redisplay, or redisplay
6300 wasn't called because of the pending input (see
6301 keyboard.c). In both cases, we would display the message
6302 fine, but the rest of the display would be garbage.
6303
6304 Otherwise, we can do with updating just what we displayed
c59c668a 6305 above. */
9f50252b
GM
6306
6307 if (window_height_changed_p || detect_input_pending ())
c59c668a 6308 {
9f50252b
GM
6309 int count = specpdl_ptr - specpdl;
6310
6311 specbind (Qredisplay_dont_pause, Qt);
c59c668a
GM
6312 ++windows_or_buffers_changed;
6313 ++update_mode_lines;
6314 redisplay_internal (0);
9f50252b 6315 unbind_to (count, Qnil);
c59c668a
GM
6316 }
6317 else if (FRAME_WINDOW_P (f))
5f5c8ee5
GM
6318 {
6319 update_single_window (w, 1);
6320 rif->flush_display (f);
6321 }
6322 else
6323 update_frame (f, 1, 1);
6324 }
6325 }
6326 else if (!EQ (mini_window, selected_window))
6327 windows_or_buffers_changed++;
c59c668a
GM
6328
6329 /* Last displayed message is now the current message. */
dd2eb166
GM
6330 echo_area_buffer[1] = echo_area_buffer[0];
6331
5f5c8ee5
GM
6332 /* Prevent redisplay optimization in redisplay_internal by resetting
6333 this_line_start_pos. This is done because the mini-buffer now
6334 displays the message instead of its buffer text. */
6335 if (EQ (mini_window, selected_window))
6336 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
6337
6338 return window_height_changed_p;
5f5c8ee5
GM
6339}
6340
6341
6342\f
6343/***********************************************************************
6344 Frame Titles
6345 ***********************************************************************/
6346
6347
6348#ifdef HAVE_WINDOW_SYSTEM
6349
6350/* A buffer for constructing frame titles in it; allocated from the
6351 heap in init_xdisp and resized as needed in store_frame_title_char. */
6352
6353static char *frame_title_buf;
6354
6355/* The buffer's end, and a current output position in it. */
6356
6357static char *frame_title_buf_end;
6358static char *frame_title_ptr;
6359
6360
6361/* Store a single character C for the frame title in frame_title_buf.
6362 Re-allocate frame_title_buf if necessary. */
6363
6364static void
6365store_frame_title_char (c)
6366 char c;
6367{
6368 /* If output position has reached the end of the allocated buffer,
6369 double the buffer's size. */
6370 if (frame_title_ptr == frame_title_buf_end)
6371 {
6372 int len = frame_title_ptr - frame_title_buf;
6373 int new_size = 2 * len * sizeof *frame_title_buf;
6374 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
6375 frame_title_buf_end = frame_title_buf + new_size;
6376 frame_title_ptr = frame_title_buf + len;
6377 }
6378
6379 *frame_title_ptr++ = c;
6380}
6381
6382
6383/* Store part of a frame title in frame_title_buf, beginning at
6384 frame_title_ptr. STR is the string to store. Do not copy more
6385 than PRECISION number of bytes from STR; PRECISION <= 0 means copy
6386 the whole string. Pad with spaces until FIELD_WIDTH number of
6387 characters have been copied; FIELD_WIDTH <= 0 means don't pad.
6388 Called from display_mode_element when it is used to build a frame
6389 title. */
6390
6391static int
6392store_frame_title (str, field_width, precision)
6393 unsigned char *str;
6394 int field_width, precision;
6395{
6396 int n = 0;
6397
6398 /* Copy at most PRECISION chars from STR. */
6399 while ((precision <= 0 || n < precision)
6400 && *str)
6401 {
6402 store_frame_title_char (*str++);
6403 ++n;
6404 }
6405
6406 /* Fill up with spaces until FIELD_WIDTH reached. */
6407 while (field_width > 0
6408 && n < field_width)
6409 {
6410 store_frame_title_char (' ');
6411 ++n;
6412 }
6413
6414 return n;
6415}
6416
6417
6418/* Set the title of FRAME, if it has changed. The title format is
6419 Vicon_title_format if FRAME is iconified, otherwise it is
6420 frame_title_format. */
6421
6422static void
6423x_consider_frame_title (frame)
6424 Lisp_Object frame;
6425{
6426 struct frame *f = XFRAME (frame);
6427
6428 if (FRAME_WINDOW_P (f)
6429 || FRAME_MINIBUF_ONLY_P (f)
6430 || f->explicit_name)
6431 {
6432 /* Do we have more than one visible frame on this X display? */
6433 Lisp_Object tail;
6434 Lisp_Object fmt;
6435 struct buffer *obuf;
6436 int len;
6437 struct it it;
6438
9472f927 6439 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 6440 {
9472f927 6441 struct frame *tf = XFRAME (XCAR (tail));
5f5c8ee5
GM
6442
6443 if (tf != f
6444 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
6445 && !FRAME_MINIBUF_ONLY_P (tf)
6446 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
6447 break;
6448 }
6449
6450 /* Set global variable indicating that multiple frames exist. */
6451 multiple_frames = CONSP (tail);
6452
6453 /* Switch to the buffer of selected window of the frame. Set up
6454 frame_title_ptr so that display_mode_element will output into it;
6455 then display the title. */
6456 obuf = current_buffer;
6457 Fset_buffer (XWINDOW (f->selected_window)->buffer);
6458 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
6459 frame_title_ptr = frame_title_buf;
6460 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
6461 NULL, DEFAULT_FACE_ID);
6462 len = display_mode_element (&it, 0, -1, -1, fmt);
6463 frame_title_ptr = NULL;
6464 set_buffer_internal (obuf);
6465
6466 /* Set the title only if it's changed. This avoids consing in
6467 the common case where it hasn't. (If it turns out that we've
6468 already wasted too much time by walking through the list with
6469 display_mode_element, then we might need to optimize at a
6470 higher level than this.) */
6471 if (! STRINGP (f->name)
6472 || STRING_BYTES (XSTRING (f->name)) != len
6473 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
6474 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
6475 }
6476}
6477
6478#else /* not HAVE_WINDOW_SYSTEM */
6479
6480#define frame_title_ptr ((char *)0)
6481#define store_frame_title(str, mincol, maxcol) 0
6482
6483#endif /* not HAVE_WINDOW_SYSTEM */
6484
6485
6486
6487\f
6488/***********************************************************************
6489 Menu Bars
6490 ***********************************************************************/
6491
6492
6493/* Prepare for redisplay by updating menu-bar item lists when
6494 appropriate. This can call eval. */
6495
6496void
6497prepare_menu_bars ()
6498{
6499 int all_windows;
6500 struct gcpro gcpro1, gcpro2;
6501 struct frame *f;
6502 struct frame *tooltip_frame;
6503
6504#ifdef HAVE_X_WINDOWS
6505 tooltip_frame = tip_frame;
6506#else
6507 tooltip_frame = NULL;
6508#endif
6509
6510 /* Update all frame titles based on their buffer names, etc. We do
6511 this before the menu bars so that the buffer-menu will show the
6512 up-to-date frame titles. */
6513#ifdef HAVE_WINDOW_SYSTEM
6514 if (windows_or_buffers_changed || update_mode_lines)
6515 {
6516 Lisp_Object tail, frame;
6517
6518 FOR_EACH_FRAME (tail, frame)
6519 {
6520 f = XFRAME (frame);
6521 if (f != tooltip_frame
6522 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
6523 x_consider_frame_title (frame);
6524 }
6525 }
6526#endif /* HAVE_WINDOW_SYSTEM */
6527
6528 /* Update the menu bar item lists, if appropriate. This has to be
6529 done before any actual redisplay or generation of display lines. */
6530 all_windows = (update_mode_lines
6531 || buffer_shared > 1
6532 || windows_or_buffers_changed);
6533 if (all_windows)
6534 {
6535 Lisp_Object tail, frame;
6536 int count = specpdl_ptr - specpdl;
6537
6538 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6539
6540 FOR_EACH_FRAME (tail, frame)
6541 {
6542 f = XFRAME (frame);
6543
6544 /* Ignore tooltip frame. */
6545 if (f == tooltip_frame)
6546 continue;
6547
6548 /* If a window on this frame changed size, report that to
6549 the user and clear the size-change flag. */
6550 if (FRAME_WINDOW_SIZES_CHANGED (f))
6551 {
6552 Lisp_Object functions;
6553
6554 /* Clear flag first in case we get an error below. */
6555 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
6556 functions = Vwindow_size_change_functions;
6557 GCPRO2 (tail, functions);
6558
6559 while (CONSP (functions))
6560 {
6561 call1 (XCAR (functions), frame);
6562 functions = XCDR (functions);
6563 }
6564 UNGCPRO;
6565 }
6566
6567 GCPRO1 (tail);
6568 update_menu_bar (f, 0);
6569#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 6570 update_tool_bar (f, 0);
5f5c8ee5
GM
6571#endif
6572 UNGCPRO;
6573 }
6574
6575 unbind_to (count, Qnil);
6576 }
6577 else
6578 {
886bd6f2
GM
6579 struct frame *sf = SELECTED_FRAME ();
6580 update_menu_bar (sf, 1);
5f5c8ee5 6581#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 6582 update_tool_bar (sf, 1);
5f5c8ee5
GM
6583#endif
6584 }
6585
6586 /* Motif needs this. See comment in xmenu.c. Turn it off when
6587 pending_menu_activation is not defined. */
6588#ifdef USE_X_TOOLKIT
6589 pending_menu_activation = 0;
6590#endif
6591}
6592
6593
6594/* Update the menu bar item list for frame F. This has to be done
6595 before we start to fill in any display lines, because it can call
6596 eval.
6597
6598 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
6599
6600static void
6601update_menu_bar (f, save_match_data)
6602 struct frame *f;
6603 int save_match_data;
6604{
6605 Lisp_Object window;
6606 register struct window *w;
6607
6608 window = FRAME_SELECTED_WINDOW (f);
6609 w = XWINDOW (window);
6610
6611 if (update_mode_lines)
6612 w->update_mode_line = Qt;
6613
6614 if (FRAME_WINDOW_P (f)
6615 ?
6616#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6617 FRAME_EXTERNAL_MENU_BAR (f)
6618#else
6619 FRAME_MENU_BAR_LINES (f) > 0
6620#endif
6621 : FRAME_MENU_BAR_LINES (f) > 0)
6622 {
6623 /* If the user has switched buffers or windows, we need to
6624 recompute to reflect the new bindings. But we'll
6625 recompute when update_mode_lines is set too; that means
6626 that people can use force-mode-line-update to request
6627 that the menu bar be recomputed. The adverse effect on
6628 the rest of the redisplay algorithm is about the same as
6629 windows_or_buffers_changed anyway. */
6630 if (windows_or_buffers_changed
6631 || !NILP (w->update_mode_line)
6632 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6633 < BUF_MODIFF (XBUFFER (w->buffer)))
6634 != !NILP (w->last_had_star))
6635 || ((!NILP (Vtransient_mark_mode)
6636 && !NILP (XBUFFER (w->buffer)->mark_active))
6637 != !NILP (w->region_showing)))
6638 {
6639 struct buffer *prev = current_buffer;
6640 int count = specpdl_ptr - specpdl;
6641
6642 set_buffer_internal_1 (XBUFFER (w->buffer));
6643 if (save_match_data)
6644 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6645 if (NILP (Voverriding_local_map_menu_flag))
6646 {
6647 specbind (Qoverriding_terminal_local_map, Qnil);
6648 specbind (Qoverriding_local_map, Qnil);
6649 }
6650
6651 /* Run the Lucid hook. */
6652 call1 (Vrun_hooks, Qactivate_menubar_hook);
6653
6654 /* If it has changed current-menubar from previous value,
6655 really recompute the menu-bar from the value. */
6656 if (! NILP (Vlucid_menu_bar_dirty_flag))
6657 call0 (Qrecompute_lucid_menubar);
6658
6659 safe_run_hooks (Qmenu_bar_update_hook);
6660 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
6661
6662 /* Redisplay the menu bar in case we changed it. */
6663#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6664 if (FRAME_WINDOW_P (f))
6665 set_frame_menubar (f, 0, 0);
6666 else
6667 /* On a terminal screen, the menu bar is an ordinary screen
6668 line, and this makes it get updated. */
6669 w->update_mode_line = Qt;
6670#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6671 /* In the non-toolkit version, the menu bar is an ordinary screen
6672 line, and this makes it get updated. */
6673 w->update_mode_line = Qt;
6674#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6675
6676 unbind_to (count, Qnil);
6677 set_buffer_internal_1 (prev);
6678 }
6679 }
6680}
6681
6682
6683\f
6684/***********************************************************************
e037b9ec 6685 Tool-bars
5f5c8ee5
GM
6686 ***********************************************************************/
6687
6688#ifdef HAVE_WINDOW_SYSTEM
6689
e037b9ec 6690/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
6691 before we start to fill in any display lines. Called from
6692 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
6693 and restore it here. */
6694
6695static void
e037b9ec 6696update_tool_bar (f, save_match_data)
5f5c8ee5
GM
6697 struct frame *f;
6698 int save_match_data;
6699{
e037b9ec
GM
6700 if (WINDOWP (f->tool_bar_window)
6701 && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
5f5c8ee5
GM
6702 {
6703 Lisp_Object window;
6704 struct window *w;
6705
6706 window = FRAME_SELECTED_WINDOW (f);
6707 w = XWINDOW (window);
6708
6709 /* If the user has switched buffers or windows, we need to
6710 recompute to reflect the new bindings. But we'll
6711 recompute when update_mode_lines is set too; that means
6712 that people can use force-mode-line-update to request
6713 that the menu bar be recomputed. The adverse effect on
6714 the rest of the redisplay algorithm is about the same as
6715 windows_or_buffers_changed anyway. */
6716 if (windows_or_buffers_changed
6717 || !NILP (w->update_mode_line)
6718 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6719 < BUF_MODIFF (XBUFFER (w->buffer)))
6720 != !NILP (w->last_had_star))
6721 || ((!NILP (Vtransient_mark_mode)
6722 && !NILP (XBUFFER (w->buffer)->mark_active))
6723 != !NILP (w->region_showing)))
6724 {
6725 struct buffer *prev = current_buffer;
6726 int count = specpdl_ptr - specpdl;
a2889657 6727
5f5c8ee5
GM
6728 /* Set current_buffer to the buffer of the selected
6729 window of the frame, so that we get the right local
6730 keymaps. */
6731 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 6732
5f5c8ee5
GM
6733 /* Save match data, if we must. */
6734 if (save_match_data)
6735 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6736
6737 /* Make sure that we don't accidentally use bogus keymaps. */
6738 if (NILP (Voverriding_local_map_menu_flag))
6739 {
6740 specbind (Qoverriding_terminal_local_map, Qnil);
6741 specbind (Qoverriding_local_map, Qnil);
1f40cad2 6742 }
1f40cad2 6743
e037b9ec
GM
6744 /* Build desired tool-bar items from keymaps. */
6745 f->desired_tool_bar_items
6746 = tool_bar_items (f->desired_tool_bar_items,
6747 &f->n_desired_tool_bar_items);
5f5c8ee5 6748
e037b9ec 6749 /* Redisplay the tool-bar in case we changed it. */
5f5c8ee5
GM
6750 w->update_mode_line = Qt;
6751
6752 unbind_to (count, Qnil);
6753 set_buffer_internal_1 (prev);
81d478f3 6754 }
a2889657
JB
6755 }
6756}
6757
6c4429a5 6758
e037b9ec
GM
6759/* Set F->desired_tool_bar_string to a Lisp string representing frame
6760 F's desired tool-bar contents. F->desired_tool_bar_items must have
5f5c8ee5
GM
6761 been set up previously by calling prepare_menu_bars. */
6762
a2889657 6763static void
e037b9ec 6764build_desired_tool_bar_string (f)
5f5c8ee5 6765 struct frame *f;
a2889657 6766{
5f5c8ee5
GM
6767 int i, size, size_needed, string_idx;
6768 struct gcpro gcpro1, gcpro2, gcpro3;
6769 Lisp_Object image, plist, props;
a2889657 6770
5f5c8ee5
GM
6771 image = plist = props = Qnil;
6772 GCPRO3 (image, plist, props);
a2889657 6773
e037b9ec 6774 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5
GM
6775 Otherwise, make a new string. */
6776
6777 /* The size of the string we might be able to reuse. */
e037b9ec
GM
6778 size = (STRINGP (f->desired_tool_bar_string)
6779 ? XSTRING (f->desired_tool_bar_string)->size
5f5c8ee5
GM
6780 : 0);
6781
6782 /* Each image in the string we build is preceded by a space,
6783 and there is a space at the end. */
e037b9ec 6784 size_needed = f->n_desired_tool_bar_items + 1;
5f5c8ee5 6785
e037b9ec 6786 /* Reuse f->desired_tool_bar_string, if possible. */
5f5c8ee5 6787 if (size < size_needed)
6fc556fd
KR
6788 f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
6789 make_number (' '));
5f5c8ee5
GM
6790 else
6791 {
6792 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
6793 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 6794 props, f->desired_tool_bar_string);
5f5c8ee5 6795 }
a2889657 6796
5f5c8ee5 6797 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
6798 put a `menu_item' property on tool-bar items with a value that
6799 is the index of the item in F's tool-bar item vector. */
5f5c8ee5 6800 for (i = 0, string_idx = 0;
e037b9ec 6801 i < f->n_desired_tool_bar_items;
5f5c8ee5 6802 ++i, string_idx += 1)
a2889657 6803 {
5f5c8ee5 6804#define PROP(IDX) \
e037b9ec
GM
6805 (XVECTOR (f->desired_tool_bar_items) \
6806 ->contents[i * TOOL_BAR_ITEM_NSLOTS + (IDX)])
5f5c8ee5 6807
e037b9ec
GM
6808 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
6809 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
5f5c8ee5
GM
6810 int margin, relief;
6811 extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
6812 extern Lisp_Object Qlaplace;
6813
6814 /* If image is a vector, choose the image according to the
6815 button state. */
e037b9ec 6816 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
6817 if (VECTORP (image))
6818 {
e037b9ec 6819 enum tool_bar_item_image idx;
5f5c8ee5
GM
6820
6821 if (enabled_p)
6822 idx = (selected_p
e037b9ec
GM
6823 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6824 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
6825 else
6826 idx = (selected_p
e037b9ec
GM
6827 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6828 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
5f5c8ee5
GM
6829
6830 xassert (XVECTOR (image)->size >= idx);
6831 image = XVECTOR (image)->contents[idx];
6832 }
6833
6834 /* Ignore invalid image specifications. */
6835 if (!valid_image_p (image))
6836 continue;
6837
e037b9ec 6838 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
6839 plist = Fcopy_sequence (XCDR (image));
6840
6841 /* Compute margin and relief to draw. */
e037b9ec
GM
6842 relief = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
6843 margin = relief + max (0, tool_bar_button_margin);
5f5c8ee5 6844
e037b9ec 6845 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
6846 {
6847 /* Add a `:relief' property to the image spec if the item is
6848 selected. */
6849 if (selected_p)
6850 {
6851 plist = Fplist_put (plist, QCrelief, make_number (-relief));
6852 margin -= relief;
6853 }
6854 }
6855 else
6856 {
6857 /* If image is selected, display it pressed, i.e. with a
6858 negative relief. If it's not selected, display it with a
6859 raised relief. */
6860 plist = Fplist_put (plist, QCrelief,
6861 (selected_p
6862 ? make_number (-relief)
6863 : make_number (relief)));
6864 margin -= relief;
6865 }
6866
6867 /* Put a margin around the image. */
6868 if (margin)
6869 plist = Fplist_put (plist, QCmargin, make_number (margin));
6870
6871 /* If button is not enabled, make the image appear disabled by
6872 applying an appropriate algorithm to it. */
6873 if (!enabled_p)
6874 plist = Fplist_put (plist, QCalgorithm, Qlaplace);
6875
6876 /* Put a `display' text property on the string for the image to
6877 display. Put a `menu-item' property on the string that gives
e037b9ec 6878 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
6879 vector. */
6880 image = Fcons (Qimage, plist);
6881 props = list4 (Qdisplay, image,
e037b9ec 6882 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)),
5f5c8ee5
GM
6883 Fadd_text_properties (make_number (string_idx),
6884 make_number (string_idx + 1),
e037b9ec 6885 props, f->desired_tool_bar_string);
5f5c8ee5 6886#undef PROP
a2889657
JB
6887 }
6888
5f5c8ee5
GM
6889 UNGCPRO;
6890}
6891
6892
e037b9ec 6893/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
6894
6895static void
e037b9ec 6896display_tool_bar_line (it)
5f5c8ee5
GM
6897 struct it *it;
6898{
6899 struct glyph_row *row = it->glyph_row;
6900 int max_x = it->last_visible_x;
6901 struct glyph *last;
6902
6903 prepare_desired_row (row);
6904 row->y = it->current_y;
6905
6906 while (it->current_x < max_x)
a2889657 6907 {
5f5c8ee5 6908 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 6909
5f5c8ee5
GM
6910 /* Get the next display element. */
6911 if (!get_next_display_element (it))
6912 break;
73af359d 6913
5f5c8ee5
GM
6914 /* Produce glyphs. */
6915 x_before = it->current_x;
6916 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
6917 PRODUCE_GLYPHS (it);
daa37602 6918
5f5c8ee5
GM
6919 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
6920 i = 0;
6921 x = x_before;
6922 while (i < nglyphs)
6923 {
6924 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
6925
6926 if (x + glyph->pixel_width > max_x)
6927 {
6928 /* Glyph doesn't fit on line. */
6929 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
6930 it->current_x = x;
6931 goto out;
6932 }
daa37602 6933
5f5c8ee5
GM
6934 ++it->hpos;
6935 x += glyph->pixel_width;
6936 ++i;
6937 }
6938
6939 /* Stop at line ends. */
6940 if (ITERATOR_AT_END_OF_LINE_P (it))
6941 break;
6942
6943 set_iterator_to_next (it);
a2889657 6944 }
a2889657 6945
5f5c8ee5 6946 out:;
a2889657 6947
5f5c8ee5
GM
6948 row->displays_text_p = row->used[TEXT_AREA] != 0;
6949 extend_face_to_end_of_line (it);
6950 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
6951 last->right_box_line_p = 1;
6952 compute_line_metrics (it);
6953
e037b9ec 6954 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
6955 if (!row->displays_text_p)
6956 {
312246d1
GM
6957 row->height = row->phys_height = it->last_visible_y - row->y;
6958 row->ascent = row->phys_ascent = 0;
5f5c8ee5
GM
6959 }
6960
6961 row->full_width_p = 1;
6962 row->continued_p = 0;
6963 row->truncated_on_left_p = 0;
6964 row->truncated_on_right_p = 0;
6965
6966 it->current_x = it->hpos = 0;
6967 it->current_y += row->height;
6968 ++it->vpos;
6969 ++it->glyph_row;
a2889657 6970}
96a410bc 6971
5f5c8ee5 6972
e037b9ec 6973/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 6974 items of frame F visible. */
96a410bc 6975
d39b6696 6976static int
e037b9ec 6977tool_bar_lines_needed (f)
5f5c8ee5 6978 struct frame *f;
d39b6696 6979{
e037b9ec 6980 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5
GM
6981 struct it it;
6982
e037b9ec
GM
6983 /* Initialize an iterator for iteration over
6984 F->desired_tool_bar_string in the tool-bar window of frame F. */
6985 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
6986 it.first_visible_x = 0;
6987 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
e037b9ec 6988 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
6989
6990 while (!ITERATOR_AT_END_P (&it))
6991 {
6992 it.glyph_row = w->desired_matrix->rows;
6993 clear_glyph_row (it.glyph_row);
e037b9ec 6994 display_tool_bar_line (&it);
5f5c8ee5
GM
6995 }
6996
6997 return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
d39b6696 6998}
96a410bc 6999
5f5c8ee5 7000
e037b9ec 7001/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
7002 height should be changed. */
7003
7004static int
e037b9ec 7005redisplay_tool_bar (f)
5f5c8ee5 7006 struct frame *f;
96a410bc 7007{
5f5c8ee5
GM
7008 struct window *w;
7009 struct it it;
7010 struct glyph_row *row;
7011 int change_height_p = 0;
7012
e037b9ec
GM
7013 /* If frame hasn't a tool-bar window or if it is zero-height, don't
7014 do anything. This means you must start with tool-bar-lines
5f5c8ee5 7015 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
7016 can turn off tool-bars by specifying tool-bar-lines zero. */
7017 if (!WINDOWP (f->tool_bar_window)
7018 || (w = XWINDOW (f->tool_bar_window),
5f5c8ee5
GM
7019 XFASTINT (w->height) == 0))
7020 return 0;
96a410bc 7021
e037b9ec
GM
7022 /* Set up an iterator for the tool-bar window. */
7023 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
7024 it.first_visible_x = 0;
7025 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
7026 row = it.glyph_row;
3450d04c 7027
e037b9ec
GM
7028 /* Build a string that represents the contents of the tool-bar. */
7029 build_desired_tool_bar_string (f);
7030 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 7031
e037b9ec 7032 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 7033 while (it.current_y < it.last_visible_y)
e037b9ec 7034 display_tool_bar_line (&it);
3450d04c 7035
e037b9ec 7036 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
7037 window, so don't do it. */
7038 w->desired_matrix->no_scrolling_p = 1;
7039 w->must_be_updated_p = 1;
3450d04c 7040
e037b9ec 7041 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
7042 {
7043 int nlines;
7044
7045 /* If there are blank lines at the end, except for a partially
7046 visible blank line at the end that is smaller than
e037b9ec 7047 CANON_Y_UNIT, change the tool-bar's height. */
5f5c8ee5
GM
7048 row = it.glyph_row - 1;
7049 if (!row->displays_text_p
7050 && row->height >= CANON_Y_UNIT (f))
7051 change_height_p = 1;
7052
e037b9ec
GM
7053 /* If row displays tool-bar items, but is partially visible,
7054 change the tool-bar's height. */
5f5c8ee5
GM
7055 if (row->displays_text_p
7056 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
7057 change_height_p = 1;
7058
e037b9ec 7059 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
7060 frame parameter. */
7061 if (change_height_p
e037b9ec 7062 && (nlines = tool_bar_lines_needed (f),
5f5c8ee5
GM
7063 nlines != XFASTINT (w->height)))
7064 {
e037b9ec 7065 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5
GM
7066 Lisp_Object frame;
7067
7068 XSETFRAME (frame, f);
7069 clear_glyph_matrix (w->desired_matrix);
7070 Fmodify_frame_parameters (frame,
e037b9ec 7071 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
7072 make_number (nlines)),
7073 Qnil));
7074 fonts_changed_p = 1;
7075 }
7076 }
3450d04c 7077
5f5c8ee5 7078 return change_height_p;
96a410bc 7079}
90adcf20 7080
5f5c8ee5 7081
e037b9ec
GM
7082/* Get information about the tool-bar item which is displayed in GLYPH
7083 on frame F. Return in *PROP_IDX the index where tool-bar item
7084 properties start in F->current_tool_bar_items. Value is zero if
7085 GLYPH doesn't display a tool-bar item. */
5f5c8ee5
GM
7086
7087int
e037b9ec 7088tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
7089 struct frame *f;
7090 struct glyph *glyph;
7091 int *prop_idx;
90adcf20 7092{
5f5c8ee5
GM
7093 Lisp_Object prop;
7094 int success_p;
7095
7096 /* Get the text property `menu-item' at pos. The value of that
7097 property is the start index of this item's properties in
e037b9ec 7098 F->current_tool_bar_items. */
5f5c8ee5 7099 prop = Fget_text_property (make_number (glyph->charpos),
e037b9ec 7100 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
7101 if (INTEGERP (prop))
7102 {
7103 *prop_idx = XINT (prop);
7104 success_p = 1;
7105 }
7106 else
7107 success_p = 0;
90adcf20 7108
5f5c8ee5
GM
7109 return success_p;
7110}
7111
7112#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 7113
feb0c42f 7114
5f5c8ee5
GM
7115\f
7116/************************************************************************
7117 Horizontal scrolling
7118 ************************************************************************/
feb0c42f 7119
5f5c8ee5
GM
7120static int hscroll_window_tree P_ ((Lisp_Object));
7121static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 7122
5f5c8ee5
GM
7123/* For all leaf windows in the window tree rooted at WINDOW, set their
7124 hscroll value so that PT is (i) visible in the window, and (ii) so
7125 that it is not within a certain margin at the window's left and
7126 right border. Value is non-zero if any window's hscroll has been
7127 changed. */
7128
7129static int
7130hscroll_window_tree (window)
7131 Lisp_Object window;
7132{
7133 int hscrolled_p = 0;
7134
7135 while (WINDOWP (window))
90adcf20 7136 {
5f5c8ee5
GM
7137 struct window *w = XWINDOW (window);
7138
7139 if (WINDOWP (w->hchild))
7140 hscrolled_p |= hscroll_window_tree (w->hchild);
7141 else if (WINDOWP (w->vchild))
7142 hscrolled_p |= hscroll_window_tree (w->vchild);
7143 else if (w->cursor.vpos >= 0)
7144 {
7145 int hscroll_margin, text_area_x, text_area_y;
7146 int text_area_width, text_area_height;
92a90e89
GM
7147 struct glyph_row *current_cursor_row
7148 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
7149 struct glyph_row *desired_cursor_row
7150 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
7151 struct glyph_row *cursor_row
7152 = (desired_cursor_row->enabled_p
7153 ? desired_cursor_row
7154 : current_cursor_row);
a2725ab2 7155
5f5c8ee5
GM
7156 window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
7157 &text_area_width, &text_area_height);
90adcf20 7158
5f5c8ee5
GM
7159 /* Scroll when cursor is inside this scroll margin. */
7160 hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
7161
7162 if ((XFASTINT (w->hscroll)
7163 && w->cursor.x < hscroll_margin)
92a90e89
GM
7164 || (cursor_row->enabled_p
7165 && cursor_row->truncated_on_right_p
5f5c8ee5 7166 && (w->cursor.x > text_area_width - hscroll_margin)))
08b610e4 7167 {
5f5c8ee5
GM
7168 struct it it;
7169 int hscroll;
7170 struct buffer *saved_current_buffer;
7171 int pt;
7172
7173 /* Find point in a display of infinite width. */
7174 saved_current_buffer = current_buffer;
7175 current_buffer = XBUFFER (w->buffer);
7176
7177 if (w == XWINDOW (selected_window))
7178 pt = BUF_PT (current_buffer);
7179 else
08b610e4 7180 {
5f5c8ee5
GM
7181 pt = marker_position (w->pointm);
7182 pt = max (BEGV, pt);
7183 pt = min (ZV, pt);
7184 }
7185
7186 /* Move iterator to pt starting at cursor_row->start in
7187 a line with infinite width. */
7188 init_to_row_start (&it, w, cursor_row);
7189 it.last_visible_x = INFINITY;
7190 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
7191 current_buffer = saved_current_buffer;
7192
7193 /* Center cursor in window. */
7194 hscroll = (max (0, it.current_x - text_area_width / 2)
7195 / CANON_X_UNIT (it.f));
7196
7197 /* Don't call Fset_window_hscroll if value hasn't
7198 changed because it will prevent redisplay
7199 optimizations. */
7200 if (XFASTINT (w->hscroll) != hscroll)
7201 {
7202 Fset_window_hscroll (window, make_number (hscroll));
7203 hscrolled_p = 1;
08b610e4 7204 }
08b610e4 7205 }
08b610e4 7206 }
a2725ab2 7207
5f5c8ee5 7208 window = w->next;
90adcf20 7209 }
cd6dfed6 7210
5f5c8ee5
GM
7211 /* Value is non-zero if hscroll of any leaf window has been changed. */
7212 return hscrolled_p;
7213}
7214
7215
7216/* Set hscroll so that cursor is visible and not inside horizontal
7217 scroll margins for all windows in the tree rooted at WINDOW. See
7218 also hscroll_window_tree above. Value is non-zero if any window's
7219 hscroll has been changed. If it has, desired matrices on the frame
7220 of WINDOW are cleared. */
7221
7222static int
7223hscroll_windows (window)
7224 Lisp_Object window;
7225{
d475bcb8
GM
7226 int hscrolled_p;
7227
7228 if (automatic_hscrolling_p)
7229 {
7230 hscrolled_p = hscroll_window_tree (window);
7231 if (hscrolled_p)
7232 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
7233 }
7234 else
7235 hscrolled_p = 0;
5f5c8ee5 7236 return hscrolled_p;
90adcf20 7237}
5f5c8ee5
GM
7238
7239
90adcf20 7240\f
5f5c8ee5
GM
7241/************************************************************************
7242 Redisplay
7243 ************************************************************************/
7244
7245/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
7246 to a non-zero value. This is sometimes handy to have in a debugger
7247 session. */
7248
7249#if GLYPH_DEBUG
a2889657 7250
5f5c8ee5
GM
7251/* First and last unchanged row for try_window_id. */
7252
7253int debug_first_unchanged_at_end_vpos;
7254int debug_last_unchanged_at_beg_vpos;
7255
7256/* Delta vpos and y. */
7257
7258int debug_dvpos, debug_dy;
7259
7260/* Delta in characters and bytes for try_window_id. */
7261
7262int debug_delta, debug_delta_bytes;
7263
7264/* Values of window_end_pos and window_end_vpos at the end of
7265 try_window_id. */
7266
7267int debug_end_pos, debug_end_vpos;
7268
7269/* Append a string to W->desired_matrix->method. FMT is a printf
7270 format string. A1...A9 are a supplement for a variable-length
7271 argument list. If trace_redisplay_p is non-zero also printf the
7272 resulting string to stderr. */
7273
7274static void
7275debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
7276 struct window *w;
7277 char *fmt;
7278 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
7279{
7280 char buffer[512];
7281 char *method = w->desired_matrix->method;
7282 int len = strlen (method);
7283 int size = sizeof w->desired_matrix->method;
7284 int remaining = size - len - 1;
7285
7286 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
7287 if (len && remaining)
7288 {
7289 method[len] = '|';
7290 --remaining, ++len;
7291 }
7292
7293 strncpy (method + len, buffer, remaining);
7294
7295 if (trace_redisplay_p)
7296 fprintf (stderr, "%p (%s): %s\n",
7297 w,
7298 ((BUFFERP (w->buffer)
7299 && STRINGP (XBUFFER (w->buffer)->name))
7300 ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
7301 : "no buffer"),
7302 buffer);
7303}
a2889657 7304
5f5c8ee5 7305#endif /* GLYPH_DEBUG */
90adcf20 7306
a2889657 7307
5f5c8ee5
GM
7308/* This counter is used to clear the face cache every once in a while
7309 in redisplay_internal. It is incremented for each redisplay.
7310 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
7311 cleared. */
0d231165 7312
5f5c8ee5 7313#define CLEAR_FACE_CACHE_COUNT 10000
463f6b91
RS
7314static int clear_face_cache_count;
7315
20de20dc 7316/* Record the previous terminal frame we displayed. */
5f5c8ee5
GM
7317
7318static struct frame *previous_terminal_frame;
7319
7320/* Non-zero while redisplay_internal is in progress. */
7321
7322int redisplaying_p;
7323
7324
7325/* Value is non-zero if all changes in window W, which displays
7326 current_buffer, are in the text between START and END. START is a
7327 buffer position, END is given as a distance from Z. Used in
7328 redisplay_internal for display optimization. */
7329
7330static INLINE int
7331text_outside_line_unchanged_p (w, start, end)
7332 struct window *w;
7333 int start, end;
7334{
7335 int unchanged_p = 1;
7336
7337 /* If text or overlays have changed, see where. */
7338 if (XFASTINT (w->last_modified) < MODIFF
7339 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
7340 {
7341 /* Gap in the line? */
7342 if (GPT < start || Z - GPT < end)
7343 unchanged_p = 0;
7344
7345 /* Changes start in front of the line, or end after it? */
7346 if (unchanged_p
9142dd5b
GM
7347 && (BEG_UNCHANGED < start - 1
7348 || END_UNCHANGED < end))
5f5c8ee5
GM
7349 unchanged_p = 0;
7350
7351 /* If selective display, can't optimize if changes start at the
7352 beginning of the line. */
7353 if (unchanged_p
7354 && INTEGERP (current_buffer->selective_display)
7355 && XINT (current_buffer->selective_display) > 0
9142dd5b 7356 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5
GM
7357 unchanged_p = 0;
7358 }
7359
7360 return unchanged_p;
7361}
7362
7363
7364/* Do a frame update, taking possible shortcuts into account. This is
7365 the main external entry point for redisplay.
7366
7367 If the last redisplay displayed an echo area message and that message
7368 is no longer requested, we clear the echo area or bring back the
7369 mini-buffer if that is in use. */
20de20dc 7370
a2889657
JB
7371void
7372redisplay ()
e9874cee
RS
7373{
7374 redisplay_internal (0);
7375}
7376
260a86a0
KH
7377/* Return 1 if point moved out of or into a composition. Otherwise
7378 return 0. PREV_BUF and PREV_PT are the last point buffer and
7379 position. BUF and PT are the current point buffer and position. */
7380
7381int
7382check_point_in_composition (prev_buf, prev_pt, buf, pt)
7383 struct buffer *prev_buf, *buf;
7384 int prev_pt, pt;
7385{
7386 int start, end;
7387 Lisp_Object prop;
7388 Lisp_Object buffer;
7389
7390 XSETBUFFER (buffer, buf);
7391 /* Check a composition at the last point if point moved within the
7392 same buffer. */
7393 if (prev_buf == buf)
7394 {
7395 if (prev_pt == pt)
7396 /* Point didn't move. */
7397 return 0;
7398
7399 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
7400 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
7401 && COMPOSITION_VALID_P (start, end, prop)
7402 && start < prev_pt && end > prev_pt)
7403 /* The last point was within the composition. Return 1 iff
7404 point moved out of the composition. */
7405 return (pt <= start || pt >= end);
7406 }
7407
7408 /* Check a composition at the current point. */
7409 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
7410 && find_composition (pt, -1, &start, &end, &prop, buffer)
7411 && COMPOSITION_VALID_P (start, end, prop)
7412 && start < pt && end > pt);
7413}
5f5c8ee5 7414
9142dd5b
GM
7415/* Reconsider the setting of B->clip_changed which is displayed
7416 in window W. */
7417
7418static INLINE void
7419reconsider_clip_changes (w, b)
7420 struct window *w;
7421 struct buffer *b;
7422{
7423 if (b->prevent_redisplay_optimizations_p)
7424 b->clip_changed = 1;
7425 else if (b->clip_changed
7426 && !NILP (w->window_end_valid)
7427 && w->current_matrix->buffer == b
7428 && w->current_matrix->zv == BUF_ZV (b)
7429 && w->current_matrix->begv == BUF_BEGV (b))
7430 b->clip_changed = 0;
260a86a0
KH
7431
7432 /* If display wasn't paused, and W is not a tool bar window, see if
7433 point has been moved into or out of a composition. In that case,
7434 we set b->clip_changed to 1 to force updating the screen. If
7435 b->clip_changed has already been set to 1, we can skip this
7436 check. */
7437 if (!b->clip_changed
7438 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
7439 {
7440 int pt;
7441
7442 if (w == XWINDOW (selected_window))
7443 pt = BUF_PT (current_buffer);
7444 else
7445 pt = marker_position (w->pointm);
7446
7447 if ((w->current_matrix->buffer != XBUFFER (w->buffer)
6fc556fd 7448 || pt != XINT (w->last_point))
260a86a0 7449 && check_point_in_composition (w->current_matrix->buffer,
6fc556fd 7450 XINT (w->last_point),
260a86a0
KH
7451 XBUFFER (w->buffer), pt))
7452 b->clip_changed = 1;
7453 }
9142dd5b
GM
7454}
7455
7456
5f5c8ee5
GM
7457/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
7458 response to any user action; therefore, we should preserve the echo
7459 area. (Actually, our caller does that job.) Perhaps in the future
7460 avoid recentering windows if it is not necessary; currently that
7461 causes some problems. */
e9874cee
RS
7462
7463static void
7464redisplay_internal (preserve_echo_area)
7465 int preserve_echo_area;
a2889657 7466{
5f5c8ee5
GM
7467 struct window *w = XWINDOW (selected_window);
7468 struct frame *f = XFRAME (w->frame);
7469 int pause;
a2889657 7470 int must_finish = 0;
5f5c8ee5 7471 struct text_pos tlbufpos, tlendpos;
89819bdd 7472 int number_of_visible_frames;
28514cd9 7473 int count;
886bd6f2 7474 struct frame *sf = SELECTED_FRAME ();
a2889657 7475
5f5c8ee5
GM
7476 /* Non-zero means redisplay has to consider all windows on all
7477 frames. Zero means, only selected_window is considered. */
7478 int consider_all_windows_p;
7479
7480 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
7481
7482 /* No redisplay if running in batch mode or frame is not yet fully
7483 initialized, or redisplay is explicitly turned off by setting
7484 Vinhibit_redisplay. */
7485 if (noninteractive
7486 || !NILP (Vinhibit_redisplay)
7487 || !f->glyphs_initialized_p)
a2889657
JB
7488 return;
7489
5f5c8ee5
GM
7490 /* The flag redisplay_performed_directly_p is set by
7491 direct_output_for_insert when it already did the whole screen
7492 update necessary. */
7493 if (redisplay_performed_directly_p)
7494 {
7495 redisplay_performed_directly_p = 0;
7496 if (!hscroll_windows (selected_window))
7497 return;
7498 }
7499
15f0cf78
RS
7500#ifdef USE_X_TOOLKIT
7501 if (popup_activated ())
7502 return;
7503#endif
7504
28514cd9 7505 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 7506 if (redisplaying_p)
735c094c
KH
7507 return;
7508
28514cd9
GM
7509 /* Record a function that resets redisplaying_p to its old value
7510 when we leave this function. */
7511 count = specpdl_ptr - specpdl;
7512 record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
7513 ++redisplaying_p;
7514
8b32d885 7515 retry:
bd9d0f3f 7516 pause = 0;
9142dd5b
GM
7517 reconsider_clip_changes (w, current_buffer);
7518
5f5c8ee5
GM
7519 /* If new fonts have been loaded that make a glyph matrix adjustment
7520 necessary, do it. */
7521 if (fonts_changed_p)
7522 {
7523 adjust_glyphs (NULL);
7524 ++windows_or_buffers_changed;
7525 fonts_changed_p = 0;
7526 }
7527
886bd6f2
GM
7528 if (! FRAME_WINDOW_P (sf)
7529 && previous_terminal_frame != sf)
20de20dc 7530 {
5f5c8ee5
GM
7531 /* Since frames on an ASCII terminal share the same display
7532 area, displaying a different frame means redisplay the whole
7533 thing. */
20de20dc 7534 windows_or_buffers_changed++;
886bd6f2
GM
7535 SET_FRAME_GARBAGED (sf);
7536 XSETFRAME (Vterminal_frame, sf);
20de20dc 7537 }
886bd6f2 7538 previous_terminal_frame = sf;
20de20dc 7539
5f5c8ee5
GM
7540 /* Set the visible flags for all frames. Do this before checking
7541 for resized or garbaged frames; they want to know if their frames
7542 are visible. See the comment in frame.h for
7543 FRAME_SAMPLE_VISIBILITY. */
d724d989 7544 {
35f56f96 7545 Lisp_Object tail, frame;
d724d989 7546
89819bdd
RS
7547 number_of_visible_frames = 0;
7548
35f56f96 7549 FOR_EACH_FRAME (tail, frame)
f82aff7c 7550 {
5f5c8ee5
GM
7551 struct frame *f = XFRAME (frame);
7552
7553 FRAME_SAMPLE_VISIBILITY (f);
7554 if (FRAME_VISIBLE_P (f))
7555 ++number_of_visible_frames;
7556 clear_desired_matrices (f);
f82aff7c 7557 }
d724d989
JB
7558 }
7559
44fa5b1e 7560 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 7561 do_pending_window_change (1);
a2889657 7562
5f5c8ee5 7563 /* Clear frames marked as garbaged. */
44fa5b1e 7564 if (frame_garbaged)
c6e89d6c 7565 clear_garbaged_frames ();
a2889657 7566
e037b9ec 7567 /* Build menubar and tool-bar items. */
f82aff7c
RS
7568 prepare_menu_bars ();
7569
28995e67 7570 if (windows_or_buffers_changed)
a2889657
JB
7571 update_mode_lines++;
7572
538f13d4
RS
7573 /* Detect case that we need to write or remove a star in the mode line. */
7574 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
7575 {
7576 w->update_mode_line = Qt;
7577 if (buffer_shared > 1)
7578 update_mode_lines++;
7579 }
7580
5f5c8ee5 7581 /* If %c is in the mode line, update it if needed. */
28995e67
RS
7582 if (!NILP (w->column_number_displayed)
7583 /* This alternative quickly identifies a common case
7584 where no change is needed. */
7585 && !(PT == XFASTINT (w->last_point)
8850a573
RS
7586 && XFASTINT (w->last_modified) >= MODIFF
7587 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
7588 && XFASTINT (w->column_number_displayed) != current_column ())
7589 w->update_mode_line = Qt;
7590
44fa5b1e 7591 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 7592
5f5c8ee5
GM
7593 /* The variable buffer_shared is set in redisplay_window and
7594 indicates that we redisplay a buffer in different windows. See
7595 there. */
7596 consider_all_windows_p = update_mode_lines || buffer_shared > 1;
a2889657
JB
7597
7598 /* If specs for an arrow have changed, do thorough redisplay
7599 to ensure we remove any arrow that should no longer exist. */
d45de95b 7600 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 7601 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 7602 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 7603
90adcf20
RS
7604 /* Normally the message* functions will have already displayed and
7605 updated the echo area, but the frame may have been trashed, or
7606 the update may have been preempted, so display the echo area
c6e89d6c
GM
7607 again here. Checking both message buffers captures the case that
7608 the echo area should be cleared. */
7609 if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
90adcf20 7610 {
c6e89d6c 7611 int window_height_changed_p = echo_area_display (0);
90adcf20 7612 must_finish = 1;
dd2eb166 7613
c6e89d6c
GM
7614 if (fonts_changed_p)
7615 goto retry;
7616 else if (window_height_changed_p)
7617 {
7618 consider_all_windows_p = 1;
7619 ++update_mode_lines;
7620 ++windows_or_buffers_changed;
9142dd5b
GM
7621
7622 /* If window configuration was changed, frames may have been
7623 marked garbaged. Clear them or we will experience
7624 surprises wrt scrolling. */
7625 if (frame_garbaged)
7626 clear_garbaged_frames ();
c6e89d6c 7627 }
90adcf20 7628 }
97a36635 7629 else if (EQ (selected_window, minibuf_window)
dd2eb166
GM
7630 && (current_buffer->clip_changed
7631 || XFASTINT (w->last_modified) < MODIFF
7632 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 7633 && resize_mini_window (w, 0))
c6e89d6c
GM
7634 {
7635 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
7636 showing if its contents might have changed. */
7637 must_finish = 1;
7638 consider_all_windows_p = 1;
c6e89d6c 7639 ++windows_or_buffers_changed;
dd2eb166 7640 ++update_mode_lines;
9142dd5b
GM
7641
7642 /* If window configuration was changed, frames may have been
7643 marked garbaged. Clear them or we will experience
7644 surprises wrt scrolling. */
7645 if (frame_garbaged)
7646 clear_garbaged_frames ();
c6e89d6c
GM
7647 }
7648
90adcf20 7649
5f5c8ee5
GM
7650 /* If showing the region, and mark has changed, we must redisplay
7651 the whole window. The assignment to this_line_start_pos prevents
7652 the optimization directly below this if-statement. */
bd66d1ba
RS
7653 if (((!NILP (Vtransient_mark_mode)
7654 && !NILP (XBUFFER (w->buffer)->mark_active))
7655 != !NILP (w->region_showing))
82d04750
JB
7656 || (!NILP (w->region_showing)
7657 && !EQ (w->region_showing,
7658 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
7659 CHARPOS (this_line_start_pos) = 0;
7660
7661 /* Optimize the case that only the line containing the cursor in the
7662 selected window has changed. Variables starting with this_ are
7663 set in display_line and record information about the line
7664 containing the cursor. */
7665 tlbufpos = this_line_start_pos;
7666 tlendpos = this_line_end_pos;
7667 if (!consider_all_windows_p
7668 && CHARPOS (tlbufpos) > 0
7669 && NILP (w->update_mode_line)
73af359d 7670 && !current_buffer->clip_changed
44fa5b1e 7671 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 7672 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 7673 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
7674 && this_line_buffer == current_buffer
7675 && current_buffer == XBUFFER (w->buffer)
265a9e55 7676 && NILP (w->force_start)
5f5c8ee5
GM
7677 /* Point must be on the line that we have info recorded about. */
7678 && PT >= CHARPOS (tlbufpos)
7679 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
7680 /* All text outside that line, including its final newline,
7681 must be unchanged */
5f5c8ee5
GM
7682 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
7683 CHARPOS (tlendpos)))
7684 {
7685 if (CHARPOS (tlbufpos) > BEGV
7686 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
7687 && (CHARPOS (tlbufpos) == ZV
7688 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
7689 /* Former continuation line has disappeared by becoming empty */
7690 goto cancel;
7691 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 7692 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
7693 || MINI_WINDOW_P (w))
7694 {
1c9241f5
KH
7695 /* We have to handle the case of continuation around a
7696 wide-column character (See the comment in indent.c around
7697 line 885).
7698
7699 For instance, in the following case:
7700
7701 -------- Insert --------
7702 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
7703 J_I_ ==> J_I_ `^^' are cursors.
7704 ^^ ^^
7705 -------- --------
7706
7707 As we have to redraw the line above, we should goto cancel. */
7708
5f5c8ee5
GM
7709 struct it it;
7710 int line_height_before = this_line_pixel_height;
7711
7712 /* Note that start_display will handle the case that the
7713 line starting at tlbufpos is a continuation lines. */
7714 start_display (&it, w, tlbufpos);
7715
7716 /* Implementation note: It this still necessary? */
7717 if (it.current_x != this_line_start_x)
1c9241f5
KH
7718 goto cancel;
7719
5f5c8ee5
GM
7720 TRACE ((stderr, "trying display optimization 1\n"));
7721 w->cursor.vpos = -1;
a2889657 7722 overlay_arrow_seen = 0;
5f5c8ee5
GM
7723 it.vpos = this_line_vpos;
7724 it.current_y = this_line_y;
7725 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
7726 display_line (&it);
7727
a2889657 7728 /* If line contains point, is not continued,
5f5c8ee5
GM
7729 and ends at same distance from eob as before, we win */
7730 if (w->cursor.vpos >= 0
7731 /* Line is not continued, otherwise this_line_start_pos
7732 would have been set to 0 in display_line. */
7733 && CHARPOS (this_line_start_pos)
7734 /* Line ends as before. */
7735 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
7736 /* Line has same height as before. Otherwise other lines
7737 would have to be shifted up or down. */
7738 && this_line_pixel_height == line_height_before)
a2889657 7739 {
5f5c8ee5
GM
7740 /* If this is not the window's last line, we must adjust
7741 the charstarts of the lines below. */
7742 if (it.current_y < it.last_visible_y)
7743 {
7744 struct glyph_row *row
7745 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
7746 int delta, delta_bytes;
7747
7748 if (Z - CHARPOS (tlendpos) == ZV)
7749 {
7750 /* This line ends at end of (accessible part of)
7751 buffer. There is no newline to count. */
7752 delta = (Z
7753 - CHARPOS (tlendpos)
7754 - MATRIX_ROW_START_CHARPOS (row));
7755 delta_bytes = (Z_BYTE
7756 - BYTEPOS (tlendpos)
7757 - MATRIX_ROW_START_BYTEPOS (row));
7758 }
7759 else
7760 {
7761 /* This line ends in a newline. Must take
7762 account of the newline and the rest of the
7763 text that follows. */
7764 delta = (Z
7765 - CHARPOS (tlendpos)
7766 - MATRIX_ROW_START_CHARPOS (row));
7767 delta_bytes = (Z_BYTE
7768 - BYTEPOS (tlendpos)
7769 - MATRIX_ROW_START_BYTEPOS (row));
7770 }
7771
f2d86d7a
GM
7772 increment_matrix_positions (w->current_matrix,
7773 this_line_vpos + 1,
7774 w->current_matrix->nrows,
7775 delta, delta_bytes);
85bcef6c 7776 }
46db8486 7777
5f5c8ee5
GM
7778 /* If this row displays text now but previously didn't,
7779 or vice versa, w->window_end_vpos may have to be
7780 adjusted. */
7781 if ((it.glyph_row - 1)->displays_text_p)
7782 {
7783 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
7784 XSETINT (w->window_end_vpos, this_line_vpos);
7785 }
7786 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
7787 && this_line_vpos > 0)
7788 XSETINT (w->window_end_vpos, this_line_vpos - 1);
7789 w->window_end_valid = Qnil;
7790
7791 /* Update hint: No need to try to scroll in update_window. */
7792 w->desired_matrix->no_scrolling_p = 1;
7793
7794#if GLYPH_DEBUG
7795 *w->desired_matrix->method = 0;
7796 debug_method_add (w, "optimization 1");
7797#endif
a2889657
JB
7798 goto update;
7799 }
7800 else
7801 goto cancel;
7802 }
5f5c8ee5
GM
7803 else if (/* Cursor position hasn't changed. */
7804 PT == XFASTINT (w->last_point)
b6f0fe04
RS
7805 /* Make sure the cursor was last displayed
7806 in this window. Otherwise we have to reposition it. */
5f5c8ee5
GM
7807 && 0 <= w->cursor.vpos
7808 && XINT (w->height) > w->cursor.vpos)
a2889657
JB
7809 {
7810 if (!must_finish)
7811 {
c6e89d6c 7812 do_pending_window_change (1);
5f5c8ee5
GM
7813
7814 /* We used to always goto end_of_redisplay here, but this
7815 isn't enough if we have a blinking cursor. */
7816 if (w->cursor_off_p == w->last_cursor_off_p)
7817 goto end_of_redisplay;
a2889657
JB
7818 }
7819 goto update;
7820 }
8b51f1e3
KH
7821 /* If highlighting the region, or if the cursor is in the echo area,
7822 then we can't just move the cursor. */
bd66d1ba
RS
7823 else if (! (!NILP (Vtransient_mark_mode)
7824 && !NILP (current_buffer->mark_active))
97a36635 7825 && (EQ (selected_window, current_buffer->last_selected_window)
293a54ce 7826 || highlight_nonselected_windows)
8b51f1e3 7827 && NILP (w->region_showing)
8f897821 7828 && NILP (Vshow_trailing_whitespace)
8b51f1e3 7829 && !cursor_in_echo_area)
a2889657 7830 {
5f5c8ee5
GM
7831 struct it it;
7832 struct glyph_row *row;
7833
7834 /* Skip from tlbufpos to PT and see where it is. Note that
7835 PT may be in invisible text. If so, we will end at the
7836 next visible position. */
7837 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
7838 NULL, DEFAULT_FACE_ID);
7839 it.current_x = this_line_start_x;
7840 it.current_y = this_line_y;
7841 it.vpos = this_line_vpos;
7842
7843 /* The call to move_it_to stops in front of PT, but
7844 moves over before-strings. */
7845 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
7846
7847 if (it.vpos == this_line_vpos
7848 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
7849 row->enabled_p))
a2889657 7850 {
5f5c8ee5
GM
7851 xassert (this_line_vpos == it.vpos);
7852 xassert (this_line_y == it.current_y);
7853 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
a2889657
JB
7854 goto update;
7855 }
7856 else
7857 goto cancel;
7858 }
5f5c8ee5 7859
a2889657 7860 cancel:
5f5c8ee5
GM
7861 /* Text changed drastically or point moved off of line. */
7862 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
7863 }
7864
5f5c8ee5
GM
7865 CHARPOS (this_line_start_pos) = 0;
7866 consider_all_windows_p |= buffer_shared > 1;
7867 ++clear_face_cache_count;
a2889657 7868
5f5c8ee5 7869
bd9d0f3f
GM
7870 /* Build desired matrices, and update the display. If
7871 consider_all_windows_p is non-zero, do it for all windows on all
7872 frames. Otherwise do it for selected_window, only. */
463f6b91 7873
5f5c8ee5 7874 if (consider_all_windows_p)
a2889657 7875 {
35f56f96 7876 Lisp_Object tail, frame;
a2889657 7877
5f5c8ee5
GM
7878 /* Clear the face cache eventually. */
7879 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 7880 {
5f5c8ee5 7881 clear_face_cache (0);
463f6b91
RS
7882 clear_face_cache_count = 0;
7883 }
31b24551 7884
5f5c8ee5
GM
7885 /* Recompute # windows showing selected buffer. This will be
7886 incremented each time such a window is displayed. */
a2889657
JB
7887 buffer_shared = 0;
7888
35f56f96 7889 FOR_EACH_FRAME (tail, frame)
30c566e4 7890 {
5f5c8ee5 7891 struct frame *f = XFRAME (frame);
bd9d0f3f 7892
886bd6f2 7893 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 7894 {
5f5c8ee5
GM
7895 /* Mark all the scroll bars to be removed; we'll redeem
7896 the ones we want when we redisplay their windows. */
9769686d
RS
7897 if (condemn_scroll_bars_hook)
7898 (*condemn_scroll_bars_hook) (f);
30c566e4 7899
f21ef775 7900 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 7901 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 7902
5f5c8ee5
GM
7903 /* Any scroll bars which redisplay_windows should have
7904 nuked should now go away. */
9769686d
RS
7905 if (judge_scroll_bars_hook)
7906 (*judge_scroll_bars_hook) (f);
bd9d0f3f
GM
7907
7908 /* If fonts changed, display again. */
7909 if (fonts_changed_p)
7910 goto retry;
7911
7912 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
7913 {
7914 /* See if we have to hscroll. */
7915 if (hscroll_windows (f->root_window))
7916 goto retry;
7917
7918 /* Prevent various kinds of signals during display
7919 update. stdio is not robust about handling
7920 signals, which can cause an apparent I/O
7921 error. */
7922 if (interrupt_input)
7923 unrequest_sigio ();
7924 stop_polling ();
7925
7926 /* Update the display. */
7927 set_window_update_flags (XWINDOW (f->root_window), 1);
7928 pause |= update_frame (f, 0, 0);
7929 if (pause)
7930 break;
7931
7932 mark_window_display_accurate (f->root_window, 1);
7933 if (frame_up_to_date_hook)
7934 frame_up_to_date_hook (f);
7935 }
9769686d 7936 }
30c566e4 7937 }
a2889657 7938 }
bd9d0f3f
GM
7939 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
7940 {
7941 Lisp_Object mini_window;
7942 struct frame *mini_frame;
5f5c8ee5 7943
bd9d0f3f 7944 redisplay_window (selected_window, 1);
5f5c8ee5 7945
bd9d0f3f
GM
7946 /* Compare desired and current matrices, perform output. */
7947 update:
5f5c8ee5 7948
bd9d0f3f
GM
7949 /* If fonts changed, display again. */
7950 if (fonts_changed_p)
92a90e89 7951 goto retry;
a2889657 7952
bd9d0f3f
GM
7953 /* Prevent various kinds of signals during display update.
7954 stdio is not robust about handling signals,
7955 which can cause an apparent I/O error. */
7956 if (interrupt_input)
7957 unrequest_sigio ();
7958 stop_polling ();
1af9f229 7959
bd9d0f3f 7960 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
5f5c8ee5 7961 {
92a90e89
GM
7962 if (hscroll_windows (selected_window))
7963 goto retry;
7964
5f5c8ee5 7965 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 7966 pause = update_frame (sf, 0, 0);
5f5c8ee5 7967 }
d724d989 7968
8de2d90b 7969 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
7970 function. If the echo area is on another frame, that may
7971 have put text on a frame other than the selected one, so the
7972 above call to update_frame would not have caught it. Catch
8de2d90b 7973 it here. */
bd9d0f3f
GM
7974 mini_window = FRAME_MINIBUF_WINDOW (sf);
7975 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
8de2d90b 7976
bd9d0f3f
GM
7977 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
7978 {
7979 XWINDOW (mini_window)->must_be_updated_p = 1;
7980 pause |= update_frame (mini_frame, 0, 0);
7981 if (!pause && hscroll_windows (mini_window))
7982 goto retry;
7983 }
6e8290aa 7984 }
a2889657 7985
5f5c8ee5
GM
7986 /* If display was paused because of pending input, make sure we do a
7987 thorough update the next time. */
a2889657
JB
7988 if (pause)
7989 {
5f5c8ee5
GM
7990 /* Prevent the optimization at the beginning of
7991 redisplay_internal that tries a single-line update of the
7992 line containing the cursor in the selected window. */
7993 CHARPOS (this_line_start_pos) = 0;
7994
7995 /* Let the overlay arrow be updated the next time. */
265a9e55 7996 if (!NILP (last_arrow_position))
a2889657
JB
7997 {
7998 last_arrow_position = Qt;
7999 last_arrow_string = Qt;
8000 }
5f5c8ee5
GM
8001
8002 /* If we pause after scrolling, some rows in the current
8003 matrices of some windows are not valid. */
8004 if (!WINDOW_FULL_WIDTH_P (w)
8005 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
8006 update_mode_lines = 1;
8007 }
8008
5f5c8ee5
GM
8009 /* Now text on frame agrees with windows, so put info into the
8010 windows for partial redisplay to follow. */
a2889657
JB
8011 if (!pause)
8012 {
8013 register struct buffer *b = XBUFFER (w->buffer);
8014
9142dd5b
GM
8015 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
8016 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
8017 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
8018 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
a2889657 8019
5f5c8ee5 8020 if (consider_all_windows_p)
886bd6f2 8021 mark_window_display_accurate (FRAME_ROOT_WINDOW (sf), 1);
a2889657
JB
8022 else
8023 {
5f5c8ee5
GM
8024 XSETFASTINT (w->last_point, BUF_PT (b));
8025 w->last_cursor = w->cursor;
8026 w->last_cursor_off_p = w->cursor_off_p;
8027
28995e67 8028 b->clip_changed = 0;
9142dd5b 8029 b->prevent_redisplay_optimizations_p = 0;
a2889657 8030 w->update_mode_line = Qnil;
c2213350 8031 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
8850a573 8032 XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
538f13d4
RS
8033 w->last_had_star
8034 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
8035 ? Qt : Qnil);
3ee4159a
RS
8036
8037 /* Record if we are showing a region, so can make sure to
8038 update it fully at next redisplay. */
8039 w->region_showing = (!NILP (Vtransient_mark_mode)
97a36635
GM
8040 && (EQ (selected_window,
8041 current_buffer->last_selected_window)
293a54ce 8042 || highlight_nonselected_windows)
3ee4159a
RS
8043 && !NILP (XBUFFER (w->buffer)->mark_active)
8044 ? Fmarker_position (XBUFFER (w->buffer)->mark)
8045 : Qnil);
8046
d2f84654 8047 w->window_end_valid = w->buffer;
d45de95b 8048 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657 8049 last_arrow_string = Voverlay_arrow_string;
efc63ef0 8050 if (frame_up_to_date_hook != 0)
886bd6f2 8051 (*frame_up_to_date_hook) (sf);
9142dd5b
GM
8052
8053 w->current_matrix->buffer = b;
8054 w->current_matrix->begv = BUF_BEGV (b);
8055 w->current_matrix->zv = BUF_ZV (b);
a2889657 8056 }
15e26c76 8057
a2889657
JB
8058 update_mode_lines = 0;
8059 windows_or_buffers_changed = 0;
8060 }
8061
5f5c8ee5
GM
8062 /* Start SIGIO interrupts coming again. Having them off during the
8063 code above makes it less likely one will discard output, but not
8064 impossible, since there might be stuff in the system buffer here.
a2889657 8065 But it is much hairier to try to do anything about that. */
a2889657
JB
8066 if (interrupt_input)
8067 request_sigio ();
8068 start_polling ();
8069
5f5c8ee5
GM
8070 /* If a frame has become visible which was not before, redisplay
8071 again, so that we display it. Expose events for such a frame
8072 (which it gets when becoming visible) don't call the parts of
8073 redisplay constructing glyphs, so simply exposing a frame won't
8074 display anything in this case. So, we have to display these
8075 frames here explicitly. */
11c52c4f
RS
8076 if (!pause)
8077 {
8078 Lisp_Object tail, frame;
8079 int new_count = 0;
8080
8081 FOR_EACH_FRAME (tail, frame)
8082 {
8083 int this_is_visible = 0;
8e83f802
RS
8084
8085 if (XFRAME (frame)->visible)
8086 this_is_visible = 1;
8087 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
8088 if (XFRAME (frame)->visible)
8089 this_is_visible = 1;
11c52c4f
RS
8090
8091 if (this_is_visible)
8092 new_count++;
8093 }
8094
89819bdd 8095 if (new_count != number_of_visible_frames)
11c52c4f
RS
8096 windows_or_buffers_changed++;
8097 }
8098
44fa5b1e 8099 /* Change frame size now if a change is pending. */
c6e89d6c 8100 do_pending_window_change (1);
d8e242fd 8101
8b32d885
RS
8102 /* If we just did a pending size change, or have additional
8103 visible frames, redisplay again. */
3c8c72e0 8104 if (windows_or_buffers_changed && !pause)
8b32d885 8105 goto retry;
5f5c8ee5
GM
8106
8107 end_of_redisplay:;
c6e89d6c 8108
28514cd9 8109 unbind_to (count, Qnil);
a2889657
JB
8110}
8111
5f5c8ee5
GM
8112
8113/* Redisplay, but leave alone any recent echo area message unless
8114 another message has been requested in its place.
a2889657
JB
8115
8116 This is useful in situations where you need to redisplay but no
8117 user action has occurred, making it inappropriate for the message
8118 area to be cleared. See tracking_off and
8119 wait_reading_process_input for examples of these situations. */
8120
8991bb31 8121void
a2889657
JB
8122redisplay_preserve_echo_area ()
8123{
c6e89d6c 8124 if (!NILP (echo_area_buffer[1]))
a2889657 8125 {
c6e89d6c
GM
8126 /* We have a previously displayed message, but no current
8127 message. Redisplay the previous message. */
8128 display_last_displayed_message_p = 1;
e9874cee 8129 redisplay_internal (1);
c6e89d6c 8130 display_last_displayed_message_p = 0;
a2889657
JB
8131 }
8132 else
e9874cee 8133 redisplay_internal (1);
a2889657
JB
8134}
8135
5f5c8ee5 8136
28514cd9
GM
8137/* Function registered with record_unwind_protect in
8138 redisplay_internal. Clears the flag indicating that a redisplay is
8139 in progress. */
8140
8141static Lisp_Object
8142unwind_redisplay (old_redisplaying_p)
8143 Lisp_Object old_redisplaying_p;
8144{
8145 redisplaying_p = XFASTINT (old_redisplaying_p);
c6e89d6c 8146 return Qnil;
28514cd9
GM
8147}
8148
8149
5f5c8ee5
GM
8150/* Mark the display of windows in the window tree rooted at WINDOW as
8151 accurate or inaccurate. If FLAG is non-zero mark display of WINDOW
8152 as accurate. If FLAG is zero arrange for WINDOW to be redisplayed
8153 the next time redisplay_internal is called. */
8154
a2889657 8155void
5f5c8ee5 8156mark_window_display_accurate (window, accurate_p)
a2889657 8157 Lisp_Object window;
5f5c8ee5 8158 int accurate_p;
a2889657 8159{
5f5c8ee5
GM
8160 struct window *w;
8161
8162 for (; !NILP (window); window = w->next)
a2889657
JB
8163 {
8164 w = XWINDOW (window);
8165
5f5c8ee5 8166 if (BUFFERP (w->buffer))
bd66d1ba 8167 {
5f5c8ee5
GM
8168 struct buffer *b = XBUFFER (w->buffer);
8169
c2213350 8170 XSETFASTINT (w->last_modified,
5f5c8ee5 8171 accurate_p ? BUF_MODIFF (b) : 0);
8850a573 8172 XSETFASTINT (w->last_overlay_modified,
5f5c8ee5
GM
8173 accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
8174 w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)
8175 ? Qt : Qnil);
bd66d1ba 8176
5f5c8ee5
GM
8177#if 0 /* I don't think this is necessary because display_line does it.
8178 Let's check it. */
bd66d1ba
RS
8179 /* Record if we are showing a region, so can make sure to
8180 update it fully at next redisplay. */
5f5c8ee5
GM
8181 w->region_showing
8182 = (!NILP (Vtransient_mark_mode)
8183 && (w == XWINDOW (current_buffer->last_selected_window)
8184 || highlight_nonselected_windows)
8185 && (!NILP (b->mark_active)
8186 ? Fmarker_position (b->mark)
8187 : Qnil));
8188#endif
8189
8190 if (accurate_p)
8191 {
8192 b->clip_changed = 0;
9142dd5b
GM
8193 b->prevent_redisplay_optimizations_p = 0;
8194 w->current_matrix->buffer = b;
8195 w->current_matrix->begv = BUF_BEGV (b);
8196 w->current_matrix->zv = BUF_ZV (b);
5f5c8ee5
GM
8197 w->last_cursor = w->cursor;
8198 w->last_cursor_off_p = w->cursor_off_p;
8199 if (w == XWINDOW (selected_window))
6fc556fd 8200 w->last_point = make_number (BUF_PT (b));
5f5c8ee5 8201 else
6fc556fd 8202 w->last_point = make_number (XMARKER (w->pointm)->charpos);
5f5c8ee5 8203 }
bd66d1ba
RS
8204 }
8205
d2f84654 8206 w->window_end_valid = w->buffer;
a2889657
JB
8207 w->update_mode_line = Qnil;
8208
265a9e55 8209 if (!NILP (w->vchild))
5f5c8ee5 8210 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 8211 if (!NILP (w->hchild))
5f5c8ee5 8212 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
8213 }
8214
5f5c8ee5 8215 if (accurate_p)
a2889657 8216 {
d45de95b 8217 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
8218 last_arrow_string = Voverlay_arrow_string;
8219 }
8220 else
8221 {
5f5c8ee5
GM
8222 /* Force a thorough redisplay the next time by setting
8223 last_arrow_position and last_arrow_string to t, which is
8224 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
8225 last_arrow_position = Qt;
8226 last_arrow_string = Qt;
8227 }
8228}
5f5c8ee5
GM
8229
8230
8231/* Return value in display table DP (Lisp_Char_Table *) for character
8232 C. Since a display table doesn't have any parent, we don't have to
8233 follow parent. Do not call this function directly but use the
8234 macro DISP_CHAR_VECTOR. */
8235
8236Lisp_Object
8237disp_char_vector (dp, c)
8238 struct Lisp_Char_Table *dp;
8239 int c;
8240{
8241 int code[4], i;
8242 Lisp_Object val;
8243
8244 if (SINGLE_BYTE_CHAR_P (c))
8245 return (dp->contents[c]);
8246
c5924f47 8247 SPLIT_CHAR (c, code[0], code[1], code[2]);
260a86a0
KH
8248 if (code[1] < 32)
8249 code[1] = -1;
8250 else if (code[2] < 32)
8251 code[2] = -1;
5f5c8ee5
GM
8252
8253 /* Here, the possible range of code[0] (== charset ID) is
8254 128..max_charset. Since the top level char table contains data
8255 for multibyte characters after 256th element, we must increment
8256 code[0] by 128 to get a correct index. */
8257 code[0] += 128;
8258 code[3] = -1; /* anchor */
8259
8260 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
8261 {
8262 val = dp->contents[code[i]];
8263 if (!SUB_CHAR_TABLE_P (val))
8264 return (NILP (val) ? dp->defalt : val);
8265 }
8266
8267 /* Here, val is a sub char table. We return the default value of
8268 it. */
8269 return (dp->defalt);
8270}
8271
8272
a2889657 8273\f
5f5c8ee5
GM
8274/***********************************************************************
8275 Window Redisplay
8276 ***********************************************************************/
a2725ab2 8277
5f5c8ee5 8278/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
8279
8280static void
5f5c8ee5
GM
8281redisplay_windows (window)
8282 Lisp_Object window;
90adcf20 8283{
5f5c8ee5
GM
8284 while (!NILP (window))
8285 {
8286 struct window *w = XWINDOW (window);
8287
8288 if (!NILP (w->hchild))
8289 redisplay_windows (w->hchild);
8290 else if (!NILP (w->vchild))
8291 redisplay_windows (w->vchild);
8292 else
8293 redisplay_window (window, 0);
a2725ab2 8294
5f5c8ee5
GM
8295 window = w->next;
8296 }
8297}
8298
8299
8300/* Set cursor position of W. PT is assumed to be displayed in ROW.
8301 DELTA is the number of bytes by which positions recorded in ROW
8302 differ from current buffer positions. */
8303
8304void
8305set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
8306 struct window *w;
8307 struct glyph_row *row;
8308 struct glyph_matrix *matrix;
8309 int delta, delta_bytes, dy, dvpos;
8310{
8311 struct glyph *glyph = row->glyphs[TEXT_AREA];
8312 struct glyph *end = glyph + row->used[TEXT_AREA];
8313 int x = row->x;
8314 int pt_old = PT - delta;
8315
8316 /* Skip over glyphs not having an object at the start of the row.
8317 These are special glyphs like truncation marks on terminal
8318 frames. */
8319 if (row->displays_text_p)
8320 while (glyph < end
6fc556fd 8321 && INTEGERP (glyph->object)
5f5c8ee5
GM
8322 && glyph->charpos < 0)
8323 {
8324 x += glyph->pixel_width;
8325 ++glyph;
8326 }
8327
8328 while (glyph < end
6fc556fd 8329 && !INTEGERP (glyph->object)
5f5c8ee5
GM
8330 && (!BUFFERP (glyph->object)
8331 || glyph->charpos < pt_old))
8332 {
8333 x += glyph->pixel_width;
8334 ++glyph;
8335 }
8336
8337 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
8338 w->cursor.x = x;
8339 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
8340 w->cursor.y = row->y + dy;
8341
8342 if (w == XWINDOW (selected_window))
8343 {
8344 if (!row->continued_p
8345 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
8346 && row->x == 0)
8347 {
8348 this_line_buffer = XBUFFER (w->buffer);
8349
8350 CHARPOS (this_line_start_pos)
8351 = MATRIX_ROW_START_CHARPOS (row) + delta;
8352 BYTEPOS (this_line_start_pos)
8353 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
8354
8355 CHARPOS (this_line_end_pos)
8356 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
8357 BYTEPOS (this_line_end_pos)
8358 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
8359
8360 this_line_y = w->cursor.y;
8361 this_line_pixel_height = row->height;
8362 this_line_vpos = w->cursor.vpos;
8363 this_line_start_x = row->x;
8364 }
8365 else
8366 CHARPOS (this_line_start_pos) = 0;
8367 }
8368}
8369
8370
8371/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
8372 start STARTP. Sets the window start of WINDOW to that position.
8373
8374 We assume that the window's buffer is really current. */
5f5c8ee5
GM
8375
8376static INLINE struct text_pos
8377run_window_scroll_functions (window, startp)
8378 Lisp_Object window;
8379 struct text_pos startp;
8380{
8381 struct window *w = XWINDOW (window);
8382 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
8383
8384 if (current_buffer != XBUFFER (w->buffer))
8385 abort ();
8386
5f5c8ee5
GM
8387 if (!NILP (Vwindow_scroll_functions))
8388 {
8389 run_hook_with_args_2 (Qwindow_scroll_functions, window,
8390 make_number (CHARPOS (startp)));
8391 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
8392 /* In case the hook functions switch buffers. */
8393 if (current_buffer != XBUFFER (w->buffer))
8394 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8395 }
90adcf20 8396
5f5c8ee5
GM
8397 return startp;
8398}
8399
8400
8401/* Modify the desired matrix of window W and W->vscroll so that the
8402 line containing the cursor is fully visible. */
8403
8404static void
8405make_cursor_line_fully_visible (w)
8406 struct window *w;
8407{
8408 struct glyph_matrix *matrix;
8409 struct glyph_row *row;
b28cb6ed 8410 int window_height, header_line_height;
5f5c8ee5
GM
8411
8412 /* It's not always possible to find the cursor, e.g, when a window
8413 is full of overlay strings. Don't do anything in that case. */
8414 if (w->cursor.vpos < 0)
8415 return;
8416
8417 matrix = w->desired_matrix;
8418 row = MATRIX_ROW (matrix, w->cursor.vpos);
8419
b28cb6ed
GM
8420 /* If the cursor row is not partially visible, there's nothing
8421 to do. */
8422 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
8423 return;
8424
8425 /* If the row the cursor is in is taller than the window's height,
8426 it's not clear what to do, so do nothing. */
8427 window_height = window_box_height (w);
8428 if (row->height >= window_height)
8429 return;
8430
8431 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
5f5c8ee5
GM
8432 {
8433 int dy = row->height - row->visible_height;
8434 w->vscroll = 0;
8435 w->cursor.y += dy;
8436 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
8437 }
b28cb6ed 8438 else /* MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) */
5f5c8ee5
GM
8439 {
8440 int dy = - (row->height - row->visible_height);
8441 w->vscroll = dy;
8442 w->cursor.y += dy;
8443 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
8444 }
b28cb6ed 8445
5f5c8ee5
GM
8446 /* When we change the cursor y-position of the selected window,
8447 change this_line_y as well so that the display optimization for
8448 the cursor line of the selected window in redisplay_internal uses
8449 the correct y-position. */
8450 if (w == XWINDOW (selected_window))
8451 this_line_y = w->cursor.y;
8452}
8453
8454
8455/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
8456 non-zero means only WINDOW is redisplayed in redisplay_internal.
8457 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
8458 in redisplay_window to bring a partially visible line into view in
8459 the case that only the cursor has moved.
8460
8461 Value is
8462
8463 1 if scrolling succeeded
8464
8465 0 if scrolling didn't find point.
8466
8467 -1 if new fonts have been loaded so that we must interrupt
8468 redisplay, adjust glyph matrices, and try again. */
8469
8470static int
8471try_scrolling (window, just_this_one_p, scroll_conservatively,
8472 scroll_step, temp_scroll_step)
8473 Lisp_Object window;
8474 int just_this_one_p;
8475 int scroll_conservatively, scroll_step;
8476 int temp_scroll_step;
8477{
8478 struct window *w = XWINDOW (window);
8479 struct frame *f = XFRAME (w->frame);
8480 struct text_pos scroll_margin_pos;
8481 struct text_pos pos;
8482 struct text_pos startp;
8483 struct it it;
8484 Lisp_Object window_end;
8485 int this_scroll_margin;
8486 int dy = 0;
8487 int scroll_max;
8488 int line_height, rc;
8489 int amount_to_scroll = 0;
8490 Lisp_Object aggressive;
8491 int height;
8492
8493#if GLYPH_DEBUG
8494 debug_method_add (w, "try_scrolling");
78614721 8495#endif
5f5c8ee5
GM
8496
8497 SET_TEXT_POS_FROM_MARKER (startp, w->start);
8498
8499 /* Compute scroll margin height in pixels. We scroll when point is
8500 within this distance from the top or bottom of the window. */
8501 if (scroll_margin > 0)
90adcf20 8502 {
5f5c8ee5
GM
8503 this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
8504 this_scroll_margin *= CANON_Y_UNIT (f);
8505 }
8506 else
8507 this_scroll_margin = 0;
8508
8509 /* Compute how much we should try to scroll maximally to bring point
8510 into view. */
8511 if (scroll_step)
8512 scroll_max = scroll_step;
8513 else if (scroll_conservatively)
8514 scroll_max = scroll_conservatively;
8515 else if (temp_scroll_step)
8516 scroll_max = temp_scroll_step;
8517 else if (NUMBERP (current_buffer->scroll_down_aggressively)
8518 || NUMBERP (current_buffer->scroll_up_aggressively))
8519 /* We're trying to scroll because of aggressive scrolling
8520 but no scroll_step is set. Choose an arbitrary one. Maybe
8521 there should be a variable for this. */
8522 scroll_max = 10;
8523 else
8524 scroll_max = 0;
8525 scroll_max *= CANON_Y_UNIT (f);
8526
8527 /* Decide whether we have to scroll down. Start at the window end
8528 and move this_scroll_margin up to find the position of the scroll
8529 margin. */
8530 window_end = Fwindow_end (window, Qt);
8531 CHARPOS (scroll_margin_pos) = XINT (window_end);
8532 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
8533 if (this_scroll_margin)
8534 {
8535 start_display (&it, w, scroll_margin_pos);
8536 move_it_vertically (&it, - this_scroll_margin);
8537 scroll_margin_pos = it.current.pos;
8538 }
8539
8540 if (PT >= CHARPOS (scroll_margin_pos))
8541 {
8542 int y0;
8543
8544 /* Point is in the scroll margin at the bottom of the window, or
8545 below. Compute a new window start that makes point visible. */
47589c8c 8546
5f5c8ee5
GM
8547 /* Compute the distance from the scroll margin to PT.
8548 Give up if the distance is greater than scroll_max. */
8549 start_display (&it, w, scroll_margin_pos);
8550 y0 = it.current_y;
8551 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8552 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8553 line_height = (it.max_ascent + it.max_descent
8554 ? it.max_ascent + it.max_descent
8555 : last_height);
8556 dy = it.current_y + line_height - y0;
47589c8c 8557
5f5c8ee5
GM
8558 if (dy > scroll_max)
8559 return 0;
8560
8561 /* Move the window start down. If scrolling conservatively,
8562 move it just enough down to make point visible. If
8563 scroll_step is set, move it down by scroll_step. */
8564 start_display (&it, w, startp);
8565
8566 if (scroll_conservatively)
8567 amount_to_scroll = dy;
8568 else if (scroll_step || temp_scroll_step)
8569 amount_to_scroll = scroll_max;
8570 else
90adcf20 8571 {
5f5c8ee5
GM
8572 aggressive = current_buffer->scroll_down_aggressively;
8573 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8574 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8575 if (NUMBERP (aggressive))
8576 amount_to_scroll = XFLOATINT (aggressive) * height;
8577 }
a2725ab2 8578
5f5c8ee5
GM
8579 if (amount_to_scroll <= 0)
8580 return 0;
a2725ab2 8581
5f5c8ee5
GM
8582 move_it_vertically (&it, amount_to_scroll);
8583 startp = it.current.pos;
8584 }
8585 else
8586 {
8587 /* See if point is inside the scroll margin at the top of the
8588 window. */
8589 scroll_margin_pos = startp;
8590 if (this_scroll_margin)
8591 {
8592 start_display (&it, w, startp);
8593 move_it_vertically (&it, this_scroll_margin);
8594 scroll_margin_pos = it.current.pos;
8595 }
8596
8597 if (PT < CHARPOS (scroll_margin_pos))
8598 {
8599 /* Point is in the scroll margin at the top of the window or
8600 above what is displayed in the window. */
8601 int y0;
8602
8603 /* Compute the vertical distance from PT to the scroll
8604 margin position. Give up if distance is greater than
8605 scroll_max. */
8606 SET_TEXT_POS (pos, PT, PT_BYTE);
8607 start_display (&it, w, pos);
8608 y0 = it.current_y;
8609 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
8610 it.last_visible_y, -1,
8611 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8612 dy = it.current_y - y0;
8613 if (dy > scroll_max)
8614 return 0;
8615
8616 /* Compute new window start. */
8617 start_display (&it, w, startp);
8618
8619 if (scroll_conservatively)
8620 amount_to_scroll = dy;
8621 else if (scroll_step || temp_scroll_step)
8622 amount_to_scroll = scroll_max;
538f13d4 8623 else
5f5c8ee5
GM
8624 {
8625 aggressive = current_buffer->scroll_up_aggressively;
8626 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8627 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8628 if (NUMBERP (aggressive))
8629 amount_to_scroll = XFLOATINT (aggressive) * height;
8630 }
a2725ab2 8631
5f5c8ee5
GM
8632 if (amount_to_scroll <= 0)
8633 return 0;
8634
8635 move_it_vertically (&it, - amount_to_scroll);
8636 startp = it.current.pos;
90adcf20
RS
8637 }
8638 }
a2889657 8639
5f5c8ee5
GM
8640 /* Run window scroll functions. */
8641 startp = run_window_scroll_functions (window, startp);
90adcf20 8642
5f5c8ee5
GM
8643 /* Display the window. Give up if new fonts are loaded, or if point
8644 doesn't appear. */
8645 if (!try_window (window, startp))
8646 rc = -1;
8647 else if (w->cursor.vpos < 0)
8648 {
8649 clear_glyph_matrix (w->desired_matrix);
8650 rc = 0;
8651 }
8652 else
8653 {
8654 /* Maybe forget recorded base line for line number display. */
8655 if (!just_this_one_p
8656 || current_buffer->clip_changed
9142dd5b 8657 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5
GM
8658 w->base_line_number = Qnil;
8659
8660 /* If cursor ends up on a partially visible line, shift display
8661 lines up or down. */
8662 make_cursor_line_fully_visible (w);
8663 rc = 1;
8664 }
8665
8666 return rc;
a2889657
JB
8667}
8668
5f5c8ee5
GM
8669
8670/* Compute a suitable window start for window W if display of W starts
8671 on a continuation line. Value is non-zero if a new window start
8672 was computed.
8673
8674 The new window start will be computed, based on W's width, starting
8675 from the start of the continued line. It is the start of the
8676 screen line with the minimum distance from the old start W->start. */
8677
8678static int
8679compute_window_start_on_continuation_line (w)
8680 struct window *w;
1f1ff51d 8681{
5f5c8ee5
GM
8682 struct text_pos pos, start_pos;
8683 int window_start_changed_p = 0;
1f1ff51d 8684
5f5c8ee5 8685 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 8686
5f5c8ee5
GM
8687 /* If window start is on a continuation line... Window start may be
8688 < BEGV in case there's invisible text at the start of the
8689 buffer (M-x rmail, for example). */
8690 if (CHARPOS (start_pos) > BEGV
8691 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 8692 {
5f5c8ee5
GM
8693 struct it it;
8694 struct glyph_row *row;
f3751a65
GM
8695
8696 /* Handle the case that the window start is out of range. */
8697 if (CHARPOS (start_pos) < BEGV)
8698 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
8699 else if (CHARPOS (start_pos) > ZV)
8700 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
5f5c8ee5
GM
8701
8702 /* Find the start of the continued line. This should be fast
8703 because scan_buffer is fast (newline cache). */
045dee35 8704 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
8705 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
8706 row, DEFAULT_FACE_ID);
8707 reseat_at_previous_visible_line_start (&it);
8708
8709 /* If the line start is "too far" away from the window start,
8710 say it takes too much time to compute a new window start. */
8711 if (CHARPOS (start_pos) - IT_CHARPOS (it)
8712 < XFASTINT (w->height) * XFASTINT (w->width))
8713 {
8714 int min_distance, distance;
8715
8716 /* Move forward by display lines to find the new window
8717 start. If window width was enlarged, the new start can
8718 be expected to be > the old start. If window width was
8719 decreased, the new window start will be < the old start.
8720 So, we're looking for the display line start with the
8721 minimum distance from the old window start. */
8722 pos = it.current.pos;
8723 min_distance = INFINITY;
8724 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
8725 distance < min_distance)
8726 {
8727 min_distance = distance;
8728 pos = it.current.pos;
8729 move_it_by_lines (&it, 1, 0);
8730 }
8731
8732 /* Set the window start there. */
8733 SET_MARKER_FROM_TEXT_POS (w->start, pos);
8734 window_start_changed_p = 1;
8735 }
1f1ff51d 8736 }
5f5c8ee5
GM
8737
8738 return window_start_changed_p;
1f1ff51d
KH
8739}
8740
5f5c8ee5 8741
47589c8c
GM
8742/* Try cursor movement in case text has not changes in window WINDOW,
8743 with window start STARTP. Value is
8744
8745 1 if successful
8746
8747 0 if this method cannot be used
8748
8749 -1 if we know we have to scroll the display. *SCROLL_STEP is
8750 set to 1, under certain circumstances, if we want to scroll as
8751 if scroll-step were set to 1. See the code. */
8752
8753static int
8754try_cursor_movement (window, startp, scroll_step)
8755 Lisp_Object window;
8756 struct text_pos startp;
8757 int *scroll_step;
8758{
8759 struct window *w = XWINDOW (window);
8760 struct frame *f = XFRAME (w->frame);
8761 int rc = 0;
8762
8763 /* Handle case where text has not changed, only point, and it has
8764 not moved off the frame. */
8765 if (/* Point may be in this window. */
8766 PT >= CHARPOS (startp)
8767 /* If we don't check this, we are called to move the cursor in a
8768 horizontally split window with a current matrix that doesn't
8769 fit the display. */
8770 && !windows_or_buffers_changed
8771 /* Selective display hasn't changed. */
8772 && !current_buffer->clip_changed
8773 /* If force-mode-line-update was called, really redisplay;
8774 that's how redisplay is forced after e.g. changing
8775 buffer-invisibility-spec. */
8776 && NILP (w->update_mode_line)
8777 /* Can't use this case if highlighting a region. When a
8778 region exists, cursor movement has to do more than just
8779 set the cursor. */
8780 && !(!NILP (Vtransient_mark_mode)
8781 && !NILP (current_buffer->mark_active))
8782 && NILP (w->region_showing)
8783 && NILP (Vshow_trailing_whitespace)
8784 /* Right after splitting windows, last_point may be nil. */
8785 && INTEGERP (w->last_point)
8786 /* This code is not used for mini-buffer for the sake of the case
8787 of redisplaying to replace an echo area message; since in
8788 that case the mini-buffer contents per se are usually
8789 unchanged. This code is of no real use in the mini-buffer
8790 since the handling of this_line_start_pos, etc., in redisplay
8791 handles the same cases. */
8792 && !EQ (window, minibuf_window)
8793 /* When splitting windows or for new windows, it happens that
8794 redisplay is called with a nil window_end_vpos or one being
8795 larger than the window. This should really be fixed in
8796 window.c. I don't have this on my list, now, so we do
8797 approximately the same as the old redisplay code. --gerd. */
8798 && INTEGERP (w->window_end_vpos)
8799 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
8800 && (FRAME_WINDOW_P (f)
8801 || !MARKERP (Voverlay_arrow_position)
8802 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
8803 {
8804 int this_scroll_margin;
8805 struct glyph_row *row;
8806
8807#if GLYPH_DEBUG
8808 debug_method_add (w, "cursor movement");
8809#endif
8810
8811 /* Scroll if point within this distance from the top or bottom
8812 of the window. This is a pixel value. */
8813 this_scroll_margin = max (0, scroll_margin);
8814 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
8815 this_scroll_margin *= CANON_Y_UNIT (f);
8816
8817 /* Start with the row the cursor was displayed during the last
8818 not paused redisplay. Give up if that row is not valid. */
bd9d0f3f
GM
8819 if (w->last_cursor.vpos < 0
8820 || w->last_cursor.vpos >= w->current_matrix->nrows)
47589c8c
GM
8821 rc = -1;
8822 else
8823 {
8824 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
8825 if (row->mode_line_p)
8826 ++row;
8827 if (!row->enabled_p)
8828 rc = -1;
8829 }
8830
8831 if (rc == 0)
8832 {
8833 int scroll_p = 0;
8834
8835 if (PT > XFASTINT (w->last_point))
8836 {
8837 /* Point has moved forward. */
8838 int last_y = window_text_bottom_y (w) - this_scroll_margin;
8839
8840 while (MATRIX_ROW_END_CHARPOS (row) < PT
8841 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
8842 {
8843 xassert (row->enabled_p);
8844 ++row;
8845 }
8846
8847 /* The end position of a row equals the start position
8848 of the next row. If PT is there, we would rather
8849 display it in the next line. Exceptions are when the
8850 row ends in the middle of a character, or ends in
8851 ZV. */
8852 if (MATRIX_ROW_BOTTOM_Y (row) < last_y
8853 && MATRIX_ROW_END_CHARPOS (row) == PT
8854 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
8855 && !row->ends_at_zv_p)
8856 {
8857 xassert (row->enabled_p);
8858 ++row;
8859 }
8860
8861 /* If within the scroll margin, scroll. Note that
8862 MATRIX_ROW_BOTTOM_Y gives the pixel position at which
8863 the next line would be drawn, and that
8864 this_scroll_margin can be zero. */
8865 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
8866 || PT > MATRIX_ROW_END_CHARPOS (row)
8867 /* Line is completely visible last line in window
8868 and PT is to be set in the next line. */
8869 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
8870 && PT == MATRIX_ROW_END_CHARPOS (row)
8871 && !row->ends_at_zv_p
8872 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
8873 scroll_p = 1;
8874 }
8875 else if (PT < XFASTINT (w->last_point))
8876 {
8877 /* Cursor has to be moved backward. Note that PT >=
8878 CHARPOS (startp) because of the outer
8879 if-statement. */
8880 while (!row->mode_line_p
8881 && (MATRIX_ROW_START_CHARPOS (row) > PT
8882 || (MATRIX_ROW_START_CHARPOS (row) == PT
8883 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
8884 && (row->y > this_scroll_margin
8885 || CHARPOS (startp) == BEGV))
8886 {
8887 xassert (row->enabled_p);
8888 --row;
8889 }
8890
8891 /* Consider the following case: Window starts at BEGV,
8892 there is invisible, intangible text at BEGV, so that
8893 display starts at some point START > BEGV. It can
8894 happen that we are called with PT somewhere between
8895 BEGV and START. Try to handle that case. */
8896 if (row < w->current_matrix->rows
8897 || row->mode_line_p)
8898 {
8899 row = w->current_matrix->rows;
8900 if (row->mode_line_p)
8901 ++row;
8902 }
8903
8904 /* Due to newlines in overlay strings, we may have to
8905 skip forward over overlay strings. */
8906 while (MATRIX_ROW_END_CHARPOS (row) == PT
8907 && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row)
8908 && !row->ends_at_zv_p)
8909 ++row;
8910
8911 /* If within the scroll margin, scroll. */
8912 if (row->y < this_scroll_margin
8913 && CHARPOS (startp) != BEGV)
8914 scroll_p = 1;
8915 }
8916
8917 if (PT < MATRIX_ROW_START_CHARPOS (row)
8918 || PT > MATRIX_ROW_END_CHARPOS (row))
8919 {
8920 /* if PT is not in the glyph row, give up. */
8921 rc = -1;
8922 }
440fc135 8923 else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
47589c8c
GM
8924 {
8925 /* If we end up in a partially visible line, let's make it
8926 fully visible, except when it's taller than the window,
8927 in which case we can't do much about it. */
440fc135
GM
8928 if (row->height > window_box_height (w))
8929 {
8930 *scroll_step = 1;
8931 rc = -1;
8932 }
8933 else
8934 {
8935 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
8936 try_window (window, startp);
8937 make_cursor_line_fully_visible (w);
8938 rc = 1;
8939 }
47589c8c
GM
8940 }
8941 else if (scroll_p)
8942 rc = -1;
8943 else
8944 {
8945 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
8946 rc = 1;
8947 }
8948 }
8949 }
8950
8951 return rc;
8952}
8953
8954
5f5c8ee5
GM
8955/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
8956 selected_window is redisplayed. */
90adcf20 8957
a2889657 8958static void
5f5c8ee5 8959redisplay_window (window, just_this_one_p)
a2889657 8960 Lisp_Object window;
5f5c8ee5 8961 int just_this_one_p;
a2889657 8962{
5f5c8ee5
GM
8963 struct window *w = XWINDOW (window);
8964 struct frame *f = XFRAME (w->frame);
8965 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 8966 struct buffer *old = current_buffer;
5f5c8ee5 8967 struct text_pos lpoint, opoint, startp;
e481f960 8968 int update_mode_line;
5f5c8ee5
GM
8969 int tem;
8970 struct it it;
8971 /* Record it now because it's overwritten. */
8972 int current_matrix_up_to_date_p = 0;
5f5c8ee5 8973 int temp_scroll_step = 0;
2e54982e 8974 int count = specpdl_ptr - specpdl;
47589c8c 8975 int rc;
a2889657 8976
5f5c8ee5
GM
8977 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8978 opoint = lpoint;
a2889657 8979
5f5c8ee5
GM
8980 /* W must be a leaf window here. */
8981 xassert (!NILP (w->buffer));
8982#if GLYPH_DEBUG
8983 *w->desired_matrix->method = 0;
8984#endif
2e54982e
RS
8985
8986 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
8987
8988 reconsider_clip_changes (w, buffer);
8989
5f5c8ee5
GM
8990 /* Has the mode line to be updated? */
8991 update_mode_line = (!NILP (w->update_mode_line)
8992 || update_mode_lines
8993 || buffer->clip_changed);
8de2d90b
JB
8994
8995 if (MINI_WINDOW_P (w))
8996 {
5f5c8ee5 8997 if (w == XWINDOW (echo_area_window)
c6e89d6c 8998 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
8999 {
9000 if (update_mode_line)
9001 /* We may have to update a tty frame's menu bar or a
e037b9ec 9002 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
9003 goto finish_menu_bars;
9004 else
9005 /* We've already displayed the echo area glyphs in this window. */
9006 goto finish_scroll_bars;
9007 }
73af359d 9008 else if (w != XWINDOW (minibuf_window))
8de2d90b 9009 {
5f5c8ee5
GM
9010 /* W is a mini-buffer window, but it's not the currently
9011 active one, so clear it. */
9012 int yb = window_text_bottom_y (w);
9013 struct glyph_row *row;
9014 int y;
9015
9016 for (y = 0, row = w->desired_matrix->rows;
9017 y < yb;
9018 y += row->height, ++row)
9019 blank_row (w, row, y);
88f22aff 9020 goto finish_scroll_bars;
8de2d90b
JB
9021 }
9022 }
a2889657 9023
5f5c8ee5
GM
9024 /* Otherwise set up data on this window; select its buffer and point
9025 value. */
6a93695f
GM
9026 /* Really select the buffer, for the sake of buffer-local
9027 variables. */
9028 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5
GM
9029 SET_TEXT_POS (opoint, PT, PT_BYTE);
9030
9031 current_matrix_up_to_date_p
9032 = (!NILP (w->window_end_valid)
9033 && !current_buffer->clip_changed
9034 && XFASTINT (w->last_modified) >= MODIFF
9035 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 9036
5f5c8ee5
GM
9037 /* When windows_or_buffers_changed is non-zero, we can't rely on
9038 the window end being valid, so set it to nil there. */
9039 if (windows_or_buffers_changed)
9040 {
9041 /* If window starts on a continuation line, maybe adjust the
9042 window start in case the window's width changed. */
9043 if (XMARKER (w->start)->buffer == current_buffer)
9044 compute_window_start_on_continuation_line (w);
9045
9046 w->window_end_valid = Qnil;
9047 }
12adba34 9048
5f5c8ee5
GM
9049 /* Some sanity checks. */
9050 CHECK_WINDOW_END (w);
9051 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 9052 abort ();
5f5c8ee5 9053 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 9054 abort ();
a2889657 9055
28995e67
RS
9056 /* If %c is in mode line, update it if needed. */
9057 if (!NILP (w->column_number_displayed)
9058 /* This alternative quickly identifies a common case
9059 where no change is needed. */
9060 && !(PT == XFASTINT (w->last_point)
8850a573
RS
9061 && XFASTINT (w->last_modified) >= MODIFF
9062 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
9063 && XFASTINT (w->column_number_displayed) != current_column ())
9064 update_mode_line = 1;
9065
5f5c8ee5
GM
9066 /* Count number of windows showing the selected buffer. An indirect
9067 buffer counts as its base buffer. */
9068 if (!just_this_one_p)
42640f83
RS
9069 {
9070 struct buffer *current_base, *window_base;
9071 current_base = current_buffer;
9072 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
9073 if (current_base->base_buffer)
9074 current_base = current_base->base_buffer;
9075 if (window_base->base_buffer)
9076 window_base = window_base->base_buffer;
9077 if (current_base == window_base)
9078 buffer_shared++;
9079 }
a2889657 9080
5f5c8ee5
GM
9081 /* Point refers normally to the selected window. For any other
9082 window, set up appropriate value. */
a2889657
JB
9083 if (!EQ (window, selected_window))
9084 {
12adba34
RS
9085 int new_pt = XMARKER (w->pointm)->charpos;
9086 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 9087 if (new_pt < BEGV)
a2889657 9088 {
f67a0f51 9089 new_pt = BEGV;
12adba34
RS
9090 new_pt_byte = BEGV_BYTE;
9091 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 9092 }
f67a0f51 9093 else if (new_pt > (ZV - 1))
a2889657 9094 {
f67a0f51 9095 new_pt = ZV;
12adba34
RS
9096 new_pt_byte = ZV_BYTE;
9097 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 9098 }
5f5c8ee5 9099
f67a0f51 9100 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 9101 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
9102 }
9103
f4faa47c 9104 /* If any of the character widths specified in the display table
5f5c8ee5
GM
9105 have changed, invalidate the width run cache. It's true that
9106 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
9107 redisplay goes (non-fatally) haywire when the display table is
9108 changed, so why should we worry about doing any better? */
9109 if (current_buffer->width_run_cache)
9110 {
f908610f 9111 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
9112
9113 if (! disptab_matches_widthtab (disptab,
9114 XVECTOR (current_buffer->width_table)))
9115 {
9116 invalidate_region_cache (current_buffer,
9117 current_buffer->width_run_cache,
9118 BEG, Z);
9119 recompute_width_table (current_buffer, disptab);
9120 }
9121 }
9122
a2889657 9123 /* If window-start is screwed up, choose a new one. */
a2889657
JB
9124 if (XMARKER (w->start)->buffer != current_buffer)
9125 goto recenter;
9126
5f5c8ee5 9127 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 9128
cf0df6ab
RS
9129 /* If someone specified a new starting point but did not insist,
9130 check whether it can be used. */
cfad01b4
GM
9131 if (!NILP (w->optional_new_start)
9132 && CHARPOS (startp) >= BEGV
9133 && CHARPOS (startp) <= ZV)
cf0df6ab
RS
9134 {
9135 w->optional_new_start = Qnil;
5f5c8ee5
GM
9136 start_display (&it, w, startp);
9137 move_it_to (&it, PT, 0, it.last_visible_y, -1,
9138 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
9139 if (IT_CHARPOS (it) == PT)
cf0df6ab
RS
9140 w->force_start = Qt;
9141 }
9142
8de2d90b 9143 /* Handle case where place to start displaying has been specified,
aa6d10fa 9144 unless the specified location is outside the accessible range. */
9472f927
GM
9145 if (!NILP (w->force_start)
9146 || w->frozen_window_start_p)
a2889657 9147 {
e63574d7 9148 w->force_start = Qnil;
5f5c8ee5 9149 w->vscroll = 0;
b5174a51 9150 w->window_end_valid = Qnil;
5f5c8ee5
GM
9151
9152 /* Forget any recorded base line for line number display. */
9153 if (!current_matrix_up_to_date_p
9154 || current_buffer->clip_changed)
9155 w->base_line_number = Qnil;
9156
75c43375
RS
9157 /* Redisplay the mode line. Select the buffer properly for that.
9158 Also, run the hook window-scroll-functions
9159 because we have scrolled. */
e63574d7
RS
9160 /* Note, we do this after clearing force_start because
9161 if there's an error, it is better to forget about force_start
9162 than to get into an infinite loop calling the hook functions
9163 and having them get more errors. */
75c43375
RS
9164 if (!update_mode_line
9165 || ! NILP (Vwindow_scroll_functions))
e481f960 9166 {
e481f960
RS
9167 update_mode_line = 1;
9168 w->update_mode_line = Qt;
5f5c8ee5 9169 startp = run_window_scroll_functions (window, startp);
e481f960 9170 }
5f5c8ee5 9171
c2213350 9172 XSETFASTINT (w->last_modified, 0);
8850a573 9173 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5
GM
9174 if (CHARPOS (startp) < BEGV)
9175 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
9176 else if (CHARPOS (startp) > ZV)
9177 SET_TEXT_POS (startp, ZV, ZV_BYTE);
9178
9179 /* Redisplay, then check if cursor has been set during the
9180 redisplay. Give up if new fonts were loaded. */
9181 if (!try_window (window, startp))
9182 {
9183 w->force_start = Qt;
9184 clear_glyph_matrix (w->desired_matrix);
9185 goto restore_buffers;
9186 }
9187
9472f927 9188 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5 9189 {
b28cb6ed
GM
9190 /* If point does not appear, try to move point so it does
9191 appear. The desired matrix has been built above, so we
9192 can use it here. */
9193 int window_height;
9194 struct glyph_row *row;
9195
9196 window_height = window_box_height (w) / 2;
9197 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
9198 while (MATRIX_ROW_BOTTOM_Y (row) < window_height)
5f5c8ee5
GM
9199 ++row;
9200
9201 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
9202 MATRIX_ROW_START_BYTEPOS (row));
9203
90adcf20 9204 if (w != XWINDOW (selected_window))
12adba34 9205 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
9206 else if (current_buffer == old)
9207 SET_TEXT_POS (lpoint, PT, PT_BYTE);
9208
9209 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
9210
9211 /* If we are highlighting the region, then we just changed
9212 the region, so redisplay to show it. */
df0b5ea1
RS
9213 if (!NILP (Vtransient_mark_mode)
9214 && !NILP (current_buffer->mark_active))
6f27fa9b 9215 {
5f5c8ee5
GM
9216 clear_glyph_matrix (w->desired_matrix);
9217 if (!try_window (window, startp))
9218 goto restore_buffers;
6f27fa9b 9219 }
a2889657 9220 }
5f5c8ee5
GM
9221
9222 make_cursor_line_fully_visible (w);
9223#if GLYPH_DEBUG
9224 debug_method_add (w, "forced window start");
9225#endif
a2889657
JB
9226 goto done;
9227 }
9228
5f5c8ee5
GM
9229 /* Handle case where text has not changed, only point, and it has
9230 not moved off the frame. */
9231 if (current_matrix_up_to_date_p
47589c8c
GM
9232 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
9233 rc != 0))
a2889657 9234 {
47589c8c 9235 if (rc == -1)
5f5c8ee5 9236 goto try_to_scroll;
47589c8c
GM
9237 else
9238 goto done;
a2889657
JB
9239 }
9240 /* If current starting point was originally the beginning of a line
9241 but no longer is, find a new starting point. */
265a9e55 9242 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
9243 && !(CHARPOS (startp) <= BEGV
9244 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 9245 {
5f5c8ee5
GM
9246#if GLYPH_DEBUG
9247 debug_method_add (w, "recenter 1");
9248#endif
a2889657
JB
9249 goto recenter;
9250 }
5f5c8ee5
GM
9251
9252 /* Try scrolling with try_window_id. */
9142dd5b
GM
9253 else if (/* Windows and buffers haven't changed. */
9254 !windows_or_buffers_changed
5f5c8ee5
GM
9255 /* Window must be either use window-based redisplay or
9256 be full width. */
9257 && (FRAME_WINDOW_P (f)
c59c668a 9258 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)))
5f5c8ee5
GM
9259 && !MINI_WINDOW_P (w)
9260 /* Point is not known NOT to appear in window. */
9261 && PT >= CHARPOS (startp)
a2889657 9262 && XFASTINT (w->last_modified)
5f5c8ee5
GM
9263 /* Window is not hscrolled. */
9264 && XFASTINT (w->hscroll) == 0
9265 /* Selective display has not changed. */
9266 && !current_buffer->clip_changed
9267 /* Current matrix is up to date. */
9268 && !NILP (w->window_end_valid)
9269 /* Can't use this case if highlighting a region because
9270 a cursor movement will do more than just set the cursor. */
bd66d1ba
RS
9271 && !(!NILP (Vtransient_mark_mode)
9272 && !NILP (current_buffer->mark_active))
9273 && NILP (w->region_showing)
8f897821 9274 && NILP (Vshow_trailing_whitespace)
5f5c8ee5 9275 /* Overlay arrow position and string not changed. */
d45de95b 9276 && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
a2889657 9277 && EQ (last_arrow_string, Voverlay_arrow_string)
5f5c8ee5
GM
9278 /* Value is > 0 if update has been done, it is -1 if we
9279 know that the same window start will not work. It is 0
9280 if unsuccessful for some other reason. */
9281 && (tem = try_window_id (w)) != 0)
a2889657 9282 {
5f5c8ee5 9283#if GLYPH_DEBUG
ef121659 9284 debug_method_add (w, "try_window_id %d", tem);
5f5c8ee5
GM
9285#endif
9286
9287 if (fonts_changed_p)
9288 goto restore_buffers;
a2889657
JB
9289 if (tem > 0)
9290 goto done;
ef121659 9291
5f5c8ee5
GM
9292 /* Otherwise try_window_id has returned -1 which means that we
9293 don't want the alternative below this comment to execute. */
a2889657 9294 }
5f5c8ee5
GM
9295 else if (CHARPOS (startp) >= BEGV
9296 && CHARPOS (startp) <= ZV
9297 && PT >= CHARPOS (startp)
9298 && (CHARPOS (startp) < ZV
e9874cee 9299 /* Avoid starting at end of buffer. */
5f5c8ee5 9300 || CHARPOS (startp) == BEGV
8850a573
RS
9301 || (XFASTINT (w->last_modified) >= MODIFF
9302 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 9303 {
5f5c8ee5
GM
9304#if GLYPH_DEBUG
9305 debug_method_add (w, "same window start");
9306#endif
9307
9308 /* Try to redisplay starting at same place as before.
9309 If point has not moved off frame, accept the results. */
9310 if (!current_matrix_up_to_date_p
9311 /* Don't use try_window_reusing_current_matrix in this case
15e26c76
GM
9312 because a window scroll function can have changed the
9313 buffer. */
5f5c8ee5
GM
9314 || !NILP (Vwindow_scroll_functions)
9315 || MINI_WINDOW_P (w)
9316 || !try_window_reusing_current_matrix (w))
9317 {
9318 IF_DEBUG (debug_method_add (w, "1"));
9319 try_window (window, startp);
9320 }
9321
9322 if (fonts_changed_p)
9323 goto restore_buffers;
9324
9325 if (w->cursor.vpos >= 0)
aa6d10fa 9326 {
5f5c8ee5
GM
9327 if (!just_this_one_p
9328 || current_buffer->clip_changed
9142dd5b 9329 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
9330 /* Forget any recorded base line for line number display. */
9331 w->base_line_number = Qnil;
5f5c8ee5
GM
9332
9333 make_cursor_line_fully_visible (w);
aa6d10fa
RS
9334 goto done;
9335 }
a2889657 9336 else
5f5c8ee5 9337 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
9338 }
9339
5f5c8ee5
GM
9340 try_to_scroll:
9341
c2213350 9342 XSETFASTINT (w->last_modified, 0);
8850a573 9343 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5 9344
e481f960
RS
9345 /* Redisplay the mode line. Select the buffer properly for that. */
9346 if (!update_mode_line)
9347 {
e481f960
RS
9348 update_mode_line = 1;
9349 w->update_mode_line = Qt;
9350 }
a2889657 9351
5f5c8ee5
GM
9352 /* Try to scroll by specified few lines. */
9353 if ((scroll_conservatively
9354 || scroll_step
9355 || temp_scroll_step
9356 || NUMBERP (current_buffer->scroll_up_aggressively)
9357 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 9358 && !current_buffer->clip_changed
5f5c8ee5
GM
9359 && CHARPOS (startp) >= BEGV
9360 && CHARPOS (startp) <= ZV)
0789adb2 9361 {
5f5c8ee5
GM
9362 /* The function returns -1 if new fonts were loaded, 1 if
9363 successful, 0 if not successful. */
9364 int rc = try_scrolling (window, just_this_one_p,
9365 scroll_conservatively,
9366 scroll_step,
9367 temp_scroll_step);
9368 if (rc > 0)
9369 goto done;
9370 else if (rc < 0)
9371 goto restore_buffers;
9372 }
f9c8af06 9373
5f5c8ee5 9374 /* Finally, just choose place to start which centers point */
5936754e 9375
5f5c8ee5 9376 recenter:
44173109 9377
5f5c8ee5
GM
9378#if GLYPH_DEBUG
9379 debug_method_add (w, "recenter");
9380#endif
0789adb2 9381
5f5c8ee5 9382 /* w->vscroll = 0; */
0789adb2 9383
5f5c8ee5
GM
9384 /* Forget any previously recorded base line for line number display. */
9385 if (!current_matrix_up_to_date_p
9386 || current_buffer->clip_changed)
9387 w->base_line_number = Qnil;
9388
9389 /* Move backward half the height of the window. */
9390 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
9391 it.current_y = it.last_visible_y;
9392 move_it_vertically_backward (&it, it.last_visible_y / 2);
9393 xassert (IT_CHARPOS (it) >= BEGV);
9394
9395 /* The function move_it_vertically_backward may move over more
9396 than the specified y-distance. If it->w is small, e.g. a
9397 mini-buffer window, we may end up in front of the window's
9398 display area. Start displaying at the start of the line
9399 containing PT in this case. */
9400 if (it.current_y <= 0)
9401 {
9402 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
9403 move_it_vertically (&it, 0);
9404 xassert (IT_CHARPOS (it) <= PT);
9405 it.current_y = 0;
0789adb2
RS
9406 }
9407
5f5c8ee5
GM
9408 it.current_x = it.hpos = 0;
9409
9410 /* Set startp here explicitly in case that helps avoid an infinite loop
9411 in case the window-scroll-functions functions get errors. */
9412 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
9413
9414 /* Run scroll hooks. */
9415 startp = run_window_scroll_functions (window, it.current.pos);
9416
9417 /* Redisplay the window. */
9418 if (!current_matrix_up_to_date_p
9419 || windows_or_buffers_changed
9420 /* Don't use try_window_reusing_current_matrix in this case
9421 because it can have changed the buffer. */
9422 || !NILP (Vwindow_scroll_functions)
9423 || !just_this_one_p
9424 || MINI_WINDOW_P (w)
9425 || !try_window_reusing_current_matrix (w))
9426 try_window (window, startp);
9427
9428 /* If new fonts have been loaded (due to fontsets), give up. We
9429 have to start a new redisplay since we need to re-adjust glyph
9430 matrices. */
9431 if (fonts_changed_p)
9432 goto restore_buffers;
9433
9434 /* If cursor did not appear assume that the middle of the window is
9435 in the first line of the window. Do it again with the next line.
9436 (Imagine a window of height 100, displaying two lines of height
9437 60. Moving back 50 from it->last_visible_y will end in the first
9438 line.) */
9439 if (w->cursor.vpos < 0)
a2889657 9440 {
5f5c8ee5
GM
9441 if (!NILP (w->window_end_valid)
9442 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 9443 {
5f5c8ee5
GM
9444 clear_glyph_matrix (w->desired_matrix);
9445 move_it_by_lines (&it, 1, 0);
9446 try_window (window, it.current.pos);
a2889657 9447 }
5f5c8ee5 9448 else if (PT < IT_CHARPOS (it))
a2889657 9449 {
5f5c8ee5
GM
9450 clear_glyph_matrix (w->desired_matrix);
9451 move_it_by_lines (&it, -1, 0);
9452 try_window (window, it.current.pos);
9453 }
9454 else
9455 {
9456 /* Not much we can do about it. */
a2889657 9457 }
a2889657 9458 }
010494d0 9459
5f5c8ee5
GM
9460 /* Consider the following case: Window starts at BEGV, there is
9461 invisible, intangible text at BEGV, so that display starts at
9462 some point START > BEGV. It can happen that we are called with
9463 PT somewhere between BEGV and START. Try to handle that case. */
9464 if (w->cursor.vpos < 0)
835766b6 9465 {
5f5c8ee5
GM
9466 struct glyph_row *row = w->current_matrix->rows;
9467 if (row->mode_line_p)
9468 ++row;
9469 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 9470 }
5f5c8ee5
GM
9471
9472 make_cursor_line_fully_visible (w);
b5174a51 9473
74d481ac
GM
9474 done:
9475
5f5c8ee5
GM
9476 SET_TEXT_POS_FROM_MARKER (startp, w->start);
9477 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
9478 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
9479 ? Qt : Qnil);
a2889657 9480
5f5c8ee5 9481 /* Display the mode line, if we must. */
e481f960 9482 if ((update_mode_line
aa6d10fa 9483 /* If window not full width, must redo its mode line
5f5c8ee5
GM
9484 if (a) the window to its side is being redone and
9485 (b) we do a frame-based redisplay. This is a consequence
9486 of how inverted lines are drawn in frame-based redisplay. */
9487 || (!just_this_one_p
9488 && !FRAME_WINDOW_P (f)
9489 && !WINDOW_FULL_WIDTH_P (w))
9490 /* Line number to display. */
155ef550 9491 || INTEGERP (w->base_line_pos)
5f5c8ee5 9492 /* Column number is displayed and different from the one displayed. */
155ef550
KH
9493 || (!NILP (w->column_number_displayed)
9494 && XFASTINT (w->column_number_displayed) != current_column ()))
5f5c8ee5
GM
9495 /* This means that the window has a mode line. */
9496 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 9497 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 9498 {
5da11938
GM
9499 Lisp_Object old_selected_frame;
9500
9501 old_selected_frame = selected_frame;
9502
5da11938 9503 XSETFRAME (selected_frame, f);
5f5c8ee5 9504 display_mode_lines (w);
5da11938 9505 selected_frame = old_selected_frame;
5f5c8ee5
GM
9506
9507 /* If mode line height has changed, arrange for a thorough
9508 immediate redisplay using the correct mode line height. */
9509 if (WINDOW_WANTS_MODELINE_P (w)
9510 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 9511 {
5f5c8ee5
GM
9512 fonts_changed_p = 1;
9513 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
9514 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 9515 }
5f5c8ee5
GM
9516
9517 /* If top line height has changed, arrange for a thorough
9518 immediate redisplay using the correct mode line height. */
045dee35
GM
9519 if (WINDOW_WANTS_HEADER_LINE_P (w)
9520 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
9521 {
9522 fonts_changed_p = 1;
045dee35
GM
9523 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
9524 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9525 }
9526
9527 if (fonts_changed_p)
9528 goto restore_buffers;
5ba50c51 9529 }
5f5c8ee5
GM
9530
9531 if (!line_number_displayed
9532 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
9533 {
9534 w->base_line_pos = Qnil;
9535 w->base_line_number = Qnil;
9536 }
a2889657 9537
5f5c8ee5
GM
9538 finish_menu_bars:
9539
7ce2c095 9540 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 9541 if (update_mode_line
5f5c8ee5
GM
9542 && EQ (FRAME_SELECTED_WINDOW (f), window))
9543 {
9544 int redisplay_menu_p = 0;
9545
9546 if (FRAME_WINDOW_P (f))
9547 {
dc937613 9548#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
5f5c8ee5 9549 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 9550#else
5f5c8ee5 9551 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 9552#endif
5f5c8ee5
GM
9553 }
9554 else
9555 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
9556
9557 if (redisplay_menu_p)
9558 display_menu_bar (w);
9559
9560#ifdef HAVE_WINDOW_SYSTEM
e037b9ec
GM
9561 if (WINDOWP (f->tool_bar_window)
9562 && (FRAME_TOOL_BAR_LINES (f) > 0
9563 || auto_resize_tool_bars_p))
9564 redisplay_tool_bar (f);
5f5c8ee5
GM
9565#endif
9566 }
7ce2c095 9567
88f22aff 9568 finish_scroll_bars:
5f5c8ee5 9569
88f22aff 9570 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 9571 {
b1d1124b 9572 int start, end, whole;
30c566e4 9573
b1d1124b 9574 /* Calculate the start and end positions for the current window.
3505ea70
JB
9575 At some point, it would be nice to choose between scrollbars
9576 which reflect the whole buffer size, with special markers
9577 indicating narrowing, and scrollbars which reflect only the
9578 visible region.
9579
5f5c8ee5 9580 Note that mini-buffers sometimes aren't displaying any text. */
c6e89d6c 9581 if (!MINI_WINDOW_P (w)
5f5c8ee5 9582 || (w == XWINDOW (minibuf_window)
c6e89d6c 9583 && NILP (echo_area_buffer[0])))
b1d1124b 9584 {
8a9311d7 9585 whole = ZV - BEGV;
4d641a15 9586 start = marker_position (w->start) - BEGV;
b1d1124b
JB
9587 /* I don't think this is guaranteed to be right. For the
9588 moment, we'll pretend it is. */
5f5c8ee5 9589 end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
3505ea70 9590
5f5c8ee5
GM
9591 if (end < start)
9592 end = start;
9593 if (whole < (end - start))
9594 whole = end - start;
b1d1124b
JB
9595 }
9596 else
9597 start = end = whole = 0;
30c566e4 9598
88f22aff 9599 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 9600 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 9601
5f5c8ee5
GM
9602 /* Note that we actually used the scroll bar attached to this
9603 window, so it shouldn't be deleted at the end of redisplay. */
88f22aff 9604 (*redeem_scroll_bar_hook) (w);
30c566e4 9605 }
b1d1124b 9606
5f5c8ee5
GM
9607 restore_buffers:
9608
9609 /* Restore current_buffer and value of point in it. */
9610 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
6a93695f 9611 set_buffer_internal_1 (old);
5f5c8ee5 9612 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
9613
9614 unbind_to (count, Qnil);
a2889657 9615}
a2889657 9616
5f5c8ee5
GM
9617
9618/* Build the complete desired matrix of WINDOW with a window start
9619 buffer position POS. Value is non-zero if successful. It is zero
9620 if fonts were loaded during redisplay which makes re-adjusting
9621 glyph matrices necessary. */
9622
9623int
a2889657
JB
9624try_window (window, pos)
9625 Lisp_Object window;
5f5c8ee5
GM
9626 struct text_pos pos;
9627{
9628 struct window *w = XWINDOW (window);
9629 struct it it;
9630 struct glyph_row *last_text_row = NULL;
9cbab4ff 9631
5f5c8ee5
GM
9632 /* Make POS the new window start. */
9633 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 9634
5f5c8ee5
GM
9635 /* Mark cursor position as unknown. No overlay arrow seen. */
9636 w->cursor.vpos = -1;
a2889657 9637 overlay_arrow_seen = 0;
642eefc6 9638
5f5c8ee5
GM
9639 /* Initialize iterator and info to start at POS. */
9640 start_display (&it, w, pos);
a2889657 9641
5f5c8ee5
GM
9642 /* Display all lines of W. */
9643 while (it.current_y < it.last_visible_y)
9644 {
9645 if (display_line (&it))
9646 last_text_row = it.glyph_row - 1;
9647 if (fonts_changed_p)
9648 return 0;
9649 }
a2889657 9650
5f5c8ee5
GM
9651 /* If bottom moved off end of frame, change mode line percentage. */
9652 if (XFASTINT (w->window_end_pos) <= 0
9653 && Z != IT_CHARPOS (it))
a2889657
JB
9654 w->update_mode_line = Qt;
9655
5f5c8ee5
GM
9656 /* Set window_end_pos to the offset of the last character displayed
9657 on the window from the end of current_buffer. Set
9658 window_end_vpos to its row number. */
9659 if (last_text_row)
9660 {
9661 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
9662 w->window_end_bytepos
9663 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9664 XSETFASTINT (w->window_end_pos,
9665 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9666 XSETFASTINT (w->window_end_vpos,
9667 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9668 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
9669 ->displays_text_p);
9670 }
9671 else
9672 {
9673 w->window_end_bytepos = 0;
9674 XSETFASTINT (w->window_end_pos, 0);
9675 XSETFASTINT (w->window_end_vpos, 0);
9676 }
9677
a2889657
JB
9678 /* But that is not valid info until redisplay finishes. */
9679 w->window_end_valid = Qnil;
5f5c8ee5 9680 return 1;
a2889657 9681}
5f5c8ee5
GM
9682
9683
a2889657 9684\f
5f5c8ee5
GM
9685/************************************************************************
9686 Window redisplay reusing current matrix when buffer has not changed
9687 ************************************************************************/
9688
9689/* Try redisplay of window W showing an unchanged buffer with a
9690 different window start than the last time it was displayed by
9691 reusing its current matrix. Value is non-zero if successful.
9692 W->start is the new window start. */
a2889657
JB
9693
9694static int
5f5c8ee5
GM
9695try_window_reusing_current_matrix (w)
9696 struct window *w;
a2889657 9697{
5f5c8ee5
GM
9698 struct frame *f = XFRAME (w->frame);
9699 struct glyph_row *row, *bottom_row;
9700 struct it it;
9701 struct run run;
9702 struct text_pos start, new_start;
9703 int nrows_scrolled, i;
9704 struct glyph_row *last_text_row;
9705 struct glyph_row *last_reused_text_row;
9706 struct glyph_row *start_row;
9707 int start_vpos, min_y, max_y;
9708
d18354b6
GM
9709
9710 if (/* This function doesn't handle terminal frames. */
9711 !FRAME_WINDOW_P (f)
9712 /* Don't try to reuse the display if windows have been split
9713 or such. */
9714 || windows_or_buffers_changed)
5f5c8ee5 9715 return 0;
a2889657 9716
5f5c8ee5
GM
9717 /* Can't do this if region may have changed. */
9718 if ((!NILP (Vtransient_mark_mode)
9719 && !NILP (current_buffer->mark_active))
8f897821
GM
9720 || !NILP (w->region_showing)
9721 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 9722 return 0;
a2889657 9723
5f5c8ee5 9724 /* If top-line visibility has changed, give up. */
045dee35
GM
9725 if (WINDOW_WANTS_HEADER_LINE_P (w)
9726 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
9727 return 0;
9728
9729 /* Give up if old or new display is scrolled vertically. We could
9730 make this function handle this, but right now it doesn't. */
9731 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9732 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
9733 return 0;
9734
9735 /* The variable new_start now holds the new window start. The old
9736 start `start' can be determined from the current matrix. */
9737 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
9738 start = start_row->start.pos;
9739 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 9740
5f5c8ee5
GM
9741 /* Clear the desired matrix for the display below. */
9742 clear_glyph_matrix (w->desired_matrix);
9743
9744 if (CHARPOS (new_start) <= CHARPOS (start))
9745 {
9746 int first_row_y;
9747
9748 IF_DEBUG (debug_method_add (w, "twu1"));
9749
9750 /* Display up to a row that can be reused. The variable
9751 last_text_row is set to the last row displayed that displays
9752 text. */
9753 start_display (&it, w, new_start);
9754 first_row_y = it.current_y;
9755 w->cursor.vpos = -1;
9756 last_text_row = last_reused_text_row = NULL;
9757 while (it.current_y < it.last_visible_y
9758 && IT_CHARPOS (it) < CHARPOS (start)
9759 && !fonts_changed_p)
9760 if (display_line (&it))
9761 last_text_row = it.glyph_row - 1;
9762
9763 /* A value of current_y < last_visible_y means that we stopped
9764 at the previous window start, which in turn means that we
9765 have at least one reusable row. */
9766 if (it.current_y < it.last_visible_y)
a2889657 9767 {
5f5c8ee5
GM
9768 nrows_scrolled = it.vpos;
9769
9770 /* Find PT if not already found in the lines displayed. */
9771 if (w->cursor.vpos < 0)
a2889657 9772 {
5f5c8ee5
GM
9773 int dy = it.current_y - first_row_y;
9774
9775 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9776 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9777 {
9778 if (PT >= MATRIX_ROW_START_CHARPOS (row)
9779 && PT < MATRIX_ROW_END_CHARPOS (row))
9780 {
9781 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
9782 dy, nrows_scrolled);
9783 break;
9784 }
9785
9786 if (MATRIX_ROW_BOTTOM_Y (row) + dy >= it.last_visible_y)
9787 break;
9788
9789 ++row;
9790 }
9791
9792 /* Give up if point was not found. This shouldn't
9793 happen often; not more often than with try_window
9794 itself. */
9795 if (w->cursor.vpos < 0)
9796 {
9797 clear_glyph_matrix (w->desired_matrix);
9798 return 0;
9799 }
a2889657 9800 }
5f5c8ee5
GM
9801
9802 /* Scroll the display. Do it before the current matrix is
9803 changed. The problem here is that update has not yet
9804 run, i.e. part of the current matrix is not up to date.
9805 scroll_run_hook will clear the cursor, and use the
9806 current matrix to get the height of the row the cursor is
9807 in. */
9808 run.current_y = first_row_y;
9809 run.desired_y = it.current_y;
9810 run.height = it.last_visible_y - it.current_y;
15e26c76
GM
9811 if (run.height > 0
9812 && run.current_y != run.desired_y)
a2889657 9813 {
5f5c8ee5
GM
9814 update_begin (f);
9815 rif->update_window_begin_hook (w);
64d1e7d3 9816 rif->clear_mouse_face (w);
5f5c8ee5 9817 rif->scroll_run_hook (w, &run);
64d1e7d3 9818 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5 9819 update_end (f);
a2889657 9820 }
5f5c8ee5
GM
9821
9822 /* Shift current matrix down by nrows_scrolled lines. */
9823 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9824 rotate_matrix (w->current_matrix,
9825 start_vpos,
9826 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
9827 nrows_scrolled);
9828
9829 /* Disable lines not reused. */
9830 for (i = 0; i < it.vpos; ++i)
9831 MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
9832
9833 /* Re-compute Y positions. */
9834 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix) + nrows_scrolled;
045dee35 9835 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9836 max_y = it.last_visible_y;
9837 while (row < bottom_row)
d2f84654 9838 {
5f5c8ee5
GM
9839 row->y = it.current_y;
9840
9841 if (row->y < min_y)
9842 row->visible_height = row->height - (min_y - row->y);
9843 else if (row->y + row->height > max_y)
9844 row->visible_height
9845 = row->height - (row->y + row->height - max_y);
9846 else
9847 row->visible_height = row->height;
9848
9849 it.current_y += row->height;
9850 ++it.vpos;
9851
9852 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9853 last_reused_text_row = row;
9854 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
9855 break;
9856 ++row;
d2f84654 9857 }
a2889657 9858 }
5f5c8ee5
GM
9859
9860 /* Update window_end_pos etc.; last_reused_text_row is the last
9861 reused row from the current matrix containing text, if any.
9862 The value of last_text_row is the last displayed line
9863 containing text. */
9864 if (last_reused_text_row)
a2889657 9865 {
5f5c8ee5
GM
9866 w->window_end_bytepos
9867 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
9868 XSETFASTINT (w->window_end_pos,
9869 Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
9870 XSETFASTINT (w->window_end_vpos,
9871 MATRIX_ROW_VPOS (last_reused_text_row,
9872 w->current_matrix));
a2889657 9873 }
5f5c8ee5
GM
9874 else if (last_text_row)
9875 {
9876 w->window_end_bytepos
9877 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9878 XSETFASTINT (w->window_end_pos,
9879 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9880 XSETFASTINT (w->window_end_vpos,
9881 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9882 }
9883 else
9884 {
9885 /* This window must be completely empty. */
9886 w->window_end_bytepos = 0;
9887 XSETFASTINT (w->window_end_pos, 0);
9888 XSETFASTINT (w->window_end_vpos, 0);
9889 }
9890 w->window_end_valid = Qnil;
a2889657 9891
5f5c8ee5
GM
9892 /* Update hint: don't try scrolling again in update_window. */
9893 w->desired_matrix->no_scrolling_p = 1;
9894
9895#if GLYPH_DEBUG
9896 debug_method_add (w, "try_window_reusing_current_matrix 1");
9897#endif
9898 return 1;
a2889657 9899 }
5f5c8ee5
GM
9900 else if (CHARPOS (new_start) > CHARPOS (start))
9901 {
9902 struct glyph_row *pt_row, *row;
9903 struct glyph_row *first_reusable_row;
9904 struct glyph_row *first_row_to_display;
9905 int dy;
9906 int yb = window_text_bottom_y (w);
9907
9908 IF_DEBUG (debug_method_add (w, "twu2"));
9909
9910 /* Find the row starting at new_start, if there is one. Don't
9911 reuse a partially visible line at the end. */
9912 first_reusable_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9913 while (first_reusable_row->enabled_p
9914 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
9915 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9916 < CHARPOS (new_start)))
9917 ++first_reusable_row;
9918
9919 /* Give up if there is no row to reuse. */
9920 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
9921 || !first_reusable_row->enabled_p
9922 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9923 != CHARPOS (new_start)))
5f5c8ee5
GM
9924 return 0;
9925
5f5c8ee5
GM
9926 /* We can reuse fully visible rows beginning with
9927 first_reusable_row to the end of the window. Set
9928 first_row_to_display to the first row that cannot be reused.
9929 Set pt_row to the row containing point, if there is any. */
9930 first_row_to_display = first_reusable_row;
9931 pt_row = NULL;
9932 while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb)
9933 {
9934 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
9935 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
9936 pt_row = first_row_to_display;
a2889657 9937
5f5c8ee5
GM
9938 ++first_row_to_display;
9939 }
a2889657 9940
5f5c8ee5
GM
9941 /* Start displaying at the start of first_row_to_display. */
9942 xassert (first_row_to_display->y < yb);
9943 init_to_row_start (&it, w, first_row_to_display);
9944 nrows_scrolled = MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix);
9945 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
9946 - nrows_scrolled);
9947 it.current_y = first_row_to_display->y - first_reusable_row->y;
9948
9949 /* Display lines beginning with first_row_to_display in the
9950 desired matrix. Set last_text_row to the last row displayed
9951 that displays text. */
9952 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
9953 if (pt_row == NULL)
9954 w->cursor.vpos = -1;
9955 last_text_row = NULL;
9956 while (it.current_y < it.last_visible_y && !fonts_changed_p)
9957 if (display_line (&it))
9958 last_text_row = it.glyph_row - 1;
9959
9960 /* Give up If point isn't in a row displayed or reused. */
9961 if (w->cursor.vpos < 0)
9962 {
9963 clear_glyph_matrix (w->desired_matrix);
9964 return 0;
9965 }
12adba34 9966
5f5c8ee5
GM
9967 /* If point is in a reused row, adjust y and vpos of the cursor
9968 position. */
9969 if (pt_row)
9970 {
9971 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
9972 w->current_matrix);
9973 w->cursor.y -= first_reusable_row->y;
a2889657
JB
9974 }
9975
5f5c8ee5
GM
9976 /* Scroll the display. */
9977 run.current_y = first_reusable_row->y;
045dee35 9978 run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9979 run.height = it.last_visible_y - run.current_y;
9980 if (run.height)
9981 {
9982 struct frame *f = XFRAME (WINDOW_FRAME (w));
9983 update_begin (f);
9984 rif->update_window_begin_hook (w);
64d1e7d3 9985 rif->clear_mouse_face (w);
5f5c8ee5 9986 rif->scroll_run_hook (w, &run);
64d1e7d3 9987 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
9988 update_end (f);
9989 }
a2889657 9990
5f5c8ee5
GM
9991 /* Adjust Y positions of reused rows. */
9992 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9993 row = first_reusable_row;
9994 dy = first_reusable_row->y;
045dee35 9995 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9996 max_y = it.last_visible_y;
9997 while (row < first_row_to_display)
9998 {
9999 row->y -= dy;
10000 if (row->y < min_y)
10001 row->visible_height = row->height - (min_y - row->y);
10002 else if (row->y + row->height > max_y)
10003 row->visible_height
10004 = row->height - (row->y + row->height - max_y);
10005 else
10006 row->visible_height = row->height;
10007 ++row;
10008 }
a2889657 10009
5f5c8ee5
GM
10010 /* Disable rows not reused. */
10011 while (row < bottom_row)
10012 {
10013 row->enabled_p = 0;
10014 ++row;
10015 }
10016
10017 /* Scroll the current matrix. */
10018 xassert (nrows_scrolled > 0);
10019 rotate_matrix (w->current_matrix,
10020 start_vpos,
10021 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
10022 -nrows_scrolled);
10023
10024 /* Adjust window end. A null value of last_text_row means that
10025 the window end is in reused rows which in turn means that
10026 only its vpos can have changed. */
10027 if (last_text_row)
10028 {
10029 w->window_end_bytepos
10030 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
10031 XSETFASTINT (w->window_end_pos,
10032 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10033 XSETFASTINT (w->window_end_vpos,
10034 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
10035 }
10036 else
a2889657 10037 {
e8e536a9 10038 XSETFASTINT (w->window_end_vpos,
5f5c8ee5 10039 XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 10040 }
5f5c8ee5
GM
10041
10042 w->window_end_valid = Qnil;
10043 w->desired_matrix->no_scrolling_p = 1;
10044
10045#if GLYPH_DEBUG
10046 debug_method_add (w, "try_window_reusing_current_matrix 2");
10047#endif
10048 return 1;
a2889657 10049 }
5f5c8ee5
GM
10050
10051 return 0;
10052}
a2889657 10053
a2889657 10054
5f5c8ee5
GM
10055\f
10056/************************************************************************
10057 Window redisplay reusing current matrix when buffer has changed
10058 ************************************************************************/
10059
10060static struct glyph_row *get_last_unchanged_at_beg_row P_ ((struct window *));
10061static struct glyph_row *get_first_unchanged_at_end_row P_ ((struct window *,
10062 int *, int *));
10063static struct glyph_row *
10064find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
10065 struct glyph_row *));
10066
10067
10068/* Return the last row in MATRIX displaying text. If row START is
10069 non-null, start searching with that row. IT gives the dimensions
10070 of the display. Value is null if matrix is empty; otherwise it is
10071 a pointer to the row found. */
10072
10073static struct glyph_row *
10074find_last_row_displaying_text (matrix, it, start)
10075 struct glyph_matrix *matrix;
10076 struct it *it;
10077 struct glyph_row *start;
10078{
10079 struct glyph_row *row, *row_found;
10080
10081 /* Set row_found to the last row in IT->w's current matrix
10082 displaying text. The loop looks funny but think of partially
10083 visible lines. */
10084 row_found = NULL;
10085 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
10086 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
10087 {
10088 xassert (row->enabled_p);
10089 row_found = row;
10090 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
10091 break;
10092 ++row;
a2889657 10093 }
5f5c8ee5
GM
10094
10095 return row_found;
10096}
10097
a2889657 10098
5f5c8ee5
GM
10099/* Return the last row in the current matrix of W that is not affected
10100 by changes at the start of current_buffer that occurred since the
10101 last time W was redisplayed. Value is null if no such row exists.
a2889657 10102
5f5c8ee5
GM
10103 The global variable beg_unchanged has to contain the number of
10104 bytes unchanged at the start of current_buffer. BEG +
10105 beg_unchanged is the buffer position of the first changed byte in
10106 current_buffer. Characters at positions < BEG + beg_unchanged are
10107 at the same buffer positions as they were when the current matrix
10108 was built. */
10109
10110static struct glyph_row *
10111get_last_unchanged_at_beg_row (w)
10112 struct window *w;
10113{
9142dd5b 10114 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
10115 struct glyph_row *row;
10116 struct glyph_row *row_found = NULL;
10117 int yb = window_text_bottom_y (w);
10118
10119 /* Find the last row displaying unchanged text. */
10120 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10121 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
10122 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 10123 {
5f5c8ee5
GM
10124 if (/* If row ends before first_changed_pos, it is unchanged,
10125 except in some case. */
10126 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
10127 /* When row ends in ZV and we write at ZV it is not
10128 unchanged. */
10129 && !row->ends_at_zv_p
10130 /* When first_changed_pos is the end of a continued line,
10131 row is not unchanged because it may be no longer
10132 continued. */
10133 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
10134 && row->continued_p))
10135 row_found = row;
10136
10137 /* Stop if last visible row. */
10138 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
10139 break;
10140
10141 ++row;
a2889657
JB
10142 }
10143
5f5c8ee5 10144 return row_found;
a2889657 10145}
5f5c8ee5
GM
10146
10147
10148/* Find the first glyph row in the current matrix of W that is not
10149 affected by changes at the end of current_buffer since the last
10150 time the window was redisplayed. Return in *DELTA the number of
c59c668a
GM
10151 chars by which buffer positions in unchanged text at the end of
10152 current_buffer must be adjusted. Return in *DELTA_BYTES the
10153 corresponding number of bytes. Value is null if no such row
10154 exists, i.e. all rows are affected by changes. */
5f5c8ee5
GM
10155
10156static struct glyph_row *
10157get_first_unchanged_at_end_row (w, delta, delta_bytes)
10158 struct window *w;
10159 int *delta, *delta_bytes;
a2889657 10160{
5f5c8ee5
GM
10161 struct glyph_row *row;
10162 struct glyph_row *row_found = NULL;
c581d710 10163
5f5c8ee5 10164 *delta = *delta_bytes = 0;
b2a76982 10165
5f5c8ee5
GM
10166 /* A value of window_end_pos >= end_unchanged means that the window
10167 end is in the range of changed text. If so, there is no
10168 unchanged row at the end of W's current matrix. */
10169 xassert (!NILP (w->window_end_valid));
9142dd5b 10170 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
10171 return NULL;
10172
10173 /* Set row to the last row in W's current matrix displaying text. */
10174 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
10175
5f5c8ee5
GM
10176 /* If matrix is entirely empty, no unchanged row exists. */
10177 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
10178 {
10179 /* The value of row is the last glyph row in the matrix having a
10180 meaningful buffer position in it. The end position of row
10181 corresponds to window_end_pos. This allows us to translate
10182 buffer positions in the current matrix to current buffer
10183 positions for characters not in changed text. */
10184 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
10185 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
10186 int last_unchanged_pos, last_unchanged_pos_old;
10187 struct glyph_row *first_text_row
10188 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10189
10190 *delta = Z - Z_old;
10191 *delta_bytes = Z_BYTE - Z_BYTE_old;
10192
10193 /* Set last_unchanged_pos to the buffer position of the last
10194 character in the buffer that has not been changed. Z is the
10195 index + 1 of the last byte in current_buffer, i.e. by
10196 subtracting end_unchanged we get the index of the last
10197 unchanged character, and we have to add BEG to get its buffer
10198 position. */
9142dd5b 10199 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5
GM
10200 last_unchanged_pos_old = last_unchanged_pos - *delta;
10201
10202 /* Search backward from ROW for a row displaying a line that
10203 starts at a minimum position >= last_unchanged_pos_old. */
10204 while (row >= first_text_row)
10205 {
10206 xassert (row->enabled_p);
10207 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row));
10208
10209 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
10210 row_found = row;
10211 --row;
10212 }
10213 }
10214
10215 xassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
10216 return row_found;
c581d710
RS
10217}
10218
c581d710 10219
5f5c8ee5
GM
10220/* Make sure that glyph rows in the current matrix of window W
10221 reference the same glyph memory as corresponding rows in the
10222 frame's frame matrix. This function is called after scrolling W's
10223 current matrix on a terminal frame in try_window_id and
10224 try_window_reusing_current_matrix. */
10225
10226static void
10227sync_frame_with_window_matrix_rows (w)
10228 struct window *w;
c581d710 10229{
5f5c8ee5
GM
10230 struct frame *f = XFRAME (w->frame);
10231 struct glyph_row *window_row, *window_row_end, *frame_row;
10232
10233 /* Preconditions: W must be a leaf window and full-width. Its frame
10234 must have a frame matrix. */
10235 xassert (NILP (w->hchild) && NILP (w->vchild));
10236 xassert (WINDOW_FULL_WIDTH_P (w));
10237 xassert (!FRAME_WINDOW_P (f));
10238
10239 /* If W is a full-width window, glyph pointers in W's current matrix
10240 have, by definition, to be the same as glyph pointers in the
10241 corresponding frame matrix. */
10242 window_row = w->current_matrix->rows;
10243 window_row_end = window_row + w->current_matrix->nrows;
10244 frame_row = f->current_matrix->rows + XFASTINT (w->top);
10245 while (window_row < window_row_end)
659a218f 10246 {
5f5c8ee5 10247 int area;
f002db93 10248
5f5c8ee5
GM
10249 for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
10250 frame_row->glyphs[area] = window_row->glyphs[area];
f002db93
GM
10251
10252 /* Disable frame rows whose corresponding window rows have
10253 been disabled in try_window_id. */
10254 if (!window_row->enabled_p)
10255 frame_row->enabled_p = 0;
10256
5f5c8ee5 10257 ++window_row, ++frame_row;
659a218f 10258 }
a2889657 10259}
5f5c8ee5
GM
10260
10261
e037b9ec
GM
10262/* Find the glyph row in window W containing CHARPOS. Consider all
10263 rows between START and END (not inclusive). END null means search
10264 all rows to the end of the display area of W. Value is the row
10265 containing CHARPOS or null. */
10266
10267static struct glyph_row *
10268row_containing_pos (w, charpos, start, end)
10269 struct window *w;
10270 int charpos;
10271 struct glyph_row *start, *end;
10272{
10273 struct glyph_row *row = start;
10274 int last_y;
10275
10276 /* If we happen to start on a header-line, skip that. */
10277 if (row->mode_line_p)
10278 ++row;
10279
10280 if ((end && row >= end) || !row->enabled_p)
10281 return NULL;
10282
10283 last_y = window_text_bottom_y (w);
10284
10285 while ((end == NULL || row < end)
10286 && (MATRIX_ROW_END_CHARPOS (row) < charpos
10287 /* The end position of a row equals the start
10288 position of the next row. If CHARPOS is there, we
10289 would rather display it in the next line, except
10290 when this line ends in ZV. */
10291 || (MATRIX_ROW_END_CHARPOS (row) == charpos
10292 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
10293 || !row->ends_at_zv_p)))
10294 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
10295 ++row;
10296
10297 /* Give up if CHARPOS not found. */
10298 if ((end && row >= end)
10299 || charpos < MATRIX_ROW_START_CHARPOS (row)
10300 || charpos > MATRIX_ROW_END_CHARPOS (row))
10301 row = NULL;
10302
10303 return row;
10304}
10305
10306
5f5c8ee5
GM
10307/* Try to redisplay window W by reusing its existing display. W's
10308 current matrix must be up to date when this function is called,
10309 i.e. window_end_valid must not be nil.
10310
10311 Value is
10312
10313 1 if display has been updated
10314 0 if otherwise unsuccessful
10315 -1 if redisplay with same window start is known not to succeed
10316
10317 The following steps are performed:
10318
10319 1. Find the last row in the current matrix of W that is not
10320 affected by changes at the start of current_buffer. If no such row
10321 is found, give up.
10322
10323 2. Find the first row in W's current matrix that is not affected by
10324 changes at the end of current_buffer. Maybe there is no such row.
10325
10326 3. Display lines beginning with the row + 1 found in step 1 to the
10327 row found in step 2 or, if step 2 didn't find a row, to the end of
10328 the window.
10329
10330 4. If cursor is not known to appear on the window, give up.
10331
10332 5. If display stopped at the row found in step 2, scroll the
10333 display and current matrix as needed.
10334
10335 6. Maybe display some lines at the end of W, if we must. This can
10336 happen under various circumstances, like a partially visible line
10337 becoming fully visible, or because newly displayed lines are displayed
10338 in smaller font sizes.
10339
10340 7. Update W's window end information. */
10341
10342 /* Check that window end is what we expect it to be. */
12adba34
RS
10343
10344static int
5f5c8ee5 10345try_window_id (w)
12adba34 10346 struct window *w;
12adba34 10347{
5f5c8ee5
GM
10348 struct frame *f = XFRAME (w->frame);
10349 struct glyph_matrix *current_matrix = w->current_matrix;
10350 struct glyph_matrix *desired_matrix = w->desired_matrix;
10351 struct glyph_row *last_unchanged_at_beg_row;
10352 struct glyph_row *first_unchanged_at_end_row;
10353 struct glyph_row *row;
10354 struct glyph_row *bottom_row;
10355 int bottom_vpos;
10356 struct it it;
10357 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
10358 struct text_pos start_pos;
10359 struct run run;
10360 int first_unchanged_at_end_vpos = 0;
10361 struct glyph_row *last_text_row, *last_text_row_at_end;
10362 struct text_pos start;
10363
10364 SET_TEXT_POS_FROM_MARKER (start, w->start);
10365
10366 /* Check pre-conditions. Window end must be valid, otherwise
10367 the current matrix would not be up to date. */
10368 xassert (!NILP (w->window_end_valid));
10369 xassert (FRAME_WINDOW_P (XFRAME (w->frame))
10370 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)));
10371
10372 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
10373 only if buffer has really changed. The reason is that the gap is
10374 initially at Z for freshly visited files. The code below would
10375 set end_unchanged to 0 in that case. */
28ee91c0
GM
10376 if (MODIFF > SAVE_MODIFF
10377 /* This seems to happen sometimes after saving a buffer. */
10378 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
5f5c8ee5 10379 {
9142dd5b
GM
10380 if (GPT - BEG < BEG_UNCHANGED)
10381 BEG_UNCHANGED = GPT - BEG;
10382 if (Z - GPT < END_UNCHANGED)
10383 END_UNCHANGED = Z - GPT;
5f5c8ee5 10384 }
bf9249e3 10385
5f5c8ee5
GM
10386 /* If window starts after a line end, and the last change is in
10387 front of that newline, then changes don't affect the display.
f2d86d7a
GM
10388 This case happens with stealth-fontification. Note that although
10389 the display is unchanged, glyph positions in the matrix have to
10390 be adjusted, of course. */
5f5c8ee5
GM
10391 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
10392 if (CHARPOS (start) > BEGV
9142dd5b 10393 && Z - END_UNCHANGED < CHARPOS (start) - 1
5f5c8ee5
GM
10394 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
10395 && PT < MATRIX_ROW_END_CHARPOS (row))
10396 {
f2d86d7a
GM
10397 struct glyph_row *r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
10398 int delta = CHARPOS (start) - MATRIX_ROW_START_CHARPOS (r0);
10399
10400 if (delta)
10401 {
10402 struct glyph_row *r1 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
10403 int delta_bytes = BYTEPOS (start) - MATRIX_ROW_START_BYTEPOS (r0);
10404
10405 increment_matrix_positions (w->current_matrix,
10406 MATRIX_ROW_VPOS (r0, current_matrix),
10407 MATRIX_ROW_VPOS (r1, current_matrix),
10408 delta, delta_bytes);
10409 }
10410
10411#if 0 /* If changes are all in front of the window start, the
10412 distance of the last displayed glyph from Z hasn't
10413 changed. */
5f5c8ee5
GM
10414 w->window_end_pos
10415 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
10416 w->window_end_bytepos
6fc556fd 10417 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
f2d86d7a
GM
10418#endif
10419
5f5c8ee5
GM
10420 return 1;
10421 }
10422
10423 /* Return quickly if changes are all below what is displayed in the
10424 window, and if PT is in the window. */
9142dd5b 10425 if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row)
5f5c8ee5
GM
10426 && PT < MATRIX_ROW_END_CHARPOS (row))
10427 {
10428 /* We have to update window end positions because the buffer's
10429 size has changed. */
10430 w->window_end_pos
10431 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
10432 w->window_end_bytepos
6fc556fd 10433 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
ef121659
GM
10434
10435 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10436 row = row_containing_pos (w, PT, row, NULL);
10437 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
10438 return 2;
5f5c8ee5
GM
10439 }
10440
10441 /* Check that window start agrees with the start of the first glyph
10442 row in its current matrix. Check this after we know the window
10443 start is not in changed text, otherwise positions would not be
10444 comparable. */
10445 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10446 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
10447 return 0;
10448
5f5c8ee5
GM
10449 /* Compute the position at which we have to start displaying new
10450 lines. Some of the lines at the top of the window might be
10451 reusable because they are not displaying changed text. Find the
10452 last row in W's current matrix not affected by changes at the
10453 start of current_buffer. Value is null if changes start in the
10454 first line of window. */
10455 last_unchanged_at_beg_row = get_last_unchanged_at_beg_row (w);
10456 if (last_unchanged_at_beg_row)
10457 {
10458 init_to_row_end (&it, w, last_unchanged_at_beg_row);
10459 start_pos = it.current.pos;
10460
10461 /* Start displaying new lines in the desired matrix at the same
10462 vpos we would use in the current matrix, i.e. below
10463 last_unchanged_at_beg_row. */
10464 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
10465 current_matrix);
10466 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10467 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
10468
10469 xassert (it.hpos == 0 && it.current_x == 0);
10470 }
10471 else
10472 {
10473 /* There are no reusable lines at the start of the window.
10474 Start displaying in the first line. */
10475 start_display (&it, w, start);
10476 start_pos = it.current.pos;
10477 }
10478
5f5c8ee5
GM
10479 /* Find the first row that is not affected by changes at the end of
10480 the buffer. Value will be null if there is no unchanged row, in
10481 which case we must redisplay to the end of the window. delta
10482 will be set to the value by which buffer positions beginning with
10483 first_unchanged_at_end_row have to be adjusted due to text
10484 changes. */
10485 first_unchanged_at_end_row
10486 = get_first_unchanged_at_end_row (w, &delta, &delta_bytes);
10487 IF_DEBUG (debug_delta = delta);
10488 IF_DEBUG (debug_delta_bytes = delta_bytes);
10489
10490 /* Set stop_pos to the buffer position up to which we will have to
10491 display new lines. If first_unchanged_at_end_row != NULL, this
10492 is the buffer position of the start of the line displayed in that
10493 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
10494 that we don't stop at a buffer position. */
10495 stop_pos = 0;
10496 if (first_unchanged_at_end_row)
10497 {
10498 xassert (last_unchanged_at_beg_row == NULL
10499 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
10500
10501 /* If this is a continuation line, move forward to the next one
10502 that isn't. Changes in lines above affect this line.
10503 Caution: this may move first_unchanged_at_end_row to a row
10504 not displaying text. */
10505 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
10506 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
10507 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
10508 < it.last_visible_y))
10509 ++first_unchanged_at_end_row;
10510
10511 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
10512 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
10513 >= it.last_visible_y))
10514 first_unchanged_at_end_row = NULL;
10515 else
10516 {
10517 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
10518 + delta);
10519 first_unchanged_at_end_vpos
10520 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 10521 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
10522 }
10523 }
10524 else if (last_unchanged_at_beg_row == NULL)
10525 return 0;
10526
10527
10528#if GLYPH_DEBUG
10529
10530 /* Either there is no unchanged row at the end, or the one we have
10531 now displays text. This is a necessary condition for the window
10532 end pos calculation at the end of this function. */
10533 xassert (first_unchanged_at_end_row == NULL
10534 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
10535
10536 debug_last_unchanged_at_beg_vpos
10537 = (last_unchanged_at_beg_row
10538 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
10539 : -1);
10540 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
10541
10542#endif /* GLYPH_DEBUG != 0 */
10543
10544
10545 /* Display new lines. Set last_text_row to the last new line
10546 displayed which has text on it, i.e. might end up as being the
10547 line where the window_end_vpos is. */
10548 w->cursor.vpos = -1;
10549 last_text_row = NULL;
10550 overlay_arrow_seen = 0;
10551 while (it.current_y < it.last_visible_y
10552 && !fonts_changed_p
10553 && (first_unchanged_at_end_row == NULL
10554 || IT_CHARPOS (it) < stop_pos))
10555 {
10556 if (display_line (&it))
10557 last_text_row = it.glyph_row - 1;
10558 }
10559
10560 if (fonts_changed_p)
10561 return -1;
10562
10563
10564 /* Compute differences in buffer positions, y-positions etc. for
10565 lines reused at the bottom of the window. Compute what we can
10566 scroll. */
ca42b2e8
GM
10567 if (first_unchanged_at_end_row
10568 /* No lines reused because we displayed everything up to the
10569 bottom of the window. */
10570 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
10571 {
10572 dvpos = (it.vpos
10573 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
10574 current_matrix));
10575 dy = it.current_y - first_unchanged_at_end_row->y;
10576 run.current_y = first_unchanged_at_end_row->y;
10577 run.desired_y = run.current_y + dy;
10578 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
10579 }
10580 else
ca42b2e8
GM
10581 {
10582 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
10583 first_unchanged_at_end_row = NULL;
10584 }
5f5c8ee5
GM
10585 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
10586
8f8ba186 10587
5f5c8ee5
GM
10588 /* Find the cursor if not already found. We have to decide whether
10589 PT will appear on this window (it sometimes doesn't, but this is
10590 not a very frequent case.) This decision has to be made before
10591 the current matrix is altered. A value of cursor.vpos < 0 means
10592 that PT is either in one of the lines beginning at
10593 first_unchanged_at_end_row or below the window. Don't care for
10594 lines that might be displayed later at the window end; as
10595 mentioned, this is not a frequent case. */
10596 if (w->cursor.vpos < 0)
10597 {
5f5c8ee5
GM
10598 /* Cursor in unchanged rows at the top? */
10599 if (PT < CHARPOS (start_pos)
10600 && last_unchanged_at_beg_row)
10601 {
e037b9ec
GM
10602 row = row_containing_pos (w, PT,
10603 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
10604 last_unchanged_at_beg_row + 1);
10605 xassert (row && row <= last_unchanged_at_beg_row);
5f5c8ee5
GM
10606 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
10607 }
10608
10609 /* Start from first_unchanged_at_end_row looking for PT. */
10610 else if (first_unchanged_at_end_row)
10611 {
e037b9ec
GM
10612 row = row_containing_pos (w, PT - delta,
10613 first_unchanged_at_end_row, NULL);
10614 if (row)
468155d7
GM
10615 set_cursor_from_row (w, row, w->current_matrix, delta,
10616 delta_bytes, dy, dvpos);
5f5c8ee5
GM
10617 }
10618
10619 /* Give up if cursor was not found. */
10620 if (w->cursor.vpos < 0)
10621 {
10622 clear_glyph_matrix (w->desired_matrix);
10623 return -1;
10624 }
10625 }
10626
10627 /* Don't let the cursor end in the scroll margins. */
10628 {
10629 int this_scroll_margin, cursor_height;
10630
10631 this_scroll_margin = max (0, scroll_margin);
10632 this_scroll_margin = min (this_scroll_margin,
10633 XFASTINT (w->height) / 4);
10634 this_scroll_margin *= CANON_Y_UNIT (it.f);
10635 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
10636
10637 if ((w->cursor.y < this_scroll_margin
10638 && CHARPOS (start) > BEGV)
10639 /* Don't take scroll margin into account at the bottom because
10640 old redisplay didn't do it either. */
10641 || w->cursor.y + cursor_height > it.last_visible_y)
10642 {
10643 w->cursor.vpos = -1;
10644 clear_glyph_matrix (w->desired_matrix);
10645 return -1;
10646 }
10647 }
10648
10649 /* Scroll the display. Do it before changing the current matrix so
10650 that xterm.c doesn't get confused about where the cursor glyph is
10651 found. */
fa77249f 10652 if (dy && run.height)
5f5c8ee5
GM
10653 {
10654 update_begin (f);
10655
10656 if (FRAME_WINDOW_P (f))
10657 {
10658 rif->update_window_begin_hook (w);
64d1e7d3 10659 rif->clear_mouse_face (w);
5f5c8ee5 10660 rif->scroll_run_hook (w, &run);
64d1e7d3 10661 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
10662 }
10663 else
10664 {
10665 /* Terminal frame. In this case, dvpos gives the number of
10666 lines to scroll by; dvpos < 0 means scroll up. */
10667 int first_unchanged_at_end_vpos
10668 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
10669 int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
10670 int end = XFASTINT (w->top) + window_internal_height (w);
10671
10672 /* Perform the operation on the screen. */
10673 if (dvpos > 0)
10674 {
10675 /* Scroll last_unchanged_at_beg_row to the end of the
10676 window down dvpos lines. */
10677 set_terminal_window (end);
10678
10679 /* On dumb terminals delete dvpos lines at the end
10680 before inserting dvpos empty lines. */
10681 if (!scroll_region_ok)
10682 ins_del_lines (end - dvpos, -dvpos);
10683
10684 /* Insert dvpos empty lines in front of
10685 last_unchanged_at_beg_row. */
10686 ins_del_lines (from, dvpos);
10687 }
10688 else if (dvpos < 0)
10689 {
10690 /* Scroll up last_unchanged_at_beg_vpos to the end of
10691 the window to last_unchanged_at_beg_vpos - |dvpos|. */
10692 set_terminal_window (end);
10693
10694 /* Delete dvpos lines in front of
10695 last_unchanged_at_beg_vpos. ins_del_lines will set
10696 the cursor to the given vpos and emit |dvpos| delete
10697 line sequences. */
10698 ins_del_lines (from + dvpos, dvpos);
10699
10700 /* On a dumb terminal insert dvpos empty lines at the
10701 end. */
10702 if (!scroll_region_ok)
10703 ins_del_lines (end + dvpos, -dvpos);
10704 }
10705
10706 set_terminal_window (0);
10707 }
10708
10709 update_end (f);
10710 }
10711
ca42b2e8
GM
10712 /* Shift reused rows of the current matrix to the right position.
10713 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
10714 text. */
10715 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
10716 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
10717 if (dvpos < 0)
10718 {
10719 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
10720 bottom_vpos, dvpos);
10721 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
10722 bottom_vpos, 0);
10723 }
10724 else if (dvpos > 0)
10725 {
10726 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
10727 bottom_vpos, dvpos);
10728 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
10729 first_unchanged_at_end_vpos + dvpos, 0);
10730 }
10731
10732 /* For frame-based redisplay, make sure that current frame and window
10733 matrix are in sync with respect to glyph memory. */
10734 if (!FRAME_WINDOW_P (f))
10735 sync_frame_with_window_matrix_rows (w);
10736
10737 /* Adjust buffer positions in reused rows. */
10738 if (delta)
f2d86d7a
GM
10739 increment_matrix_positions (current_matrix,
10740 first_unchanged_at_end_vpos + dvpos,
10741 bottom_vpos, delta, delta_bytes);
5f5c8ee5
GM
10742
10743 /* Adjust Y positions. */
10744 if (dy)
10745 shift_glyph_matrix (w, current_matrix,
10746 first_unchanged_at_end_vpos + dvpos,
10747 bottom_vpos, dy);
10748
10749 if (first_unchanged_at_end_row)
10750 first_unchanged_at_end_row += dvpos;
10751
10752 /* If scrolling up, there may be some lines to display at the end of
10753 the window. */
10754 last_text_row_at_end = NULL;
10755 if (dy < 0)
10756 {
10757 /* Set last_row to the glyph row in the current matrix where the
10758 window end line is found. It has been moved up or down in
10759 the matrix by dvpos. */
10760 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
10761 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
10762
10763 /* If last_row is the window end line, it should display text. */
10764 xassert (last_row->displays_text_p);
10765
10766 /* If window end line was partially visible before, begin
10767 displaying at that line. Otherwise begin displaying with the
10768 line following it. */
10769 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
10770 {
10771 init_to_row_start (&it, w, last_row);
10772 it.vpos = last_vpos;
10773 it.current_y = last_row->y;
10774 }
10775 else
10776 {
10777 init_to_row_end (&it, w, last_row);
10778 it.vpos = 1 + last_vpos;
10779 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
10780 ++last_row;
10781 }
12adba34 10782
5f5c8ee5
GM
10783 /* We may start in a continuation line. If so, we have to get
10784 the right continuation_lines_width and current_x. */
10785 it.continuation_lines_width = last_row->continuation_lines_width;
10786 it.hpos = it.current_x = 0;
10787
10788 /* Display the rest of the lines at the window end. */
10789 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10790 while (it.current_y < it.last_visible_y
10791 && !fonts_changed_p)
10792 {
10793 /* Is it always sure that the display agrees with lines in
10794 the current matrix? I don't think so, so we mark rows
10795 displayed invalid in the current matrix by setting their
10796 enabled_p flag to zero. */
10797 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
10798 if (display_line (&it))
10799 last_text_row_at_end = it.glyph_row - 1;
10800 }
10801 }
12adba34 10802
5f5c8ee5
GM
10803 /* Update window_end_pos and window_end_vpos. */
10804 if (first_unchanged_at_end_row
10805 && first_unchanged_at_end_row->y < it.last_visible_y
10806 && !last_text_row_at_end)
10807 {
10808 /* Window end line if one of the preserved rows from the current
10809 matrix. Set row to the last row displaying text in current
10810 matrix starting at first_unchanged_at_end_row, after
10811 scrolling. */
10812 xassert (first_unchanged_at_end_row->displays_text_p);
10813 row = find_last_row_displaying_text (w->current_matrix, &it,
10814 first_unchanged_at_end_row);
10815 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
10816
10817 XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row));
10818 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
10819 XSETFASTINT (w->window_end_vpos,
10820 MATRIX_ROW_VPOS (row, w->current_matrix));
10821 }
10822 else if (last_text_row_at_end)
10823 {
10824 XSETFASTINT (w->window_end_pos,
10825 Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
10826 w->window_end_bytepos
10827 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
10828 XSETFASTINT (w->window_end_vpos,
10829 MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
10830 }
10831 else if (last_text_row)
10832 {
10833 /* We have displayed either to the end of the window or at the
10834 end of the window, i.e. the last row with text is to be found
10835 in the desired matrix. */
10836 XSETFASTINT (w->window_end_pos,
10837 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10838 w->window_end_bytepos
10839 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
10840 XSETFASTINT (w->window_end_vpos,
10841 MATRIX_ROW_VPOS (last_text_row, desired_matrix));
10842 }
10843 else if (first_unchanged_at_end_row == NULL
10844 && last_text_row == NULL
10845 && last_text_row_at_end == NULL)
10846 {
10847 /* Displayed to end of window, but no line containing text was
10848 displayed. Lines were deleted at the end of the window. */
10849 int vpos;
045dee35 10850 int header_line_p = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
10851
10852 for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
045dee35
GM
10853 if ((w->desired_matrix->rows[vpos + header_line_p].enabled_p
10854 && w->desired_matrix->rows[vpos + header_line_p].displays_text_p)
10855 || (!w->desired_matrix->rows[vpos + header_line_p].enabled_p
10856 && w->current_matrix->rows[vpos + header_line_p].displays_text_p))
5f5c8ee5 10857 break;
12adba34 10858
5f5c8ee5
GM
10859 w->window_end_vpos = make_number (vpos);
10860 }
10861 else
10862 abort ();
10863
10864 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
10865 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 10866
5f5c8ee5
GM
10867 /* Record that display has not been completed. */
10868 w->window_end_valid = Qnil;
10869 w->desired_matrix->no_scrolling_p = 1;
ef121659 10870 return 3;
12adba34 10871}
0f9c0ff0 10872
a2889657 10873
5f5c8ee5
GM
10874\f
10875/***********************************************************************
10876 More debugging support
10877 ***********************************************************************/
a2889657 10878
5f5c8ee5 10879#if GLYPH_DEBUG
a2889657 10880
5f5c8ee5
GM
10881 void dump_glyph_row P_ ((struct glyph_matrix *, int, int));
10882static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
1c9241f5 10883
31b24551 10884
5f5c8ee5
GM
10885/* Dump the contents of glyph matrix MATRIX on stderr. If
10886 WITH_GLYPHS_P is non-zero, dump glyph contents as well. */
ca26e1c8 10887
5f85fa4e 10888static void
5f5c8ee5
GM
10889dump_glyph_matrix (matrix, with_glyphs_p)
10890 struct glyph_matrix *matrix;
10891 int with_glyphs_p;
10892{
efc63ef0 10893 int i;
5f5c8ee5
GM
10894 for (i = 0; i < matrix->nrows; ++i)
10895 dump_glyph_row (matrix, i, with_glyphs_p);
10896}
31b24551 10897
68a37fa8 10898
5f5c8ee5
GM
10899/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
10900 WITH_GLYPH_SP non-zero means dump glyph contents, too. */
a2889657 10901
5f5c8ee5
GM
10902void
10903dump_glyph_row (matrix, vpos, with_glyphs_p)
10904 struct glyph_matrix *matrix;
10905 int vpos, with_glyphs_p;
10906{
10907 struct glyph_row *row;
10908
10909 if (vpos < 0 || vpos >= matrix->nrows)
10910 return;
10911
10912 row = MATRIX_ROW (matrix, vpos);
10913
b28cb6ed
GM
10914 fprintf (stderr, "Row Start End Used oEI><O\\CTZFes X Y W H V A P\n");
10915 fprintf (stderr, "=======================================================================\n");
5f5c8ee5 10916
b28cb6ed
GM
10917 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1 \
109181d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
5f5c8ee5
GM
10919 row - matrix->rows,
10920 MATRIX_ROW_START_CHARPOS (row),
10921 MATRIX_ROW_END_CHARPOS (row),
10922 row->used[TEXT_AREA],
10923 row->contains_overlapping_glyphs_p,
10924 row->enabled_p,
10925 row->inverse_p,
10926 row->truncated_on_left_p,
10927 row->truncated_on_right_p,
10928 row->overlay_arrow_p,
10929 row->continued_p,
10930 MATRIX_ROW_CONTINUATION_LINE_P (row),
10931 row->displays_text_p,
10932 row->ends_at_zv_p,
10933 row->fill_line_p,
91004049
GM
10934 row->ends_in_middle_of_char_p,
10935 row->starts_in_middle_of_char_p,
5f5c8ee5
GM
10936 row->x,
10937 row->y,
b28cb6ed
GM
10938 row->pixel_width,
10939 row->height,
10940 row->visible_height,
10941 row->ascent,
10942 row->phys_ascent);
5f5c8ee5
GM
10943 fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
10944 row->end.overlay_string_index);
10945 fprintf (stderr, "%9d %5d\n",
10946 CHARPOS (row->start.string_pos),
10947 CHARPOS (row->end.string_pos));
10948 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
10949 row->end.dpvec_index);
10950
10951 if (with_glyphs_p)
bd66d1ba 10952 {
5f5c8ee5
GM
10953 struct glyph *glyph, *glyph_end;
10954 int prev_had_glyphs_p;
10955
10956 glyph = row->glyphs[TEXT_AREA];
10957 glyph_end = glyph + row->used[TEXT_AREA];
10958
10959 /* Glyph for a line end in text. */
10960 if (glyph == glyph_end && glyph->charpos > 0)
10961 ++glyph_end;
10962
10963 if (glyph < glyph_end)
bd66d1ba 10964 {
06568bbf 10965 fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
5f5c8ee5 10966 prev_had_glyphs_p = 1;
bd66d1ba
RS
10967 }
10968 else
5f5c8ee5
GM
10969 prev_had_glyphs_p = 0;
10970
10971 while (glyph < glyph_end)
f7b4b63a 10972 {
5f5c8ee5
GM
10973 if (glyph->type == CHAR_GLYPH)
10974 {
10975 fprintf (stderr,
06568bbf 10976 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
5f5c8ee5
GM
10977 glyph - row->glyphs[TEXT_AREA],
10978 'C',
10979 glyph->charpos,
06568bbf
GM
10980 (BUFFERP (glyph->object)
10981 ? 'B'
10982 : (STRINGP (glyph->object)
10983 ? 'S'
10984 : '-')),
5f5c8ee5 10985 glyph->pixel_width,
43d120d8
KH
10986 glyph->u.ch,
10987 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
10988 ? glyph->u.ch
5f5c8ee5 10989 : '.'),
43d120d8 10990 glyph->face_id,
5f5c8ee5
GM
10991 glyph->left_box_line_p,
10992 glyph->right_box_line_p);
10993 }
10994 else if (glyph->type == STRETCH_GLYPH)
10995 {
10996 fprintf (stderr,
06568bbf 10997 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
5f5c8ee5
GM
10998 glyph - row->glyphs[TEXT_AREA],
10999 'S',
11000 glyph->charpos,
06568bbf
GM
11001 (BUFFERP (glyph->object)
11002 ? 'B'
11003 : (STRINGP (glyph->object)
11004 ? 'S'
11005 : '-')),
5f5c8ee5
GM
11006 glyph->pixel_width,
11007 0,
11008 '.',
bcdda9a4 11009 glyph->face_id,
5f5c8ee5
GM
11010 glyph->left_box_line_p,
11011 glyph->right_box_line_p);
11012 }
11013 else if (glyph->type == IMAGE_GLYPH)
11014 {
11015 fprintf (stderr,
06568bbf 11016 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
5f5c8ee5
GM
11017 glyph - row->glyphs[TEXT_AREA],
11018 'I',
11019 glyph->charpos,
06568bbf
GM
11020 (BUFFERP (glyph->object)
11021 ? 'B'
11022 : (STRINGP (glyph->object)
11023 ? 'S'
11024 : '-')),
5f5c8ee5 11025 glyph->pixel_width,
43d120d8 11026 glyph->u.img_id,
5f5c8ee5 11027 '.',
bcdda9a4 11028 glyph->face_id,
5f5c8ee5
GM
11029 glyph->left_box_line_p,
11030 glyph->right_box_line_p);
11031 }
11032 ++glyph;
f7b4b63a 11033 }
f4faa47c 11034 }
5f5c8ee5 11035}
f4faa47c 11036
a2889657 11037
5f5c8ee5
GM
11038DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
11039 Sdump_glyph_matrix, 0, 1, "p",
11040 "Dump the current matrix of the selected window to stderr.\n\
11041Shows contents of glyph row structures. With non-nil optional\n\
11042parameter WITH-GLYPHS-P, dump glyphs as well.")
11043 (with_glyphs_p)
02513cdd 11044 Lisp_Object with_glyphs_p;
5f5c8ee5
GM
11045{
11046 struct window *w = XWINDOW (selected_window);
11047 struct buffer *buffer = XBUFFER (w->buffer);
11048
11049 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
11050 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
11051 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
11052 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
11053 fprintf (stderr, "=============================================\n");
11054 dump_glyph_matrix (w->current_matrix, !NILP (with_glyphs_p));
11055 return Qnil;
11056}
1c2250c2 11057
1fca3fae 11058
5f5c8ee5
GM
11059DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "",
11060 "Dump glyph row ROW to stderr.")
11061 (row)
11062 Lisp_Object row;
11063{
11064 CHECK_NUMBER (row, 0);
11065 dump_glyph_row (XWINDOW (selected_window)->current_matrix, XINT (row), 1);
11066 return Qnil;
11067}
1fca3fae 11068
67481ae5 11069
e037b9ec 11070DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row,
5f5c8ee5
GM
11071 0, 0, "", "")
11072 ()
11073{
886bd6f2
GM
11074 struct frame *sf = SELECTED_FRAME ();
11075 struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)
5f5c8ee5
GM
11076 ->current_matrix);
11077 dump_glyph_row (m, 0, 1);
11078 return Qnil;
11079}
ca26e1c8 11080
0f9c0ff0 11081
5f5c8ee5
GM
11082DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
11083 Strace_redisplay_toggle, 0, 0, "",
11084 "Toggle tracing of redisplay.")
11085 ()
11086{
11087 trace_redisplay_p = !trace_redisplay_p;
11088 return Qnil;
11089}
bf9249e3
GM
11090
11091
11092DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, 1, "",
11093 "Print STRING to stderr.")
11094 (string)
11095 Lisp_Object string;
11096{
11097 CHECK_STRING (string, 0);
11098 fprintf (stderr, "%s", XSTRING (string)->data);
11099 return Qnil;
11100}
5f5c8ee5
GM
11101
11102#endif /* GLYPH_DEBUG */
ca26e1c8 11103
ca26e1c8 11104
5f5c8ee5
GM
11105\f
11106/***********************************************************************
11107 Building Desired Matrix Rows
11108 ***********************************************************************/
a2889657 11109
5f5c8ee5
GM
11110/* Return a temporary glyph row holding the glyphs of an overlay
11111 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 11112
5f5c8ee5
GM
11113static struct glyph_row *
11114get_overlay_arrow_glyph_row (w)
11115 struct window *w;
11116{
11117 struct frame *f = XFRAME (WINDOW_FRAME (w));
11118 struct buffer *buffer = XBUFFER (w->buffer);
11119 struct buffer *old = current_buffer;
11120 unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data;
11121 int arrow_len = XSTRING (Voverlay_arrow_string)->size;
11122 unsigned char *arrow_end = arrow_string + arrow_len;
11123 unsigned char *p;
11124 struct it it;
11125 int multibyte_p;
11126 int n_glyphs_before;
11127
11128 set_buffer_temp (buffer);
11129 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
11130 it.glyph_row->used[TEXT_AREA] = 0;
11131 SET_TEXT_POS (it.position, 0, 0);
11132
11133 multibyte_p = !NILP (buffer->enable_multibyte_characters);
11134 p = arrow_string;
11135 while (p < arrow_end)
11136 {
11137 Lisp_Object face, ilisp;
11138
11139 /* Get the next character. */
11140 if (multibyte_p)
4fdb80f2 11141 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
11142 else
11143 it.c = *p, it.len = 1;
11144 p += it.len;
11145
11146 /* Get its face. */
11147 XSETFASTINT (ilisp, p - arrow_string);
11148 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
11149 it.face_id = compute_char_face (f, it.c, face);
11150
11151 /* Compute its width, get its glyphs. */
11152 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 11153 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
11154 PRODUCE_GLYPHS (&it);
11155
11156 /* If this character doesn't fit any more in the line, we have
11157 to remove some glyphs. */
11158 if (it.current_x > it.last_visible_x)
11159 {
11160 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
11161 break;
11162 }
11163 }
11164
11165 set_buffer_temp (old);
11166 return it.glyph_row;
11167}
ca26e1c8 11168
b0a0fbda 11169
5f5c8ee5
GM
11170/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
11171 glyphs are only inserted for terminal frames since we can't really
11172 win with truncation glyphs when partially visible glyphs are
11173 involved. Which glyphs to insert is determined by
11174 produce_special_glyphs. */
67481ae5 11175
5f5c8ee5
GM
11176static void
11177insert_left_trunc_glyphs (it)
11178 struct it *it;
11179{
11180 struct it truncate_it;
11181 struct glyph *from, *end, *to, *toend;
11182
11183 xassert (!FRAME_WINDOW_P (it->f));
11184
11185 /* Get the truncation glyphs. */
11186 truncate_it = *it;
5f5c8ee5
GM
11187 truncate_it.current_x = 0;
11188 truncate_it.face_id = DEFAULT_FACE_ID;
11189 truncate_it.glyph_row = &scratch_glyph_row;
11190 truncate_it.glyph_row->used[TEXT_AREA] = 0;
11191 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
6fc556fd 11192 truncate_it.object = make_number (0);
5f5c8ee5
GM
11193 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
11194
11195 /* Overwrite glyphs from IT with truncation glyphs. */
11196 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
11197 end = from + truncate_it.glyph_row->used[TEXT_AREA];
11198 to = it->glyph_row->glyphs[TEXT_AREA];
11199 toend = to + it->glyph_row->used[TEXT_AREA];
11200
11201 while (from < end)
11202 *to++ = *from++;
11203
11204 /* There may be padding glyphs left over. Remove them. */
11205 from = to;
11206 while (from < toend && CHAR_GLYPH_PADDING_P (*from))
11207 ++from;
11208 while (from < toend)
11209 *to++ = *from++;
11210
11211 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
11212}
e0bfbde6 11213
e0bfbde6 11214
5f5c8ee5 11215/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 11216
5f5c8ee5
GM
11217 Most of the time, ascent and height of a display line will be equal
11218 to the max_ascent and max_height values of the display iterator
11219 structure. This is not the case if
67481ae5 11220
5f5c8ee5
GM
11221 1. We hit ZV without displaying anything. In this case, max_ascent
11222 and max_height will be zero.
1c9241f5 11223
5f5c8ee5
GM
11224 2. We have some glyphs that don't contribute to the line height.
11225 (The glyph row flag contributes_to_line_height_p is for future
11226 pixmap extensions).
f6fd109b 11227
5f5c8ee5
GM
11228 The first case is easily covered by using default values because in
11229 these cases, the line height does not really matter, except that it
11230 must not be zero. */
67481ae5 11231
5f5c8ee5
GM
11232static void
11233compute_line_metrics (it)
11234 struct it *it;
11235{
11236 struct glyph_row *row = it->glyph_row;
11237 int area, i;
1c2250c2 11238
5f5c8ee5
GM
11239 if (FRAME_WINDOW_P (it->f))
11240 {
045dee35 11241 int i, header_line_height;
1c2250c2 11242
5f5c8ee5
GM
11243 /* The line may consist of one space only, that was added to
11244 place the cursor on it. If so, the row's height hasn't been
11245 computed yet. */
11246 if (row->height == 0)
11247 {
11248 if (it->max_ascent + it->max_descent == 0)
312246d1 11249 it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
5f5c8ee5
GM
11250 row->ascent = it->max_ascent;
11251 row->height = it->max_ascent + it->max_descent;
312246d1
GM
11252 row->phys_ascent = it->max_phys_ascent;
11253 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
11254 }
11255
11256 /* Compute the width of this line. */
11257 row->pixel_width = row->x;
11258 for (i = 0; i < row->used[TEXT_AREA]; ++i)
11259 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
11260
11261 xassert (row->pixel_width >= 0);
11262 xassert (row->ascent >= 0 && row->height > 0);
11263
312246d1
GM
11264 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
11265 || MATRIX_ROW_OVERLAPS_PRED_P (row));
11266
11267 /* If first line's physical ascent is larger than its logical
11268 ascent, use the physical ascent, and make the row taller.
11269 This makes accented characters fully visible. */
b28cb6ed 11270 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
312246d1
GM
11271 && row->phys_ascent > row->ascent)
11272 {
11273 row->height += row->phys_ascent - row->ascent;
11274 row->ascent = row->phys_ascent;
11275 }
11276
5f5c8ee5
GM
11277 /* Compute how much of the line is visible. */
11278 row->visible_height = row->height;
11279
045dee35
GM
11280 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
11281 if (row->y < header_line_height)
11282 row->visible_height -= header_line_height - row->y;
5f5c8ee5
GM
11283 else
11284 {
11285 int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
11286 if (row->y + row->height > max_y)
11287 row->visible_height -= row->y + row->height - max_y;
11288 }
11289 }
11290 else
11291 {
11292 row->pixel_width = row->used[TEXT_AREA];
312246d1
GM
11293 row->ascent = row->phys_ascent = 0;
11294 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 11295 }
67481ae5 11296
5f5c8ee5
GM
11297 /* Compute a hash code for this row. */
11298 row->hash = 0;
11299 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
11300 for (i = 0; i < row->used[area]; ++i)
11301 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
11302 + row->glyphs[area][i].u.val
43d120d8
KH
11303 + row->glyphs[area][i].face_id
11304 + row->glyphs[area][i].padding_p
5f5c8ee5 11305 + (row->glyphs[area][i].type << 2));
a2889657 11306
5f5c8ee5 11307 it->max_ascent = it->max_descent = 0;
312246d1 11308 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 11309}
12adba34 11310
ca26e1c8 11311
5f5c8ee5
GM
11312/* Append one space to the glyph row of iterator IT if doing a
11313 window-based redisplay. DEFAULT_FACE_P non-zero means let the
11314 space have the default face, otherwise let it have the same face as
80c6cb1f 11315 IT->face_id. Value is non-zero if a space was added.
c6e89d6c
GM
11316
11317 This function is called to make sure that there is always one glyph
11318 at the end of a glyph row that the cursor can be set on under
11319 window-systems. (If there weren't such a glyph we would not know
11320 how wide and tall a box cursor should be displayed).
11321
11322 At the same time this space let's a nicely handle clearing to the
11323 end of the line if the row ends in italic text. */
ca26e1c8 11324
80c6cb1f 11325static int
5f5c8ee5
GM
11326append_space (it, default_face_p)
11327 struct it *it;
11328 int default_face_p;
11329{
11330 if (FRAME_WINDOW_P (it->f))
11331 {
11332 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 11333
5f5c8ee5
GM
11334 if (it->glyph_row->glyphs[TEXT_AREA] + n
11335 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 11336 {
5f5c8ee5
GM
11337 /* Save some values that must not be changed. */
11338 int saved_x = it->current_x;
11339 struct text_pos saved_pos;
11340 int saved_what = it->what;
11341 int saved_face_id = it->face_id;
5f5c8ee5 11342 Lisp_Object saved_object;
980806b6 11343 struct face *face;
5f5c8ee5
GM
11344
11345 saved_object = it->object;
11346 saved_pos = it->position;
11347
11348 it->what = IT_CHARACTER;
11349 bzero (&it->position, sizeof it->position);
6fc556fd 11350 it->object = make_number (0);
5f5c8ee5
GM
11351 it->c = ' ';
11352 it->len = 1;
5f5c8ee5
GM
11353
11354 if (default_face_p)
11355 it->face_id = DEFAULT_FACE_ID;
980806b6
KH
11356 face = FACE_FROM_ID (it->f, it->face_id);
11357 it->face_id = FACE_FOR_CHAR (it->f, face, 0);
1842fc1a 11358
5f5c8ee5
GM
11359 PRODUCE_GLYPHS (it);
11360
11361 it->current_x = saved_x;
11362 it->object = saved_object;
11363 it->position = saved_pos;
11364 it->what = saved_what;
11365 it->face_id = saved_face_id;
80c6cb1f 11366 return 1;
5f5c8ee5
GM
11367 }
11368 }
80c6cb1f
GM
11369
11370 return 0;
5f5c8ee5 11371}
12adba34 11372
1842fc1a 11373
5f5c8ee5
GM
11374/* Extend the face of the last glyph in the text area of IT->glyph_row
11375 to the end of the display line. Called from display_line.
11376 If the glyph row is empty, add a space glyph to it so that we
11377 know the face to draw. Set the glyph row flag fill_line_p. */
11378
11379static void
11380extend_face_to_end_of_line (it)
11381 struct it *it;
11382{
11383 struct face *face;
11384 struct frame *f = it->f;
1842fc1a 11385
5f5c8ee5
GM
11386 /* If line is already filled, do nothing. */
11387 if (it->current_x >= it->last_visible_x)
11388 return;
11389
11390 /* Face extension extends the background and box of IT->face_id
11391 to the end of the line. If the background equals the background
11392 of the frame, we haven't to do anything. */
11393 face = FACE_FROM_ID (f, it->face_id);
11394 if (FRAME_WINDOW_P (f)
11395 && face->box == FACE_NO_BOX
11396 && face->background == FRAME_BACKGROUND_PIXEL (f)
11397 && !face->stipple)
11398 return;
1842fc1a 11399
5f5c8ee5
GM
11400 /* Set the glyph row flag indicating that the face of the last glyph
11401 in the text area has to be drawn to the end of the text area. */
11402 it->glyph_row->fill_line_p = 1;
545e04f6 11403
980806b6
KH
11404 /* If current character of IT is not ASCII, make sure we have the
11405 ASCII face. This will be automatically undone the next time
11406 get_next_display_element returns a multibyte character. Note
11407 that the character will always be single byte in unibyte text. */
11408 if (!SINGLE_BYTE_CHAR_P (it->c))
5f5c8ee5 11409 {
980806b6 11410 it->face_id = FACE_FOR_CHAR (f, face, 0);
5f5c8ee5 11411 }
545e04f6 11412
5f5c8ee5
GM
11413 if (FRAME_WINDOW_P (f))
11414 {
11415 /* If the row is empty, add a space with the current face of IT,
11416 so that we know which face to draw. */
11417 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 11418 {
5f5c8ee5 11419 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
43d120d8 11420 it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
5f5c8ee5 11421 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 11422 }
5f5c8ee5
GM
11423 }
11424 else
11425 {
11426 /* Save some values that must not be changed. */
11427 int saved_x = it->current_x;
11428 struct text_pos saved_pos;
11429 Lisp_Object saved_object;
11430 int saved_what = it->what;
11431
11432 saved_object = it->object;
11433 saved_pos = it->position;
11434
11435 it->what = IT_CHARACTER;
11436 bzero (&it->position, sizeof it->position);
6fc556fd 11437 it->object = make_number (0);
5f5c8ee5
GM
11438 it->c = ' ';
11439 it->len = 1;
11440
11441 PRODUCE_GLYPHS (it);
11442
11443 while (it->current_x <= it->last_visible_x)
11444 PRODUCE_GLYPHS (it);
11445
11446 /* Don't count these blanks really. It would let us insert a left
11447 truncation glyph below and make us set the cursor on them, maybe. */
11448 it->current_x = saved_x;
11449 it->object = saved_object;
11450 it->position = saved_pos;
11451 it->what = saved_what;
11452 }
11453}
12adba34 11454
545e04f6 11455
5f5c8ee5
GM
11456/* Value is non-zero if text starting at CHARPOS in current_buffer is
11457 trailing whitespace. */
1c9241f5 11458
5f5c8ee5
GM
11459static int
11460trailing_whitespace_p (charpos)
11461 int charpos;
11462{
11463 int bytepos = CHAR_TO_BYTE (charpos);
11464 int c = 0;
7bbe686f 11465
5f5c8ee5
GM
11466 while (bytepos < ZV_BYTE
11467 && (c = FETCH_CHAR (bytepos),
11468 c == ' ' || c == '\t'))
11469 ++bytepos;
0d09d1e6 11470
8f897821
GM
11471 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
11472 {
11473 if (bytepos != PT_BYTE)
11474 return 1;
11475 }
11476 return 0;
5f5c8ee5 11477}
31b24551 11478
545e04f6 11479
5f5c8ee5 11480/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 11481
5f5c8ee5
GM
11482void
11483highlight_trailing_whitespace (f, row)
11484 struct frame *f;
11485 struct glyph_row *row;
11486{
11487 int used = row->used[TEXT_AREA];
11488
11489 if (used)
11490 {
11491 struct glyph *start = row->glyphs[TEXT_AREA];
11492 struct glyph *glyph = start + used - 1;
11493
11494 /* Skip over the space glyph inserted to display the
11495 cursor at the end of a line. */
11496 if (glyph->type == CHAR_GLYPH
43d120d8 11497 && glyph->u.ch == ' '
6fc556fd 11498 && INTEGERP (glyph->object))
5f5c8ee5
GM
11499 --glyph;
11500
11501 /* If last glyph is a space or stretch, and it's trailing
11502 whitespace, set the face of all trailing whitespace glyphs in
11503 IT->glyph_row to `trailing-whitespace'. */
11504 if (glyph >= start
11505 && BUFFERP (glyph->object)
11506 && (glyph->type == STRETCH_GLYPH
11507 || (glyph->type == CHAR_GLYPH
43d120d8 11508 && glyph->u.ch == ' '))
5f5c8ee5 11509 && trailing_whitespace_p (glyph->charpos))
545e04f6 11510 {
980806b6 11511 int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
5f5c8ee5
GM
11512
11513 while (glyph >= start
11514 && BUFFERP (glyph->object)
11515 && (glyph->type == STRETCH_GLYPH
11516 || (glyph->type == CHAR_GLYPH
43d120d8
KH
11517 && glyph->u.ch == ' ')))
11518 (glyph--)->face_id = face_id;
545e04f6 11519 }
a2889657 11520 }
5f5c8ee5 11521}
a2889657 11522
5fcbb24d 11523
5f5c8ee5
GM
11524/* Construct the glyph row IT->glyph_row in the desired matrix of
11525 IT->w from text at the current position of IT. See dispextern.h
11526 for an overview of struct it. Value is non-zero if
11527 IT->glyph_row displays text, as opposed to a line displaying ZV
11528 only. */
11529
11530static int
11531display_line (it)
11532 struct it *it;
11533{
11534 struct glyph_row *row = it->glyph_row;
11535
11536 /* We always start displaying at hpos zero even if hscrolled. */
11537 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 11538
5f5c8ee5
GM
11539 /* We must not display in a row that's not a text row. */
11540 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
11541 < it->w->desired_matrix->nrows);
12adba34 11542
5f5c8ee5
GM
11543 /* Is IT->w showing the region? */
11544 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 11545
5f5c8ee5
GM
11546 /* Clear the result glyph row and enable it. */
11547 prepare_desired_row (row);
12adba34 11548
5f5c8ee5
GM
11549 row->y = it->current_y;
11550 row->start = it->current;
11551 row->continuation_lines_width = it->continuation_lines_width;
11552 row->displays_text_p = 1;
91004049
GM
11553 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
11554 it->starts_in_middle_of_char_p = 0;
5f5c8ee5
GM
11555
11556 /* Arrange the overlays nicely for our purposes. Usually, we call
11557 display_line on only one line at a time, in which case this
11558 can't really hurt too much, or we call it on lines which appear
11559 one after another in the buffer, in which case all calls to
11560 recenter_overlay_lists but the first will be pretty cheap. */
11561 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
11562
5f5c8ee5
GM
11563 /* Move over display elements that are not visible because we are
11564 hscrolled. This may stop at an x-position < IT->first_visible_x
11565 if the first glyph is partially visible or if we hit a line end. */
11566 if (it->current_x < it->first_visible_x)
11567 move_it_in_display_line_to (it, ZV, it->first_visible_x,
11568 MOVE_TO_POS | MOVE_TO_X);
11569
11570 /* Get the initial row height. This is either the height of the
11571 text hscrolled, if there is any, or zero. */
11572 row->ascent = it->max_ascent;
11573 row->height = it->max_ascent + it->max_descent;
312246d1
GM
11574 row->phys_ascent = it->max_phys_ascent;
11575 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
11576
11577 /* Loop generating characters. The loop is left with IT on the next
11578 character to display. */
11579 while (1)
11580 {
11581 int n_glyphs_before, hpos_before, x_before;
11582 int x, i, nglyphs;
e6819faf 11583 int ascent, descent, phys_ascent, phys_descent;
b28cb6ed 11584
5f5c8ee5
GM
11585 /* Retrieve the next thing to display. Value is zero if end of
11586 buffer reached. */
11587 if (!get_next_display_element (it))
11588 {
11589 /* Maybe add a space at the end of this line that is used to
1b335865
GM
11590 display the cursor there under X. Set the charpos of the
11591 first glyph of blank lines not corresponding to any text
11592 to -1. */
11593 if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
11594 || row->used[TEXT_AREA] == 0)
a2889657 11595 {
5f5c8ee5
GM
11596 row->glyphs[TEXT_AREA]->charpos = -1;
11597 row->displays_text_p = 0;
11598
11599 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines))
11600 row->indicate_empty_line_p = 1;
a2889657 11601 }
5f5c8ee5
GM
11602
11603 it->continuation_lines_width = 0;
11604 row->ends_at_zv_p = 1;
11605 break;
a2889657 11606 }
a2889657 11607
5f5c8ee5
GM
11608 /* Now, get the metrics of what we want to display. This also
11609 generates glyphs in `row' (which is IT->glyph_row). */
11610 n_glyphs_before = row->used[TEXT_AREA];
11611 x = it->current_x;
e6819faf
GM
11612
11613 /* Remember the line height so far in case the next element doesn't
11614 fit on the line. */
11615 if (!it->truncate_lines_p)
11616 {
11617 ascent = it->max_ascent;
11618 descent = it->max_descent;
11619 phys_ascent = it->max_phys_ascent;
11620 phys_descent = it->max_phys_descent;
11621 }
11622
5f5c8ee5 11623 PRODUCE_GLYPHS (it);
a2889657 11624
5f5c8ee5
GM
11625 /* If this display element was in marginal areas, continue with
11626 the next one. */
11627 if (it->area != TEXT_AREA)
a2889657 11628 {
5f5c8ee5
GM
11629 row->ascent = max (row->ascent, it->max_ascent);
11630 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11631 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11632 row->phys_height = max (row->phys_height,
11633 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11634 set_iterator_to_next (it);
11635 continue;
11636 }
5936754e 11637
5f5c8ee5
GM
11638 /* Does the display element fit on the line? If we truncate
11639 lines, we should draw past the right edge of the window. If
11640 we don't truncate, we want to stop so that we can display the
11641 continuation glyph before the right margin. If lines are
11642 continued, there are two possible strategies for characters
11643 resulting in more than 1 glyph (e.g. tabs): Display as many
11644 glyphs as possible in this line and leave the rest for the
11645 continuation line, or display the whole element in the next
11646 line. Original redisplay did the former, so we do it also. */
11647 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
11648 hpos_before = it->hpos;
11649 x_before = x;
11650
11651 if (nglyphs == 1
11652 && it->current_x < it->last_visible_x)
11653 {
11654 ++it->hpos;
11655 row->ascent = max (row->ascent, it->max_ascent);
11656 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11657 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11658 row->phys_height = max (row->phys_height,
11659 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11660 if (it->current_x - it->pixel_width < it->first_visible_x)
11661 row->x = x - it->first_visible_x;
11662 }
11663 else
11664 {
11665 int new_x;
11666 struct glyph *glyph;
11667
11668 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 11669 {
5f5c8ee5
GM
11670 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
11671 new_x = x + glyph->pixel_width;
11672
11673 if (/* Lines are continued. */
11674 !it->truncate_lines_p
11675 && (/* Glyph doesn't fit on the line. */
11676 new_x > it->last_visible_x
11677 /* Or it fits exactly on a window system frame. */
11678 || (new_x == it->last_visible_x
11679 && FRAME_WINDOW_P (it->f))))
a2889657 11680 {
5f5c8ee5
GM
11681 /* End of a continued line. */
11682
11683 if (it->hpos == 0
11684 || (new_x == it->last_visible_x
11685 && FRAME_WINDOW_P (it->f)))
11686 {
e6819faf
GM
11687 /* Current glyph is the only one on the line or
11688 fits exactly on the line. We must continue
11689 the line because we can't draw the cursor
11690 after the glyph. */
5f5c8ee5
GM
11691 row->continued_p = 1;
11692 it->current_x = new_x;
11693 it->continuation_lines_width += new_x;
11694 ++it->hpos;
11695 if (i == nglyphs - 1)
11696 set_iterator_to_next (it);
11697 }
3b3c4bf0
GM
11698 else if (CHAR_GLYPH_PADDING_P (*glyph)
11699 && !FRAME_WINDOW_P (it->f))
11700 {
11701 /* A padding glyph that doesn't fit on this line.
11702 This means the whole character doesn't fit
11703 on the line. */
11704 row->used[TEXT_AREA] = n_glyphs_before;
11705
11706 /* Fill the rest of the row with continuation
11707 glyphs like in 20.x. */
11708 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
11709 < row->glyphs[1 + TEXT_AREA])
11710 produce_special_glyphs (it, IT_CONTINUATION);
11711
11712 row->continued_p = 1;
11713 it->current_x = x_before;
11714 it->continuation_lines_width += x_before;
11715
11716 /* Restore the height to what it was before the
11717 element not fitting on the line. */
11718 it->max_ascent = ascent;
11719 it->max_descent = descent;
11720 it->max_phys_ascent = phys_ascent;
11721 it->max_phys_descent = phys_descent;
11722 }
5f5c8ee5 11723 else
5936754e 11724 {
5f5c8ee5
GM
11725 /* Display element draws past the right edge of
11726 the window. Restore positions to values
11727 before the element. The next line starts
11728 with current_x before the glyph that could
11729 not be displayed, so that TAB works right. */
11730 row->used[TEXT_AREA] = n_glyphs_before + i;
11731
11732 /* Display continuation glyphs. */
11733 if (!FRAME_WINDOW_P (it->f))
11734 produce_special_glyphs (it, IT_CONTINUATION);
11735 row->continued_p = 1;
11736
11737 it->current_x = x;
11738 it->continuation_lines_width += x;
91004049
GM
11739 if (nglyphs > 1 && i > 0)
11740 {
11741 row->ends_in_middle_of_char_p = 1;
11742 it->starts_in_middle_of_char_p = 1;
11743 }
e6819faf
GM
11744
11745 /* Restore the height to what it was before the
11746 element not fitting on the line. */
11747 it->max_ascent = ascent;
11748 it->max_descent = descent;
11749 it->max_phys_ascent = phys_ascent;
11750 it->max_phys_descent = phys_descent;
5936754e 11751 }
e6819faf 11752
5f5c8ee5
GM
11753 break;
11754 }
11755 else if (new_x > it->first_visible_x)
11756 {
11757 /* Increment number of glyphs actually displayed. */
11758 ++it->hpos;
11759
11760 if (x < it->first_visible_x)
11761 /* Glyph is partially visible, i.e. row starts at
11762 negative X position. */
11763 row->x = x - it->first_visible_x;
11764 }
11765 else
11766 {
11767 /* Glyph is completely off the left margin of the
11768 window. This should not happen because of the
11769 move_it_in_display_line at the start of
11770 this function. */
11771 abort ();
a2889657 11772 }
a2889657 11773 }
5f5c8ee5
GM
11774
11775 row->ascent = max (row->ascent, it->max_ascent);
11776 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11777 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11778 row->phys_height = max (row->phys_height,
11779 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11780
11781 /* End of this display line if row is continued. */
11782 if (row->continued_p)
11783 break;
a2889657 11784 }
a2889657 11785
5f5c8ee5
GM
11786 /* Is this a line end? If yes, we're also done, after making
11787 sure that a non-default face is extended up to the right
11788 margin of the window. */
11789 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 11790 {
5f5c8ee5
GM
11791 int used_before = row->used[TEXT_AREA];
11792
11793 /* Add a space at the end of the line that is used to
11794 display the cursor there. */
11795 append_space (it, 0);
11796
11797 /* Extend the face to the end of the line. */
11798 extend_face_to_end_of_line (it);
11799
11800 /* Make sure we have the position. */
11801 if (used_before == 0)
11802 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
11803
11804 /* Consume the line end. This skips over invisible lines. */
11805 set_iterator_to_next (it);
11806 it->continuation_lines_width = 0;
11807 break;
1c9241f5 11808 }
a2889657 11809
5f5c8ee5
GM
11810 /* Proceed with next display element. Note that this skips
11811 over lines invisible because of selective display. */
11812 set_iterator_to_next (it);
b1d1124b 11813
5f5c8ee5
GM
11814 /* If we truncate lines, we are done when the last displayed
11815 glyphs reach past the right margin of the window. */
11816 if (it->truncate_lines_p
11817 && (FRAME_WINDOW_P (it->f)
11818 ? (it->current_x >= it->last_visible_x)
11819 : (it->current_x > it->last_visible_x)))
75d13c64 11820 {
5f5c8ee5
GM
11821 /* Maybe add truncation glyphs. */
11822 if (!FRAME_WINDOW_P (it->f))
11823 {
11824 --it->glyph_row->used[TEXT_AREA];
11825 produce_special_glyphs (it, IT_TRUNCATION);
11826 }
11827
11828 row->truncated_on_right_p = 1;
11829 it->continuation_lines_width = 0;
312246d1 11830 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
11831 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
11832 it->hpos = hpos_before;
11833 it->current_x = x_before;
11834 break;
75d13c64 11835 }
a2889657 11836 }
a2889657 11837
5f5c8ee5
GM
11838 /* If line is not empty and hscrolled, maybe insert truncation glyphs
11839 at the left window margin. */
11840 if (it->first_visible_x
11841 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
11842 {
11843 if (!FRAME_WINDOW_P (it->f))
11844 insert_left_trunc_glyphs (it);
11845 row->truncated_on_left_p = 1;
11846 }
a2889657 11847
5f5c8ee5
GM
11848 /* If the start of this line is the overlay arrow-position, then
11849 mark this glyph row as the one containing the overlay arrow.
11850 This is clearly a mess with variable size fonts. It would be
11851 better to let it be displayed like cursors under X. */
e24c997d 11852 if (MARKERP (Voverlay_arrow_position)
a2889657 11853 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
11854 && (MATRIX_ROW_START_CHARPOS (row)
11855 == marker_position (Voverlay_arrow_position))
e24c997d 11856 && STRINGP (Voverlay_arrow_string)
a2889657
JB
11857 && ! overlay_arrow_seen)
11858 {
5f5c8ee5
GM
11859 /* Overlay arrow in window redisplay is a bitmap. */
11860 if (!FRAME_WINDOW_P (it->f))
c4628384 11861 {
5f5c8ee5
GM
11862 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
11863 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
11864 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
11865 struct glyph *p = row->glyphs[TEXT_AREA];
11866 struct glyph *p2, *end;
11867
11868 /* Copy the arrow glyphs. */
11869 while (glyph < arrow_end)
11870 *p++ = *glyph++;
11871
11872 /* Throw away padding glyphs. */
11873 p2 = p;
11874 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
11875 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
11876 ++p2;
11877 if (p2 > p)
212e4f87 11878 {
5f5c8ee5
GM
11879 while (p2 < end)
11880 *p++ = *p2++;
11881 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 11882 }
c4628384 11883 }
5f5c8ee5 11884
a2889657 11885 overlay_arrow_seen = 1;
5f5c8ee5 11886 row->overlay_arrow_p = 1;
a2889657
JB
11887 }
11888
5f5c8ee5
GM
11889 /* Compute pixel dimensions of this line. */
11890 compute_line_metrics (it);
11891
11892 /* Remember the position at which this line ends. */
11893 row->end = it->current;
11894
173cbca8 11895 /* Maybe set the cursor. */
5f5c8ee5
GM
11896 if (it->w->cursor.vpos < 0
11897 && PT >= MATRIX_ROW_START_CHARPOS (row)
173cbca8
GM
11898 && PT <= MATRIX_ROW_END_CHARPOS (row))
11899 {
11900 /* Also see redisplay_window, case cursor movement in unchanged
11901 window. */
11902 if (MATRIX_ROW_END_CHARPOS (row) == PT
11903 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
11904 && !row->ends_at_zv_p)
11905 ;
11906 else
11907 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
11908 }
5f5c8ee5
GM
11909
11910 /* Highlight trailing whitespace. */
8f897821 11911 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
11912 highlight_trailing_whitespace (it->f, it->glyph_row);
11913
11914 /* Prepare for the next line. This line starts horizontally at (X
11915 HPOS) = (0 0). Vertical positions are incremented. As a
11916 convenience for the caller, IT->glyph_row is set to the next
11917 row to be used. */
11918 it->current_x = it->hpos = 0;
11919 it->current_y += row->height;
11920 ++it->vpos;
11921 ++it->glyph_row;
11922 return row->displays_text_p;
a2889657 11923}
5f5c8ee5
GM
11924
11925
a2889657 11926\f
5f5c8ee5
GM
11927/***********************************************************************
11928 Menu Bar
11929 ***********************************************************************/
11930
11931/* Redisplay the menu bar in the frame for window W.
11932
11933 The menu bar of X frames that don't have X toolkit support is
11934 displayed in a special window W->frame->menu_bar_window.
11935
11936 The menu bar of terminal frames is treated specially as far as
11937 glyph matrices are concerned. Menu bar lines are not part of
11938 windows, so the update is done directly on the frame matrix rows
11939 for the menu bar. */
7ce2c095
RS
11940
11941static void
11942display_menu_bar (w)
11943 struct window *w;
11944{
5f5c8ee5
GM
11945 struct frame *f = XFRAME (WINDOW_FRAME (w));
11946 struct it it;
11947 Lisp_Object items;
8351baf2 11948 int i;
7ce2c095 11949
5f5c8ee5 11950 /* Don't do all this for graphical frames. */
dc937613 11951#ifdef HAVE_NTGUI
d129c4c2
KH
11952 if (!NILP (Vwindow_system))
11953 return;
dc937613 11954#endif
dc937613 11955#ifdef USE_X_TOOLKIT
d3413a53 11956 if (FRAME_X_P (f))
7ce2c095 11957 return;
5f5c8ee5
GM
11958#endif
11959
11960#ifdef USE_X_TOOLKIT
11961 xassert (!FRAME_WINDOW_P (f));
52377a47 11962 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5
GM
11963 it.first_visible_x = 0;
11964 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11965#else /* not USE_X_TOOLKIT */
11966 if (FRAME_WINDOW_P (f))
11967 {
11968 /* Menu bar lines are displayed in the desired matrix of the
11969 dummy window menu_bar_window. */
11970 struct window *menu_w;
11971 xassert (WINDOWP (f->menu_bar_window));
11972 menu_w = XWINDOW (f->menu_bar_window);
11973 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 11974 MENU_FACE_ID);
5f5c8ee5
GM
11975 it.first_visible_x = 0;
11976 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11977 }
11978 else
11979 {
11980 /* This is a TTY frame, i.e. character hpos/vpos are used as
11981 pixel x/y. */
11982 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 11983 MENU_FACE_ID);
5f5c8ee5
GM
11984 it.first_visible_x = 0;
11985 it.last_visible_x = FRAME_WIDTH (f);
11986 }
11987#endif /* not USE_X_TOOLKIT */
11988
11989 /* Clear all rows of the menu bar. */
11990 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
11991 {
11992 struct glyph_row *row = it.glyph_row + i;
11993 clear_glyph_row (row);
11994 row->enabled_p = 1;
11995 row->full_width_p = 1;
11996 }
7ce2c095 11997
5f5c8ee5
GM
11998 /* Make the first line of the menu bar appear in reverse video. */
11999 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
7ce2c095 12000
5f5c8ee5
GM
12001 /* Display all items of the menu bar. */
12002 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 12003 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 12004 {
5f5c8ee5
GM
12005 Lisp_Object string;
12006
12007 /* Stop at nil string. */
8351baf2
RS
12008 string = XVECTOR (items)->contents[i + 1];
12009 if (NILP (string))
12010 break;
2d66ad19 12011
5f5c8ee5
GM
12012 /* Remember where item was displayed. */
12013 XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos);
7ce2c095 12014
5f5c8ee5
GM
12015 /* Display the item, pad with one space. */
12016 if (it.current_x < it.last_visible_x)
12017 display_string (NULL, string, Qnil, 0, 0, &it,
12018 XSTRING (string)->size + 1, 0, 0, -1);
7ce2c095
RS
12019 }
12020
2d66ad19 12021 /* Fill out the line with spaces. */
5f5c8ee5
GM
12022 if (it.current_x < it.last_visible_x)
12023 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 12024
5f5c8ee5
GM
12025 /* Compute the total height of the lines. */
12026 compute_line_metrics (&it);
7ce2c095 12027}
5f5c8ee5
GM
12028
12029
7ce2c095 12030\f
5f5c8ee5
GM
12031/***********************************************************************
12032 Mode Line
12033 ***********************************************************************/
12034
12035/* Display the mode and/or top line of window W. */
a2889657
JB
12036
12037static void
5f5c8ee5 12038display_mode_lines (w)
a2889657
JB
12039 struct window *w;
12040{
5f5c8ee5 12041 /* These will be set while the mode line specs are processed. */
aa6d10fa 12042 line_number_displayed = 0;
155ef550 12043 w->column_number_displayed = Qnil;
aa6d10fa 12044
5f5c8ee5 12045 if (WINDOW_WANTS_MODELINE_P (w))
045dee35
GM
12046 display_mode_line (w, MODE_LINE_FACE_ID,
12047 current_buffer->mode_line_format);
5f5c8ee5 12048
045dee35
GM
12049 if (WINDOW_WANTS_HEADER_LINE_P (w))
12050 display_mode_line (w, HEADER_LINE_FACE_ID,
12051 current_buffer->header_line_format);
5f5c8ee5 12052}
03b294dc 12053
03b294dc 12054
5f5c8ee5 12055/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 12056 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
5f5c8ee5 12057 FORMAT is the mode line format to display. */
03b294dc 12058
5f5c8ee5
GM
12059static void
12060display_mode_line (w, face_id, format)
12061 struct window *w;
12062 enum face_id face_id;
12063 Lisp_Object format;
12064{
12065 struct it it;
12066 struct face *face;
03b294dc 12067
5f5c8ee5
GM
12068 init_iterator (&it, w, -1, -1, NULL, face_id);
12069 prepare_desired_row (it.glyph_row);
12070
12071 /* Temporarily make frame's keyboard the current kboard so that
12072 kboard-local variables in the mode_line_format will get the right
12073 values. */
12074 push_frame_kboard (it.f);
12075 display_mode_element (&it, 0, 0, 0, format);
12076 pop_frame_kboard ();
a2889657 12077
5f5c8ee5
GM
12078 /* Fill up with spaces. */
12079 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
12080
12081 compute_line_metrics (&it);
12082 it.glyph_row->full_width_p = 1;
12083 it.glyph_row->mode_line_p = 1;
12084 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
12085 it.glyph_row->continued_p = 0;
12086 it.glyph_row->truncated_on_left_p = 0;
12087 it.glyph_row->truncated_on_right_p = 0;
12088
12089 /* Make a 3D mode-line have a shadow at its right end. */
12090 face = FACE_FROM_ID (it.f, face_id);
12091 extend_face_to_end_of_line (&it);
12092 if (face->box != FACE_NO_BOX)
d7eb09a0 12093 {
5f5c8ee5
GM
12094 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
12095 + it.glyph_row->used[TEXT_AREA] - 1);
12096 last->right_box_line_p = 1;
d7eb09a0 12097 }
a2889657
JB
12098}
12099
a2889657 12100
5f5c8ee5
GM
12101/* Contribute ELT to the mode line for window IT->w. How it
12102 translates into text depends on its data type.
a2889657 12103
5f5c8ee5 12104 IT describes the display environment in which we display, as usual.
a2889657
JB
12105
12106 DEPTH is the depth in recursion. It is used to prevent
12107 infinite recursion here.
12108
5f5c8ee5
GM
12109 FIELD_WIDTH is the number of characters the display of ELT should
12110 occupy in the mode line, and PRECISION is the maximum number of
12111 characters to display from ELT's representation. See
12112 display_string for details. *
a2889657 12113
5f5c8ee5 12114 Returns the hpos of the end of the text generated by ELT. */
a2889657
JB
12115
12116static int
5f5c8ee5
GM
12117display_mode_element (it, depth, field_width, precision, elt)
12118 struct it *it;
a2889657 12119 int depth;
5f5c8ee5
GM
12120 int field_width, precision;
12121 Lisp_Object elt;
a2889657 12122{
5f5c8ee5
GM
12123 int n = 0, field, prec;
12124
a2889657
JB
12125 tail_recurse:
12126 if (depth > 10)
12127 goto invalid;
12128
12129 depth++;
12130
0220c518 12131 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
12132 {
12133 case Lisp_String:
12134 {
12135 /* A string: output it and check for %-constructs within it. */
5f5c8ee5
GM
12136 unsigned char c;
12137 unsigned char *this = XSTRING (elt)->data;
12138 unsigned char *lisp_string = this;
12139
12140 while ((precision <= 0 || n < precision)
12141 && *this
12142 && (frame_title_ptr
12143 || it->current_x < it->last_visible_x))
a2889657
JB
12144 {
12145 unsigned char *last = this;
5f5c8ee5
GM
12146
12147 /* Advance to end of string or next format specifier. */
a2889657
JB
12148 while ((c = *this++) != '\0' && c != '%')
12149 ;
5f5c8ee5 12150
a2889657
JB
12151 if (this - 1 != last)
12152 {
5f5c8ee5
GM
12153 /* Output to end of string or up to '%'. Field width
12154 is length of string. Don't output more than
12155 PRECISION allows us. */
12156 prec = --this - last;
12157 if (precision > 0 && prec > precision - n)
12158 prec = precision - n;
12159
d39b6696 12160 if (frame_title_ptr)
5f5c8ee5 12161 n += store_frame_title (last, prec, prec);
d39b6696 12162 else
5f5c8ee5
GM
12163 n += display_string (NULL, elt, Qnil, 0, last - lisp_string,
12164 it, 0, prec, 0, -1);
a2889657
JB
12165 }
12166 else /* c == '%' */
12167 {
5f5c8ee5
GM
12168 unsigned char *percent_position = this;
12169
12170 /* Get the specified minimum width. Zero means
12171 don't pad. */
12172 field = 0;
a2889657 12173 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 12174 field = field * 10 + c - '0';
a2889657 12175
5f5c8ee5
GM
12176 /* Don't pad beyond the total padding allowed. */
12177 if (field_width - n > 0 && field > field_width - n)
12178 field = field_width - n;
a2889657 12179
5f5c8ee5
GM
12180 /* Note that either PRECISION <= 0 or N < PRECISION. */
12181 prec = precision - n;
12182
a2889657 12183 if (c == 'M')
5f5c8ee5
GM
12184 n += display_mode_element (it, depth, field, prec,
12185 Vglobal_mode_string);
a2889657 12186 else if (c != 0)
d39b6696 12187 {
5f5c8ee5
GM
12188 unsigned char *spec
12189 = decode_mode_spec (it->w, c, field, prec);
12190
d39b6696 12191 if (frame_title_ptr)
5f5c8ee5 12192 n += store_frame_title (spec, field, prec);
d39b6696 12193 else
5f5c8ee5
GM
12194 {
12195 int nglyphs_before
12196 = it->glyph_row->used[TEXT_AREA];
12197 int charpos
12198 = percent_position - XSTRING (elt)->data;
12199 int nwritten
12200 = display_string (spec, Qnil, elt, charpos, 0, it,
12201 field, prec, 0, -1);
12202
12203 /* Assign to the glyphs written above the
12204 string where the `%x' came from, position
12205 of the `%'. */
12206 if (nwritten > 0)
12207 {
12208 struct glyph *glyph
12209 = (it->glyph_row->glyphs[TEXT_AREA]
12210 + nglyphs_before);
12211 int i;
12212
12213 for (i = 0; i < nwritten; ++i)
12214 {
12215 glyph[i].object = elt;
12216 glyph[i].charpos = charpos;
12217 }
12218
12219 n += nwritten;
12220 }
12221 }
d39b6696 12222 }
a2889657
JB
12223 }
12224 }
12225 }
12226 break;
12227
12228 case Lisp_Symbol:
12229 /* A symbol: process the value of the symbol recursively
12230 as if it appeared here directly. Avoid error if symbol void.
12231 Special case: if value of symbol is a string, output the string
12232 literally. */
12233 {
12234 register Lisp_Object tem;
12235 tem = Fboundp (elt);
265a9e55 12236 if (!NILP (tem))
a2889657
JB
12237 {
12238 tem = Fsymbol_value (elt);
12239 /* If value is a string, output that string literally:
12240 don't check for % within it. */
e24c997d 12241 if (STRINGP (tem))
d39b6696 12242 {
5f5c8ee5
GM
12243 prec = XSTRING (tem)->size;
12244 if (precision > 0 && prec > precision - n)
12245 prec = precision - n;
d39b6696 12246 if (frame_title_ptr)
5f5c8ee5 12247 n += store_frame_title (XSTRING (tem)->data, -1, prec);
d39b6696 12248 else
5f5c8ee5
GM
12249 n += display_string (NULL, tem, Qnil, 0, 0, it,
12250 0, prec, 0, -1);
d39b6696 12251 }
a2889657 12252 else if (!EQ (tem, elt))
5f5c8ee5
GM
12253 {
12254 /* Give up right away for nil or t. */
12255 elt = tem;
12256 goto tail_recurse;
12257 }
a2889657
JB
12258 }
12259 }
12260 break;
12261
12262 case Lisp_Cons:
12263 {
12264 register Lisp_Object car, tem;
12265
12266 /* A cons cell: three distinct cases.
12267 If first element is a string or a cons, process all the elements
12268 and effectively concatenate them.
12269 If first element is a negative number, truncate displaying cdr to
12270 at most that many characters. If positive, pad (with spaces)
12271 to at least that many characters.
12272 If first element is a symbol, process the cadr or caddr recursively
12273 according to whether the symbol's value is non-nil or nil. */
9472f927 12274 car = XCAR (elt);
5f5c8ee5
GM
12275 if (EQ (car, QCeval) && CONSP (XCDR (elt)))
12276 {
12277 /* An element of the form (:eval FORM) means evaluate FORM
12278 and use the result as mode line elements. */
12279 struct gcpro gcpro1;
12280 Lisp_Object spec;
12281
12282 spec = eval_form (XCAR (XCDR (elt)));
12283 GCPRO1 (spec);
12284 n += display_mode_element (it, depth, field_width - n,
12285 precision - n, spec);
12286 UNGCPRO;
12287 }
12288 else if (SYMBOLP (car))
a2889657
JB
12289 {
12290 tem = Fboundp (car);
9472f927 12291 elt = XCDR (elt);
e24c997d 12292 if (!CONSP (elt))
a2889657
JB
12293 goto invalid;
12294 /* elt is now the cdr, and we know it is a cons cell.
12295 Use its car if CAR has a non-nil value. */
265a9e55 12296 if (!NILP (tem))
a2889657
JB
12297 {
12298 tem = Fsymbol_value (car);
265a9e55 12299 if (!NILP (tem))
9472f927
GM
12300 {
12301 elt = XCAR (elt);
12302 goto tail_recurse;
12303 }
a2889657
JB
12304 }
12305 /* Symbol's value is nil (or symbol is unbound)
12306 Get the cddr of the original list
12307 and if possible find the caddr and use that. */
9472f927 12308 elt = XCDR (elt);
265a9e55 12309 if (NILP (elt))
a2889657 12310 break;
e24c997d 12311 else if (!CONSP (elt))
a2889657 12312 goto invalid;
9472f927 12313 elt = XCAR (elt);
a2889657
JB
12314 goto tail_recurse;
12315 }
e24c997d 12316 else if (INTEGERP (car))
a2889657
JB
12317 {
12318 register int lim = XINT (car);
9472f927 12319 elt = XCDR (elt);
a2889657 12320 if (lim < 0)
5f5c8ee5
GM
12321 {
12322 /* Negative int means reduce maximum width. */
12323 if (precision <= 0)
12324 precision = -lim;
12325 else
12326 precision = min (precision, -lim);
12327 }
a2889657
JB
12328 else if (lim > 0)
12329 {
12330 /* Padding specified. Don't let it be more than
12331 current maximum. */
5f5c8ee5
GM
12332 if (precision > 0)
12333 lim = min (precision, lim);
12334
a2889657
JB
12335 /* If that's more padding than already wanted, queue it.
12336 But don't reduce padding already specified even if
12337 that is beyond the current truncation point. */
5f5c8ee5 12338 field_width = max (lim, field_width);
a2889657
JB
12339 }
12340 goto tail_recurse;
12341 }
e24c997d 12342 else if (STRINGP (car) || CONSP (car))
a2889657
JB
12343 {
12344 register int limit = 50;
5f5c8ee5
GM
12345 /* Limit is to protect against circular lists. */
12346 while (CONSP (elt)
12347 && --limit > 0
12348 && (precision <= 0 || n < precision))
a2889657 12349 {
5f5c8ee5 12350 n += display_mode_element (it, depth, field_width - n,
9472f927
GM
12351 precision - n, XCAR (elt));
12352 elt = XCDR (elt);
a2889657
JB
12353 }
12354 }
12355 }
12356 break;
12357
12358 default:
12359 invalid:
d39b6696 12360 if (frame_title_ptr)
5f5c8ee5 12361 n += store_frame_title ("*invalid*", 0, precision - n);
d39b6696 12362 else
5f5c8ee5
GM
12363 n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
12364 precision - n, 0, 0);
12365 return n;
a2889657
JB
12366 }
12367
5f5c8ee5
GM
12368 /* Pad to FIELD_WIDTH. */
12369 if (field_width > 0 && n < field_width)
12370 {
12371 if (frame_title_ptr)
12372 n += store_frame_title ("", field_width - n, 0);
12373 else
12374 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
12375 0, 0, 0);
12376 }
12377
12378 return n;
a2889657 12379}
5f5c8ee5
GM
12380
12381
766525bc
RS
12382/* Write a null-terminated, right justified decimal representation of
12383 the positive integer D to BUF using a minimal field width WIDTH. */
12384
12385static void
12386pint2str (buf, width, d)
12387 register char *buf;
12388 register int width;
12389 register int d;
12390{
12391 register char *p = buf;
12392
12393 if (d <= 0)
5f5c8ee5 12394 *p++ = '0';
766525bc 12395 else
5f5c8ee5 12396 {
766525bc 12397 while (d > 0)
5f5c8ee5 12398 {
766525bc
RS
12399 *p++ = d % 10 + '0';
12400 d /= 10;
5f5c8ee5
GM
12401 }
12402 }
12403
12404 for (width -= (int) (p - buf); width > 0; --width)
12405 *p++ = ' ';
766525bc
RS
12406 *p-- = '\0';
12407 while (p > buf)
5f5c8ee5 12408 {
766525bc
RS
12409 d = *buf;
12410 *buf++ = *p;
12411 *p-- = d;
5f5c8ee5 12412 }
766525bc
RS
12413}
12414
5f5c8ee5 12415/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
12416 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
12417 type of CODING_SYSTEM. Return updated pointer into BUF. */
12418
6693a99a 12419static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 12420
1c9241f5
KH
12421static char *
12422decode_mode_spec_coding (coding_system, buf, eol_flag)
12423 Lisp_Object coding_system;
12424 register char *buf;
12425 int eol_flag;
12426{
1e1078d6 12427 Lisp_Object val;
916848d8 12428 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
302f2b38
EZ
12429 unsigned char *eol_str;
12430 int eol_str_len;
12431 /* The EOL conversion we are using. */
12432 Lisp_Object eoltype;
1e1078d6 12433
4a09dee0 12434 val = Fget (coding_system, Qcoding_system);
1c9241f5 12435
4a09dee0 12436 if (!VECTORP (val)) /* Not yet decided. */
1c9241f5 12437 {
916848d8
RS
12438 if (multibyte)
12439 *buf++ = '-';
21e989e3 12440 if (eol_flag)
302f2b38 12441 eoltype = eol_mnemonic_undecided;
1e1078d6 12442 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
12443 }
12444 else
12445 {
1e1078d6
RS
12446 Lisp_Object eolvalue;
12447
12448 eolvalue = Fget (coding_system, Qeol_type);
12449
916848d8
RS
12450 if (multibyte)
12451 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
12452
1c9241f5
KH
12453 if (eol_flag)
12454 {
1e1078d6
RS
12455 /* The EOL conversion that is normal on this system. */
12456
12457 if (NILP (eolvalue)) /* Not yet decided. */
12458 eoltype = eol_mnemonic_undecided;
12459 else if (VECTORP (eolvalue)) /* Not yet decided. */
12460 eoltype = eol_mnemonic_undecided;
12461 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
12462 eoltype = (XFASTINT (eolvalue) == 0
12463 ? eol_mnemonic_unix
12464 : (XFASTINT (eolvalue) == 1
12465 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
12466 }
12467 }
5f5c8ee5 12468
302f2b38
EZ
12469 if (eol_flag)
12470 {
12471 /* Mention the EOL conversion if it is not the usual one. */
12472 if (STRINGP (eoltype))
12473 {
12474 eol_str = XSTRING (eoltype)->data;
12475 eol_str_len = XSTRING (eoltype)->size;
12476 }
f30b3499
KH
12477 else if (INTEGERP (eoltype)
12478 && CHAR_VALID_P (XINT (eoltype), 0))
12479 {
4a09dee0 12480 eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
260a86a0 12481 eol_str_len = CHAR_STRING (XINT (eoltype), eol_str);
f30b3499 12482 }
302f2b38
EZ
12483 else
12484 {
12485 eol_str = invalid_eol_type;
12486 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 12487 }
f30b3499 12488 bcopy (eol_str, buf, eol_str_len);
302f2b38 12489 buf += eol_str_len;
1c9241f5 12490 }
302f2b38 12491
1c9241f5
KH
12492 return buf;
12493}
12494
a2889657 12495/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
12496 generated by character C. PRECISION >= 0 means don't return a
12497 string longer than that value. FIELD_WIDTH > 0 means pad the
12498 string returned with spaces to that value. */
a2889657 12499
11e82b76
JB
12500static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
12501
a2889657 12502static char *
5f5c8ee5 12503decode_mode_spec (w, c, field_width, precision)
a2889657 12504 struct window *w;
68c45bf0 12505 register int c;
5f5c8ee5 12506 int field_width, precision;
a2889657 12507{
0b67772d 12508 Lisp_Object obj;
5f5c8ee5
GM
12509 struct frame *f = XFRAME (WINDOW_FRAME (w));
12510 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 12511 struct buffer *b = XBUFFER (w->buffer);
a2889657 12512
0b67772d 12513 obj = Qnil;
a2889657
JB
12514
12515 switch (c)
12516 {
1af9f229
RS
12517 case '*':
12518 if (!NILP (b->read_only))
12519 return "%";
12520 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12521 return "*";
12522 return "-";
12523
12524 case '+':
12525 /* This differs from %* only for a modified read-only buffer. */
12526 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12527 return "*";
12528 if (!NILP (b->read_only))
12529 return "%";
12530 return "-";
12531
12532 case '&':
12533 /* This differs from %* in ignoring read-only-ness. */
12534 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12535 return "*";
12536 return "-";
12537
12538 case '%':
12539 return "%";
12540
12541 case '[':
12542 {
12543 int i;
12544 char *p;
12545
12546 if (command_loop_level > 5)
12547 return "[[[... ";
12548 p = decode_mode_spec_buf;
12549 for (i = 0; i < command_loop_level; i++)
12550 *p++ = '[';
12551 *p = 0;
12552 return decode_mode_spec_buf;
12553 }
12554
12555 case ']':
12556 {
12557 int i;
12558 char *p;
12559
12560 if (command_loop_level > 5)
12561 return " ...]]]";
12562 p = decode_mode_spec_buf;
12563 for (i = 0; i < command_loop_level; i++)
12564 *p++ = ']';
12565 *p = 0;
12566 return decode_mode_spec_buf;
12567 }
12568
12569 case '-':
12570 {
1af9f229 12571 register int i;
5f5c8ee5
GM
12572
12573 /* Let lots_of_dashes be a string of infinite length. */
12574 if (field_width <= 0
12575 || field_width > sizeof (lots_of_dashes))
1af9f229 12576 {
5f5c8ee5
GM
12577 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
12578 decode_mode_spec_buf[i] = '-';
12579 decode_mode_spec_buf[i] = '\0';
12580 return decode_mode_spec_buf;
1af9f229 12581 }
5f5c8ee5
GM
12582 else
12583 return lots_of_dashes;
1af9f229
RS
12584 }
12585
a2889657 12586 case 'b':
d39b6696 12587 obj = b->name;
a2889657
JB
12588 break;
12589
1af9f229
RS
12590 case 'c':
12591 {
12592 int col = current_column ();
12593 XSETFASTINT (w->column_number_displayed, col);
5f5c8ee5 12594 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
12595 return decode_mode_spec_buf;
12596 }
12597
12598 case 'F':
12599 /* %F displays the frame name. */
5f5c8ee5 12600 if (!NILP (f->title))
95184b48 12601 return (char *) XSTRING (f->title)->data;
fd8ff63d 12602 if (f->explicit_name || ! FRAME_WINDOW_P (f))
95184b48 12603 return (char *) XSTRING (f->name)->data;
9c6da96f 12604 return "Emacs";
1af9f229 12605
a2889657 12606 case 'f':
d39b6696 12607 obj = b->filename;
a2889657
JB
12608 break;
12609
aa6d10fa
RS
12610 case 'l':
12611 {
12adba34
RS
12612 int startpos = XMARKER (w->start)->charpos;
12613 int startpos_byte = marker_byte_position (w->start);
12614 int line, linepos, linepos_byte, topline;
aa6d10fa 12615 int nlines, junk;
aa6d10fa
RS
12616 int height = XFASTINT (w->height);
12617
12618 /* If we decided that this buffer isn't suitable for line numbers,
12619 don't forget that too fast. */
12620 if (EQ (w->base_line_pos, w->buffer))
766525bc 12621 goto no_value;
5300fd39
RS
12622 /* But do forget it, if the window shows a different buffer now. */
12623 else if (BUFFERP (w->base_line_pos))
12624 w->base_line_pos = Qnil;
aa6d10fa
RS
12625
12626 /* If the buffer is very big, don't waste time. */
37d034d3 12627 if (INTEGERP (Vline_number_display_limit)
090703f4 12628 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
aa6d10fa
RS
12629 {
12630 w->base_line_pos = Qnil;
12631 w->base_line_number = Qnil;
766525bc 12632 goto no_value;
aa6d10fa
RS
12633 }
12634
12635 if (!NILP (w->base_line_number)
12636 && !NILP (w->base_line_pos)
12adba34 12637 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
12638 {
12639 line = XFASTINT (w->base_line_number);
12640 linepos = XFASTINT (w->base_line_pos);
12adba34 12641 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
12642 }
12643 else
12644 {
12645 line = 1;
d39b6696 12646 linepos = BUF_BEGV (b);
12adba34 12647 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
12648 }
12649
12650 /* Count lines from base line to window start position. */
12adba34
RS
12651 nlines = display_count_lines (linepos, linepos_byte,
12652 startpos_byte,
12653 startpos, &junk);
aa6d10fa
RS
12654
12655 topline = nlines + line;
12656
12657 /* Determine a new base line, if the old one is too close
12658 or too far away, or if we did not have one.
12659 "Too close" means it's plausible a scroll-down would
12660 go back past it. */
d39b6696 12661 if (startpos == BUF_BEGV (b))
aa6d10fa 12662 {
c2213350
KH
12663 XSETFASTINT (w->base_line_number, topline);
12664 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
12665 }
12666 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 12667 || linepos == BUF_BEGV (b))
aa6d10fa 12668 {
d39b6696 12669 int limit = BUF_BEGV (b);
12adba34 12670 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 12671 int position;
5d121aec 12672 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
12673
12674 if (startpos - distance > limit)
12adba34
RS
12675 {
12676 limit = startpos - distance;
12677 limit_byte = CHAR_TO_BYTE (limit);
12678 }
aa6d10fa 12679
12adba34
RS
12680 nlines = display_count_lines (startpos, startpos_byte,
12681 limit_byte,
12682 - (height * 2 + 30),
aa6d10fa
RS
12683 &position);
12684 /* If we couldn't find the lines we wanted within
5d121aec 12685 line_number_display_limit_width chars per line,
aa6d10fa 12686 give up on line numbers for this window. */
12adba34 12687 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
12688 {
12689 w->base_line_pos = w->buffer;
12690 w->base_line_number = Qnil;
766525bc 12691 goto no_value;
aa6d10fa
RS
12692 }
12693
c2213350 12694 XSETFASTINT (w->base_line_number, topline - nlines);
12adba34 12695 XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
aa6d10fa
RS
12696 }
12697
12698 /* Now count lines from the start pos to point. */
12adba34
RS
12699 nlines = display_count_lines (startpos, startpos_byte,
12700 PT_BYTE, PT, &junk);
aa6d10fa
RS
12701
12702 /* Record that we did display the line number. */
12703 line_number_displayed = 1;
12704
12705 /* Make the string to show. */
5f5c8ee5 12706 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 12707 return decode_mode_spec_buf;
766525bc
RS
12708 no_value:
12709 {
12710 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
12711 int pad = field_width - 2;
12712 while (pad-- > 0)
12713 *p++ = ' ';
12714 *p++ = '?';
b357b9d4
KR
12715 *p++ = '?';
12716 *p = '\0';
766525bc
RS
12717 return decode_mode_spec_buf;
12718 }
aa6d10fa
RS
12719 }
12720 break;
12721
a2889657 12722 case 'm':
d39b6696 12723 obj = b->mode_name;
a2889657
JB
12724 break;
12725
12726 case 'n':
d39b6696 12727 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
12728 return " Narrow";
12729 break;
12730
a2889657
JB
12731 case 'p':
12732 {
12733 int pos = marker_position (w->start);
d39b6696 12734 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 12735
d39b6696 12736 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 12737 {
d39b6696 12738 if (pos <= BUF_BEGV (b))
a2889657
JB
12739 return "All";
12740 else
12741 return "Bottom";
12742 }
d39b6696 12743 else if (pos <= BUF_BEGV (b))
a2889657
JB
12744 return "Top";
12745 else
12746 {
3c7d31b9
RS
12747 if (total > 1000000)
12748 /* Do it differently for a large value, to avoid overflow. */
12749 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12750 else
12751 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
12752 /* We can't normally display a 3-digit number,
12753 so get us a 2-digit number that is close. */
12754 if (total == 100)
12755 total = 99;
12756 sprintf (decode_mode_spec_buf, "%2d%%", total);
12757 return decode_mode_spec_buf;
12758 }
12759 }
12760
8ffcb79f
RS
12761 /* Display percentage of size above the bottom of the screen. */
12762 case 'P':
12763 {
12764 int toppos = marker_position (w->start);
d39b6696
KH
12765 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
12766 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 12767
d39b6696 12768 if (botpos >= BUF_ZV (b))
8ffcb79f 12769 {
d39b6696 12770 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12771 return "All";
12772 else
12773 return "Bottom";
12774 }
12775 else
12776 {
3c7d31b9
RS
12777 if (total > 1000000)
12778 /* Do it differently for a large value, to avoid overflow. */
12779 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12780 else
12781 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
12782 /* We can't normally display a 3-digit number,
12783 so get us a 2-digit number that is close. */
12784 if (total == 100)
12785 total = 99;
d39b6696 12786 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12787 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
12788 else
12789 sprintf (decode_mode_spec_buf, "%2d%%", total);
12790 return decode_mode_spec_buf;
12791 }
12792 }
12793
1af9f229
RS
12794 case 's':
12795 /* status of process */
12796 obj = Fget_buffer_process (w->buffer);
12797 if (NILP (obj))
12798 return "no process";
12799#ifdef subprocesses
12800 obj = Fsymbol_name (Fprocess_status (obj));
12801#endif
12802 break;
d39b6696 12803
1af9f229
RS
12804 case 't': /* indicate TEXT or BINARY */
12805#ifdef MODE_LINE_BINARY_TEXT
12806 return MODE_LINE_BINARY_TEXT (b);
12807#else
12808 return "T";
12809#endif
1c9241f5
KH
12810
12811 case 'z':
12812 /* coding-system (not including end-of-line format) */
12813 case 'Z':
12814 /* coding-system (including end-of-line type) */
12815 {
12816 int eol_flag = (c == 'Z');
539b4d41 12817 char *p = decode_mode_spec_buf;
1c9241f5 12818
d30e754b 12819 if (! FRAME_WINDOW_P (f))
1c9241f5 12820 {
11c52c4f
RS
12821 /* No need to mention EOL here--the terminal never needs
12822 to do EOL conversion. */
12823 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
12824 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 12825 }
f13c925f 12826 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 12827 p, eol_flag);
f13c925f 12828
11c52c4f 12829#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
12830#ifdef subprocesses
12831 obj = Fget_buffer_process (Fcurrent_buffer ());
12832 if (PROCESSP (obj))
12833 {
12834 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
12835 p, eol_flag);
12836 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
12837 p, eol_flag);
12838 }
12839#endif /* subprocesses */
11c52c4f 12840#endif /* 0 */
1c9241f5
KH
12841 *p = 0;
12842 return decode_mode_spec_buf;
12843 }
a2889657 12844 }
d39b6696 12845
e24c997d 12846 if (STRINGP (obj))
a2889657
JB
12847 return (char *) XSTRING (obj)->data;
12848 else
12849 return "";
12850}
5f5c8ee5
GM
12851
12852
12adba34
RS
12853/* Count up to COUNT lines starting from START / START_BYTE.
12854 But don't go beyond LIMIT_BYTE.
12855 Return the number of lines thus found (always nonnegative).
59b49f63 12856
12adba34 12857 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
12858
12859static int
12adba34
RS
12860display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
12861 int start, start_byte, limit_byte, count;
12862 int *byte_pos_ptr;
59b49f63 12863{
59b49f63
RS
12864 register unsigned char *cursor;
12865 unsigned char *base;
12866
12867 register int ceiling;
12868 register unsigned char *ceiling_addr;
12adba34 12869 int orig_count = count;
59b49f63
RS
12870
12871 /* If we are not in selective display mode,
12872 check only for newlines. */
12adba34
RS
12873 int selective_display = (!NILP (current_buffer->selective_display)
12874 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
12875
12876 if (count > 0)
12adba34
RS
12877 {
12878 while (start_byte < limit_byte)
12879 {
12880 ceiling = BUFFER_CEILING_OF (start_byte);
12881 ceiling = min (limit_byte - 1, ceiling);
12882 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
12883 base = (cursor = BYTE_POS_ADDR (start_byte));
12884 while (1)
12885 {
12886 if (selective_display)
12887 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
12888 ;
12889 else
12890 while (*cursor != '\n' && ++cursor != ceiling_addr)
12891 ;
12892
12893 if (cursor != ceiling_addr)
12894 {
12895 if (--count == 0)
12896 {
12897 start_byte += cursor - base + 1;
12898 *byte_pos_ptr = start_byte;
12899 return orig_count;
12900 }
12901 else
12902 if (++cursor == ceiling_addr)
12903 break;
12904 }
12905 else
12906 break;
12907 }
12908 start_byte += cursor - base;
12909 }
12910 }
59b49f63
RS
12911 else
12912 {
12adba34
RS
12913 while (start_byte > limit_byte)
12914 {
12915 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
12916 ceiling = max (limit_byte, ceiling);
12917 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
12918 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
12919 while (1)
12920 {
12adba34
RS
12921 if (selective_display)
12922 while (--cursor != ceiling_addr
12923 && *cursor != '\n' && *cursor != 015)
12924 ;
12925 else
12926 while (--cursor != ceiling_addr && *cursor != '\n')
12927 ;
12928
59b49f63
RS
12929 if (cursor != ceiling_addr)
12930 {
12931 if (++count == 0)
12932 {
12adba34
RS
12933 start_byte += cursor - base + 1;
12934 *byte_pos_ptr = start_byte;
12935 /* When scanning backwards, we should
12936 not count the newline posterior to which we stop. */
12937 return - orig_count - 1;
59b49f63
RS
12938 }
12939 }
12940 else
12941 break;
12942 }
12adba34
RS
12943 /* Here we add 1 to compensate for the last decrement
12944 of CURSOR, which took it past the valid range. */
12945 start_byte += cursor - base + 1;
59b49f63
RS
12946 }
12947 }
12948
12adba34 12949 *byte_pos_ptr = limit_byte;
aa6d10fa 12950
12adba34
RS
12951 if (count < 0)
12952 return - orig_count + count;
12953 return orig_count - count;
aa6d10fa 12954
12adba34 12955}
a2889657 12956
a2889657 12957
5f5c8ee5
GM
12958\f
12959/***********************************************************************
12960 Displaying strings
12961 ***********************************************************************/
278feba9 12962
5f5c8ee5 12963/* Display a NUL-terminated string, starting with index START.
a3788d53 12964
5f5c8ee5
GM
12965 If STRING is non-null, display that C string. Otherwise, the Lisp
12966 string LISP_STRING is displayed.
a2889657 12967
5f5c8ee5
GM
12968 If FACE_STRING is not nil, FACE_STRING_POS is a position in
12969 FACE_STRING. Display STRING or LISP_STRING with the face at
12970 FACE_STRING_POS in FACE_STRING:
a2889657 12971
5f5c8ee5
GM
12972 Display the string in the environment given by IT, but use the
12973 standard display table, temporarily.
a3788d53 12974
5f5c8ee5
GM
12975 FIELD_WIDTH is the minimum number of output glyphs to produce.
12976 If STRING has fewer characters than FIELD_WIDTH, pad to the right
12977 with spaces. If STRING has more characters, more than FIELD_WIDTH
12978 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
12979
12980 PRECISION is the maximum number of characters to output from
12981 STRING. PRECISION < 0 means don't truncate the string.
a2889657 12982
5f5c8ee5 12983 This is roughly equivalent to printf format specifiers:
a2889657 12984
5f5c8ee5
GM
12985 FIELD_WIDTH PRECISION PRINTF
12986 ----------------------------------------
12987 -1 -1 %s
12988 -1 10 %.10s
12989 10 -1 %10s
12990 20 10 %20.10s
a2889657 12991
5f5c8ee5
GM
12992 MULTIBYTE zero means do not display multibyte chars, > 0 means do
12993 display them, and < 0 means obey the current buffer's value of
12994 enable_multibyte_characters.
278feba9 12995
5f5c8ee5 12996 Value is the number of glyphs produced. */
b1d1124b 12997
5f5c8ee5
GM
12998static int
12999display_string (string, lisp_string, face_string, face_string_pos,
13000 start, it, field_width, precision, max_x, multibyte)
13001 unsigned char *string;
13002 Lisp_Object lisp_string;
68c45bf0
PE
13003 Lisp_Object face_string;
13004 int face_string_pos;
5f5c8ee5
GM
13005 int start;
13006 struct it *it;
13007 int field_width, precision, max_x;
13008 int multibyte;
13009{
13010 int hpos_at_start = it->hpos;
13011 int saved_face_id = it->face_id;
13012 struct glyph_row *row = it->glyph_row;
13013
13014 /* Initialize the iterator IT for iteration over STRING beginning
13015 with index START. We assume that IT may be modified here (which
13016 means that display_line has to do something when displaying a
13017 mini-buffer prompt, which it does). */
13018 reseat_to_string (it, string, lisp_string, start,
13019 precision, field_width, multibyte);
13020
13021 /* If displaying STRING, set up the face of the iterator
13022 from LISP_STRING, if that's given. */
13023 if (STRINGP (face_string))
13024 {
13025 int endptr;
13026 struct face *face;
13027
13028 it->face_id
13029 = face_at_string_position (it->w, face_string, face_string_pos,
13030 0, it->region_beg_charpos,
13031 it->region_end_charpos,
13032 &endptr, it->base_face_id);
13033 face = FACE_FROM_ID (it->f, it->face_id);
13034 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 13035 }
a2889657 13036
5f5c8ee5
GM
13037 /* Set max_x to the maximum allowed X position. Don't let it go
13038 beyond the right edge of the window. */
13039 if (max_x <= 0)
13040 max_x = it->last_visible_x;
13041 else
13042 max_x = min (max_x, it->last_visible_x);
efc63ef0 13043
5f5c8ee5
GM
13044 /* Skip over display elements that are not visible. because IT->w is
13045 hscrolled. */
13046 if (it->current_x < it->first_visible_x)
13047 move_it_in_display_line_to (it, 100000, it->first_visible_x,
13048 MOVE_TO_POS | MOVE_TO_X);
a2889657 13049
5f5c8ee5
GM
13050 row->ascent = it->max_ascent;
13051 row->height = it->max_ascent + it->max_descent;
312246d1
GM
13052 row->phys_ascent = it->max_phys_ascent;
13053 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 13054
5f5c8ee5
GM
13055 /* This condition is for the case that we are called with current_x
13056 past last_visible_x. */
13057 while (it->current_x < max_x)
a2889657 13058 {
5f5c8ee5 13059 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 13060
5f5c8ee5
GM
13061 /* Get the next display element. */
13062 if (!get_next_display_element (it))
90adcf20 13063 break;
1c9241f5 13064
5f5c8ee5
GM
13065 /* Produce glyphs. */
13066 x_before = it->current_x;
13067 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
13068 PRODUCE_GLYPHS (it);
90adcf20 13069
5f5c8ee5
GM
13070 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
13071 i = 0;
13072 x = x_before;
13073 while (i < nglyphs)
a2889657 13074 {
5f5c8ee5
GM
13075 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
13076
13077 if (!it->truncate_lines_p
13078 && x + glyph->pixel_width > max_x)
13079 {
13080 /* End of continued line or max_x reached. */
13081 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
13082 it->current_x = x;
13083 break;
13084 }
13085 else if (x + glyph->pixel_width > it->first_visible_x)
13086 {
13087 /* Glyph is at least partially visible. */
13088 ++it->hpos;
13089 if (x < it->first_visible_x)
13090 it->glyph_row->x = x - it->first_visible_x;
13091 }
13092 else
a2889657 13093 {
5f5c8ee5
GM
13094 /* Glyph is off the left margin of the display area.
13095 Should not happen. */
13096 abort ();
a2889657 13097 }
5f5c8ee5
GM
13098
13099 row->ascent = max (row->ascent, it->max_ascent);
13100 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
13101 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
13102 row->phys_height = max (row->phys_height,
13103 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
13104 x += glyph->pixel_width;
13105 ++i;
a2889657 13106 }
5f5c8ee5
GM
13107
13108 /* Stop if max_x reached. */
13109 if (i < nglyphs)
13110 break;
13111
13112 /* Stop at line ends. */
13113 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 13114 {
5f5c8ee5
GM
13115 it->continuation_lines_width = 0;
13116 break;
a2889657 13117 }
1c9241f5 13118
5f5c8ee5 13119 set_iterator_to_next (it);
a688bb24 13120
5f5c8ee5
GM
13121 /* Stop if truncating at the right edge. */
13122 if (it->truncate_lines_p
13123 && it->current_x >= it->last_visible_x)
13124 {
13125 /* Add truncation mark, but don't do it if the line is
13126 truncated at a padding space. */
13127 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 13128 {
5f5c8ee5
GM
13129 if (!FRAME_WINDOW_P (it->f))
13130 produce_special_glyphs (it, IT_TRUNCATION);
13131 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 13132 }
5f5c8ee5 13133 break;
1c9241f5 13134 }
a2889657
JB
13135 }
13136
5f5c8ee5
GM
13137 /* Maybe insert a truncation at the left. */
13138 if (it->first_visible_x
13139 && IT_CHARPOS (*it) > 0)
a2889657 13140 {
5f5c8ee5
GM
13141 if (!FRAME_WINDOW_P (it->f))
13142 insert_left_trunc_glyphs (it);
13143 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
13144 }
13145
5f5c8ee5
GM
13146 it->face_id = saved_face_id;
13147
13148 /* Value is number of columns displayed. */
13149 return it->hpos - hpos_at_start;
13150}
a2889657 13151
a2889657 13152
a2889657 13153\f
5f5c8ee5
GM
13154/* This is like a combination of memq and assq. Return 1 if PROPVAL
13155 appears as an element of LIST or as the car of an element of LIST.
13156 If PROPVAL is a list, compare each element against LIST in that
13157 way, and return 1 if any element of PROPVAL is found in LIST.
13158 Otherwise return 0. This function cannot quit. */
642eefc6
RS
13159
13160int
13161invisible_p (propval, list)
13162 register Lisp_Object propval;
13163 Lisp_Object list;
13164{
af460d46 13165 register Lisp_Object tail, proptail;
9472f927 13166 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
13167 {
13168 register Lisp_Object tem;
9472f927 13169 tem = XCAR (tail);
642eefc6
RS
13170 if (EQ (propval, tem))
13171 return 1;
9472f927 13172 if (CONSP (tem) && EQ (propval, XCAR (tem)))
642eefc6
RS
13173 return 1;
13174 }
af460d46
RS
13175 if (CONSP (propval))
13176 for (proptail = propval; CONSP (proptail);
9472f927 13177 proptail = XCDR (proptail))
af460d46
RS
13178 {
13179 Lisp_Object propelt;
9472f927
GM
13180 propelt = XCAR (proptail);
13181 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
13182 {
13183 register Lisp_Object tem;
9472f927 13184 tem = XCAR (tail);
af460d46
RS
13185 if (EQ (propelt, tem))
13186 return 1;
9472f927 13187 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
af460d46
RS
13188 return 1;
13189 }
13190 }
642eefc6
RS
13191 return 0;
13192}
13193
5f5c8ee5
GM
13194
13195/* Return 1 if PROPVAL appears as the car of an element of LIST and
13196 the cdr of that element is non-nil. If PROPVAL is a list, check
13197 each element of PROPVAL in that way, and the first time some
13198 element is found, return 1 if the cdr of that element is non-nil.
13199 Otherwise return 0. This function cannot quit. */
642eefc6
RS
13200
13201int
13202invisible_ellipsis_p (propval, list)
13203 register Lisp_Object propval;
13204 Lisp_Object list;
13205{
af460d46 13206 register Lisp_Object tail, proptail;
9472f927
GM
13207
13208 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
13209 {
13210 register Lisp_Object tem;
9472f927
GM
13211 tem = XCAR (tail);
13212 if (CONSP (tem) && EQ (propval, XCAR (tem)))
13213 return ! NILP (XCDR (tem));
642eefc6 13214 }
9472f927 13215
af460d46 13216 if (CONSP (propval))
9472f927 13217 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
af460d46
RS
13218 {
13219 Lisp_Object propelt;
9472f927
GM
13220 propelt = XCAR (proptail);
13221 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
13222 {
13223 register Lisp_Object tem;
9472f927
GM
13224 tem = XCAR (tail);
13225 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
13226 return ! NILP (XCDR (tem));
af460d46
RS
13227 }
13228 }
9472f927 13229
642eefc6
RS
13230 return 0;
13231}
5f5c8ee5
GM
13232
13233
642eefc6 13234\f
5f5c8ee5
GM
13235/***********************************************************************
13236 Initialization
13237 ***********************************************************************/
13238
a2889657
JB
13239void
13240syms_of_xdisp ()
13241{
c6e89d6c
GM
13242 Vwith_echo_area_save_vector = Qnil;
13243 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 13244
c6e89d6c
GM
13245 Vmessage_stack = Qnil;
13246 staticpro (&Vmessage_stack);
13247
735c094c 13248 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 13249 staticpro (&Qinhibit_redisplay);
735c094c 13250
5f5c8ee5
GM
13251#if GLYPH_DEBUG
13252 defsubr (&Sdump_glyph_matrix);
13253 defsubr (&Sdump_glyph_row);
e037b9ec 13254 defsubr (&Sdump_tool_bar_row);
5f5c8ee5 13255 defsubr (&Strace_redisplay_toggle);
bf9249e3 13256 defsubr (&Strace_to_stderr);
5f5c8ee5
GM
13257#endif
13258
cf074754
RS
13259 staticpro (&Qmenu_bar_update_hook);
13260 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
13261
d46fb96a 13262 staticpro (&Qoverriding_terminal_local_map);
7079aefa 13263 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 13264
399164b4
KH
13265 staticpro (&Qoverriding_local_map);
13266 Qoverriding_local_map = intern ("overriding-local-map");
13267
75c43375
RS
13268 staticpro (&Qwindow_scroll_functions);
13269 Qwindow_scroll_functions = intern ("window-scroll-functions");
13270
e0bfbde6
RS
13271 staticpro (&Qredisplay_end_trigger_functions);
13272 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
5f5c8ee5 13273
2e54982e
RS
13274 staticpro (&Qinhibit_point_motion_hooks);
13275 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
13276
9499d71b
GM
13277 QCdata = intern (":data");
13278 staticpro (&QCdata);
5f5c8ee5 13279 Qdisplay = intern ("display");
f3751a65 13280 staticpro (&Qdisplay);
5f5c8ee5
GM
13281 Qspace_width = intern ("space-width");
13282 staticpro (&Qspace_width);
5f5c8ee5
GM
13283 Qraise = intern ("raise");
13284 staticpro (&Qraise);
13285 Qspace = intern ("space");
13286 staticpro (&Qspace);
f3751a65
GM
13287 Qmargin = intern ("margin");
13288 staticpro (&Qmargin);
5f5c8ee5 13289 Qleft_margin = intern ("left-margin");
f3751a65 13290 staticpro (&Qleft_margin);
5f5c8ee5 13291 Qright_margin = intern ("right-margin");
f3751a65 13292 staticpro (&Qright_margin);
5f5c8ee5
GM
13293 Qalign_to = intern ("align-to");
13294 staticpro (&Qalign_to);
13295 QCalign_to = intern (":align-to");
13296 staticpro (&QCalign_to);
5f5c8ee5
GM
13297 Qrelative_width = intern ("relative-width");
13298 staticpro (&Qrelative_width);
13299 QCrelative_width = intern (":relative-width");
13300 staticpro (&QCrelative_width);
13301 QCrelative_height = intern (":relative-height");
13302 staticpro (&QCrelative_height);
13303 QCeval = intern (":eval");
13304 staticpro (&QCeval);
d3acf96b 13305 Qwhen = intern ("when");
f3751a65 13306 staticpro (&Qwhen);
886bd6f2
GM
13307 QCfile = intern (":file");
13308 staticpro (&QCfile);
5f5c8ee5
GM
13309 Qfontified = intern ("fontified");
13310 staticpro (&Qfontified);
13311 Qfontification_functions = intern ("fontification-functions");
13312 staticpro (&Qfontification_functions);
5f5c8ee5
GM
13313 Qtrailing_whitespace = intern ("trailing-whitespace");
13314 staticpro (&Qtrailing_whitespace);
13315 Qimage = intern ("image");
13316 staticpro (&Qimage);
ad4f174e
GM
13317 Qmessage_truncate_lines = intern ("message-truncate-lines");
13318 staticpro (&Qmessage_truncate_lines);
5f5c8ee5 13319
a2889657
JB
13320 last_arrow_position = Qnil;
13321 last_arrow_string = Qnil;
f3751a65
GM
13322 staticpro (&last_arrow_position);
13323 staticpro (&last_arrow_string);
c6e89d6c
GM
13324
13325 echo_buffer[0] = echo_buffer[1] = Qnil;
13326 staticpro (&echo_buffer[0]);
13327 staticpro (&echo_buffer[1]);
13328
13329 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
13330 staticpro (&echo_area_buffer[0]);
13331 staticpro (&echo_area_buffer[1]);
a2889657 13332
6a94510a
GM
13333 Vmessages_buffer_name = build_string ("*Messages*");
13334 staticpro (&Vmessages_buffer_name);
13335
8f897821
GM
13336 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
13337 "Non-nil means highlight trailing whitespace.\n\
13338The face used for trailing whitespace is `trailing-whitespace'.");
13339 Vshow_trailing_whitespace = Qnil;
13340
735c094c
KH
13341 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
13342 "Non-nil means don't actually do any redisplay.\n\
13343This is used for internal purposes.");
13344 Vinhibit_redisplay = Qnil;
13345
a2889657 13346 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 13347 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
13348 Vglobal_mode_string = Qnil;
13349
13350 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
13351 "Marker for where to display an arrow on top of the buffer text.\n\
13352This must be the beginning of a line in order to work.\n\
13353See also `overlay-arrow-string'.");
13354 Voverlay_arrow_position = Qnil;
13355
13356 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
13357 "String to display as an arrow. See also `overlay-arrow-position'.");
13358 Voverlay_arrow_string = Qnil;
13359
13360 DEFVAR_INT ("scroll-step", &scroll_step,
13361 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
13362If that fails to bring point back on frame, point is centered instead.\n\
13363If this is zero, point is always centered after it moves off frame.");
a2889657 13364
0789adb2 13365 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
090f7baa
GM
13366 "*Scroll up to this many lines, to bring point back on screen.\n\
13367A value of zero means to scroll the text to center point vertically\n\
13368in the window.");
0789adb2
RS
13369 scroll_conservatively = 0;
13370
9afd2168
RS
13371 DEFVAR_INT ("scroll-margin", &scroll_margin,
13372 "*Number of lines of margin at the top and bottom of a window.\n\
13373Recenter the window whenever point gets within this many lines\n\
13374of the top or bottom of the window.");
13375 scroll_margin = 0;
13376
5f5c8ee5 13377#if GLYPH_DEBUG
a2889657 13378 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
5f5c8ee5 13379#endif
a2889657
JB
13380
13381 DEFVAR_BOOL ("truncate-partial-width-windows",
13382 &truncate_partial_width_windows,
44fa5b1e 13383 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
13384 truncate_partial_width_windows = 1;
13385
13386 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
13387 "*Non-nil means use inverse video for the mode line.");
13388 mode_line_inverse_video = 1;
aa6d10fa 13389
090703f4 13390 DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
5f5c8ee5 13391 "*Maximum buffer size for which line number should be displayed.\n\
db4f2bfa 13392If the buffer is bigger than this, the line number does not appear\n\
090703f4
GM
13393in the mode line. A value of nil means no limit.");
13394 Vline_number_display_limit = Qnil;
fba9ce76 13395
090703f4
GM
13396 DEFVAR_INT ("line-number-display-limit-width",
13397 &line_number_display_limit_width,
5d121aec
KH
13398 "*Maximum line width (in characters) for line number display.\n\
13399If the average length of the lines near point is bigger than this, then the\n\
13400line number may be omitted from the mode line.");
13401 line_number_display_limit_width = 200;
13402
fba9ce76
RS
13403 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
13404 "*Non-nil means highlight region even in nonselected windows.");
293a54ce 13405 highlight_nonselected_windows = 0;
d39b6696
KH
13406
13407 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
13408 "Non-nil if more than one frame is visible on this display.\n\
13409Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
13410This variable is not guaranteed to be accurate except while processing\n\
13411`frame-title-format' and `icon-title-format'.");
d39b6696
KH
13412
13413 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
5f5c8ee5 13414 "Template for displaying the title bar of visible frames.\n\
d39b6696
KH
13415\(Assuming the window manager supports this feature.)\n\
13416This variable has the same structure as `mode-line-format' (which see),\n\
13417and is used only on frames for which no explicit name has been set\n\
13418\(see `modify-frame-parameters').");
13419 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
5f5c8ee5 13420 "Template for displaying the title bar of an iconified frame.\n\
d39b6696
KH
13421\(Assuming the window manager supports this feature.)\n\
13422This variable has the same structure as `mode-line-format' (which see),\n\
13423and is used only on frames for which no explicit name has been set\n\
13424\(see `modify-frame-parameters').");
13425 Vicon_title_format
13426 = Vframe_title_format
13427 = Fcons (intern ("multiple-frames"),
13428 Fcons (build_string ("%b"),
13429 Fcons (Fcons (build_string (""),
13430 Fcons (intern ("invocation-name"),
13431 Fcons (build_string ("@"),
13432 Fcons (intern ("system-name"),
13433 Qnil)))),
13434 Qnil)));
5992c4f7
KH
13435
13436 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
13437 "Maximum number of lines to keep in the message log buffer.\n\
13438If nil, disable message logging. If t, log messages but don't truncate\n\
13439the buffer when it becomes large.");
13440 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
13441
13442 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
13443 "Functions called before redisplay, if window sizes have changed.\n\
13444The value should be a list of functions that take one argument.\n\
13445Just before redisplay, for each frame, if any of its windows have changed\n\
13446size since the last redisplay, or have been split or deleted,\n\
13447all the functions in the list are called, with the frame as argument.");
13448 Vwindow_size_change_functions = Qnil;
75c43375
RS
13449
13450 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
5f5c8ee5 13451 "List of Functions to call before redisplaying a window with scrolling.\n\
75c43375 13452Each function is called with two arguments, the window\n\
8d9583b0
RS
13453and its new display-start position. Note that the value of `window-end'\n\
13454is not valid when these functions are called.");
75c43375 13455 Vwindow_scroll_functions = Qnil;
5f5c8ee5 13456
e037b9ec
GM
13457 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
13458 "*Non-nil means automatically resize tool-bars.\n\
13459This increases a tool-bar's height if not all tool-bar items are visible.\n\
13460It decreases a tool-bar's height when it would display blank lines\n\
5f5c8ee5 13461otherwise.");
e037b9ec 13462 auto_resize_tool_bars_p = 1;
5f5c8ee5 13463
e037b9ec
GM
13464 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
13465 "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
13466 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 13467
e037b9ec
GM
13468 DEFVAR_INT ("tool-bar-button-margin", &tool_bar_button_margin,
13469 "*Margin around tool-bar buttons in pixels.");
13470 tool_bar_button_margin = 1;
5f5c8ee5 13471
e037b9ec
GM
13472 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
13473 "Relief thickness of tool-bar buttons.");
13474 tool_bar_button_relief = 3;
5f5c8ee5
GM
13475
13476 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
13477 "List of functions to call to fontify regions of text.\n\
13478Each function is called with one argument POS. Functions must\n\
13479fontify a region starting at POS in the current buffer, and give\n\
13480fontified regions the property `fontified'.\n\
13481This variable automatically becomes buffer-local when set.");
13482 Vfontification_functions = Qnil;
13483 Fmake_local_variable (Qfontification_functions);
7bbe686f
AI
13484
13485 DEFVAR_BOOL ("unibyte-display-via-language-environment",
5f5c8ee5
GM
13486 &unibyte_display_via_language_environment,
13487 "*Non-nil means display unibyte text according to language environment.\n\
7bbe686f
AI
13488Specifically this means that unibyte non-ASCII characters\n\
13489are displayed by converting them to the equivalent multibyte characters\n\
13490according to the current language environment. As a result, they are\n\
13491displayed according to the current fontset.");
13492 unibyte_display_via_language_environment = 0;
c6e89d6c
GM
13493
13494 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
13495 "*Maximum height for resizing mini-windows.\n\
13496If a float, it specifies a fraction of the mini-window frame's height.\n\
97cafc0f
GM
13497If an integer, it specifies a number of lines.\n\
13498If nil, don't resize.");
c6e89d6c 13499 Vmax_mini_window_height = make_float (0.25);
d6d26ed3
GM
13500
13501 DEFVAR_BOOL ("cursor-in-non-selected-windows",
13502 &cursor_in_non_selected_windows,
13503 "*Non-nil means display a hollow cursor in non-selected windows.\n\
13504Nil means don't display a cursor there.");
13505 cursor_in_non_selected_windows = 1;
d475bcb8
GM
13506
13507 DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p,
13508 "*Non-nil means scroll the display automatically to make point visible.");
13509 automatic_hscrolling_p = 1;
e00daaa0
GM
13510
13511 DEFVAR_LISP ("image-types", &Vimage_types,
ad4f174e 13512 "List of supported image types.\n\
e00daaa0
GM
13513Each element of the list is a symbol for a supported image type.");
13514 Vimage_types = Qnil;
ad4f174e
GM
13515
13516 DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
13517 "If non-nil, messages are truncated instead of resizing the echo area.\n\
13518Bind this around calls to `message' to let it take effect.");
13519 message_truncate_lines = 0;
a2889657
JB
13520}
13521
5f5c8ee5
GM
13522
13523/* Initialize this module when Emacs starts. */
13524
dfcf069d 13525void
a2889657
JB
13526init_xdisp ()
13527{
13528 Lisp_Object root_window;
5f5c8ee5 13529 struct window *mini_w;
a2889657 13530
5f5c8ee5 13531 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
13532
13533 mini_w = XWINDOW (minibuf_window);
11e82b76 13534 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 13535
a2889657
JB
13536 if (!noninteractive)
13537 {
5f5c8ee5
GM
13538 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
13539 int i;
13540
13541 XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f));
12c226c5 13542 set_window_height (root_window,
5f5c8ee5 13543 FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 13544 0);
c2213350 13545 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
13546 set_window_height (minibuf_window, 1, 0);
13547
c2213350
KH
13548 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
13549 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
5f5c8ee5
GM
13550
13551 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
13552 scratch_glyph_row.glyphs[TEXT_AREA + 1]
13553 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
13554
13555 /* The default ellipsis glyphs `...'. */
13556 for (i = 0; i < 3; ++i)
13557 XSETFASTINT (default_invis_vector[i], '.');
a2889657 13558 }
5f5c8ee5
GM
13559
13560#ifdef HAVE_WINDOW_SYSTEM
13561 {
13562 /* Allocate the buffer for frame titles. */
13563 int size = 100;
13564 frame_title_buf = (char *) xmalloc (size);
13565 frame_title_buf_end = frame_title_buf + size;
13566 frame_title_ptr = NULL;
13567 }
13568#endif /* HAVE_WINDOW_SYSTEM */
a2889657 13569}
5f5c8ee5
GM
13570
13571