(isearch-edit-string): When we try the search
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
5992c4f7 2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
a2889657
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
b1d1124b 8the Free Software Foundation; either version 2, or (at your option)
a2889657
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
a2889657
JB
20
21
18160b98 22#include <config.h>
a2889657
JB
23#include <stdio.h>
24/*#include <ctype.h>*/
25#undef NULL
26#include "lisp.h"
44fa5b1e 27#include "frame.h"
a2889657
JB
28#include "window.h"
29#include "termchar.h"
30#include "dispextern.h"
31#include "buffer.h"
32#include "indent.h"
33#include "commands.h"
34#include "macros.h"
35#include "disptab.h"
30c566e4 36#include "termhooks.h"
b0a0fbda 37#include "intervals.h"
fe8b0cf8 38#include "keyboard.h"
a2889657 39
8f3343d0 40#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
76412d64 41extern void set_frame_menubar ();
cd6dfed6 42extern int pending_menu_activation;
76412d64
RS
43#endif
44
a2889657
JB
45extern int interrupt_input;
46extern int command_loop_level;
47
b6436d4e
RS
48extern int minibuffer_auto_raise;
49
c4628384
RS
50extern Lisp_Object Qface;
51
399164b4
KH
52extern Lisp_Object Voverriding_local_map;
53extern Lisp_Object Voverriding_local_map_menu_flag;
54
d46fb96a 55Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 56Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 57Lisp_Object Qredisplay_end_trigger_functions;
399164b4 58
f88eb0b6 59/* Nonzero means print newline to stdout before next minibuffer message. */
a2889657
JB
60
61int noninteractive_need_newline;
62
f88eb0b6
KH
63/* Nonzero means print newline to message log before next message. */
64
3c6595e0 65static int message_log_need_newline;
f88eb0b6 66
a2889657
JB
67#define min(a, b) ((a) < (b) ? (a) : (b))
68#define max(a, b) ((a) > (b) ? (a) : (b))
210e752f
KH
69#define minmax(floor, val, ceil) \
70 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
a2889657
JB
71
72/* The buffer position of the first character appearing
44fa5b1e
JB
73 entirely or partially on the current frame line.
74 Or zero, which disables the optimization for the current frame line. */
a2889657
JB
75static int this_line_bufpos;
76
77/* Number of characters past the end of this line,
78 including the terminating newline */
79static int this_line_endpos;
80
44fa5b1e 81/* The vertical position of this frame line. */
a2889657
JB
82static int this_line_vpos;
83
44fa5b1e 84/* Hpos value for start of display on this frame line.
a2889657
JB
85 Usually zero, but negative if first character really began
86 on previous line */
87static int this_line_start_hpos;
88
89/* Buffer that this_line variables are describing. */
90static struct buffer *this_line_buffer;
91
a2889657 92/* Value of echo_area_glyphs when it was last acted on.
44fa5b1e 93 If this is nonzero, there is a message on the frame
a2889657
JB
94 in the minibuffer and it should be erased as soon
95 as it is no longer requested to appear. */
96char *previous_echo_glyphs;
97
44fa5b1e 98/* Nonzero means truncate lines in all windows less wide than the frame */
a2889657
JB
99int truncate_partial_width_windows;
100
d39b6696
KH
101/* Nonzero means we have more than one non-minibuffer-only frame.
102 Not guaranteed to be accurate except while parsing frame-title-format. */
103int multiple_frames;
104
a2889657
JB
105Lisp_Object Vglobal_mode_string;
106
107/* Marker for where to display an arrow on top of the buffer text. */
108Lisp_Object Voverlay_arrow_position;
109
110/* String to display for the arrow. */
111Lisp_Object Voverlay_arrow_string;
112
d39b6696
KH
113/* Like mode-line-format, but for the titlebar on a visible frame. */
114Lisp_Object Vframe_title_format;
115
116/* Like mode-line-format, but for the titlebar on an iconified frame. */
117Lisp_Object Vicon_title_format;
118
08b610e4
RS
119/* List of functions to call when a window's size changes. These
120 functions get one arg, a frame on which one or more windows' sizes
121 have changed. */
122static Lisp_Object Vwindow_size_change_functions;
123
a2889657 124/* Values of those variables at last redisplay. */
ded34426 125static Lisp_Object last_arrow_position, last_arrow_string;
a2889657 126
cf074754
RS
127Lisp_Object Qmenu_bar_update_hook;
128
a2889657
JB
129/* Nonzero if overlay arrow has been displayed once in this window. */
130static int overlay_arrow_seen;
131
ca26e1c8
KH
132/* Nonzero if visible end of buffer has already been displayed once
133 in this window. (We need this variable in case there are overlay
134 strings that get displayed there.) */
135static int zv_strings_seen;
136
fba9ce76
RS
137/* Nonzero means highlight the region even in nonselected windows. */
138static int highlight_nonselected_windows;
139
44fa5b1e 140/* If cursor motion alone moves point off frame,
a2889657 141 Try scrolling this many lines up or down if that will bring it back. */
14510fee 142static int scroll_step;
a2889657 143
0789adb2
RS
144/* Non-0 means scroll just far enough to bring point back on the screen,
145 when appropriate. */
146static int scroll_conservatively;
147
9afd2168
RS
148/* Recenter the window whenever point gets within this many lines
149 of the top or bottom of the window. */
150int scroll_margin;
151
a2889657
JB
152/* Nonzero if try_window_id has made blank lines at window bottom
153 since the last redisplay that paused */
154static int blank_end_of_window;
155
42640f83
RS
156/* Number of windows showing the buffer of the selected window
157 (or another buffer with the same base buffer).
a2889657
JB
158 keyboard.c refers to this. */
159int buffer_shared;
160
44fa5b1e 161/* display_text_line sets these to the frame position (origin 0) of point,
a2889657
JB
162 whether the window is selected or not.
163 Set one to -1 first to determine whether point was found afterwards. */
164
165static int cursor_vpos;
166static int cursor_hpos;
167
14510fee 168static int debug_end_pos;
a2889657
JB
169
170/* Nonzero means display mode line highlighted */
171int mode_line_inverse_video;
172
e9874cee 173static void redisplay_internal ();
ff6c30e5 174static int message_log_check_duplicate ();
a2889657
JB
175static void echo_area_display ();
176void mark_window_display_accurate ();
177static void redisplay_windows ();
178static void redisplay_window ();
90adcf20 179static void update_menu_bar ();
a2889657
JB
180static void try_window ();
181static int try_window_id ();
182static struct position *display_text_line ();
183static void display_mode_line ();
184static int display_mode_element ();
a2889657
JB
185static char *decode_mode_spec ();
186static int display_string ();
7ce2c095 187static void display_menu_bar ();
aa6d10fa 188static int display_count_lines ();
a2889657
JB
189
190/* Prompt to display in front of the minibuffer contents */
8c5b6a0a 191Lisp_Object minibuf_prompt;
a2889657
JB
192
193/* Width in columns of current minibuffer prompt. */
194int minibuf_prompt_width;
195
196/* Message to display instead of minibuffer contents
197 This is what the functions error and message make,
198 and command echoing uses it as well.
199 It overrides the minibuf_prompt as well as the buffer. */
200char *echo_area_glyphs;
201
90adcf20
RS
202/* This is the length of the message in echo_area_glyphs. */
203int echo_area_glyphs_length;
204
73af359d
RS
205/* This is the window where the echo area message was displayed.
206 It is always a minibuffer window, but it may not be the
207 same window currently active as a minibuffer. */
208Lisp_Object echo_area_window;
209
a2889657
JB
210/* true iff we should redraw the mode lines on the next redisplay */
211int update_mode_lines;
212
213/* Smallest number of characters before the gap
214 at any time since last redisplay that finished.
215 Valid for current buffer when try_window_id can be called. */
216int beg_unchanged;
217
218/* Smallest number of characters after the gap
219 at any time since last redisplay that finished.
220 Valid for current buffer when try_window_id can be called. */
221int end_unchanged;
222
223/* MODIFF as of last redisplay that finished;
8850a573
RS
224 if it matches MODIFF, and overlay_unchanged_modified
225 matches OVERLAY_MODIFF, that means beg_unchanged and end_unchanged
a2889657
JB
226 contain no useful information */
227int unchanged_modified;
228
8850a573
RS
229/* OVERLAY_MODIFF as of last redisplay that finished. */
230int overlay_unchanged_modified;
231
a2889657
JB
232/* Nonzero if window sizes or contents have changed
233 since last redisplay that finished */
234int windows_or_buffers_changed;
235
aa6d10fa
RS
236/* Nonzero after display_mode_line if %l was used
237 and it displayed a line number. */
238int line_number_displayed;
239
240/* Maximum buffer size for which to display line numbers. */
14510fee 241static int line_number_display_limit;
5992c4f7
KH
242
243/* Number of lines to keep in the message log buffer.
244 t means infinite. nil means don't log at all. */
245Lisp_Object Vmessage_log_max;
a2889657 246\f
1adc55de
RS
247/* Output a newline in the *Messages* buffer if "needs" one. */
248
3c6595e0
KH
249void
250message_log_maybe_newline ()
251{
252 if (message_log_need_newline)
253 message_dolog ("", 0, 1);
254}
255
256
d917be71
KH
257/* Add a string to the message log, optionally terminated with a newline.
258 This function calls low-level routines in order to bypass text property
259 hooks, etc. which might not be safe to run. */
90adcf20
RS
260
261void
f88eb0b6 262message_dolog (m, len, nlflag)
90adcf20 263 char *m;
f88eb0b6 264 int len, nlflag;
5992c4f7 265{
f88eb0b6 266 if (!NILP (Vmessage_log_max))
5992c4f7
KH
267 {
268 struct buffer *oldbuf;
269 int oldpoint, oldbegv, oldzv;
69f033ab 270 int old_windows_or_buffers_changed = windows_or_buffers_changed;
5992c4f7
KH
271
272 oldbuf = current_buffer;
3c6595e0 273 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
16c300fb 274 current_buffer->undo_list = Qt;
5992c4f7
KH
275 oldpoint = PT;
276 oldbegv = BEGV;
277 oldzv = ZV;
d917be71
KH
278 BEGV = BEG;
279 ZV = Z;
5992c4f7 280 if (oldpoint == Z)
f88eb0b6 281 oldpoint += len + nlflag;
5992c4f7 282 if (oldzv == Z)
f88eb0b6 283 oldzv += len + nlflag;
5992c4f7 284 TEMP_SET_PT (Z);
f88eb0b6
KH
285 if (len)
286 insert_1 (m, len, 1, 0);
287 if (nlflag)
5992c4f7 288 {
ff6c30e5
KH
289 int this_bol, prev_bol, dup;
290 insert_1 ("\n", 1, 1, 0);
291
292 this_bol = scan_buffer ('\n', Z, 0, -2, 0, 0);
293 if (this_bol > BEG)
294 {
295 prev_bol = scan_buffer ('\n', this_bol, 0, -2, 0, 0);
296 dup = message_log_check_duplicate (prev_bol, this_bol);
297 if (dup)
298 {
299 if (oldpoint > prev_bol)
300 oldpoint -= min (this_bol, oldpoint) - prev_bol;
301 if (oldbegv > prev_bol)
302 oldbegv -= min (this_bol, oldbegv) - prev_bol;
303 if (oldzv > prev_bol)
304 oldzv -= min (this_bol, oldzv) - prev_bol;
305 del_range_1 (prev_bol, this_bol, 0);
306 if (dup > 1)
307 {
308 char dupstr[40];
309 int duplen;
310
311 /* If you change this format, don't forget to also
312 change message_log_check_duplicate. */
313 sprintf (dupstr, " [%d times]", dup);
314 duplen = strlen (dupstr);
315 TEMP_SET_PT (Z-1);
316 if (oldpoint == Z)
317 oldpoint += duplen;
318 if (oldzv == Z)
319 oldzv += duplen;
320 insert_1 (dupstr, duplen, 1, 0);
321 }
322 }
323 }
324
325 if (NATNUMP (Vmessage_log_max))
326 {
327 int pos = scan_buffer ('\n', Z, 0,
328 -XFASTINT (Vmessage_log_max) - 1, 0, 0);
329 oldpoint -= min (pos, oldpoint) - BEG;
330 oldbegv -= min (pos, oldbegv) - BEG;
331 oldzv -= min (pos, oldzv) - BEG;
332 del_range_1 (BEG, pos, 0);
333 }
5992c4f7
KH
334 }
335 BEGV = oldbegv;
336 ZV = oldzv;
337 TEMP_SET_PT (oldpoint);
338 set_buffer_internal (oldbuf);
69f033ab 339 windows_or_buffers_changed = old_windows_or_buffers_changed;
3c6595e0 340 message_log_need_newline = !nlflag;
5992c4f7 341 }
f88eb0b6
KH
342}
343
ff6c30e5
KH
344/* We are at the end of the buffer after just having inserted a newline.
345 (Note: We depend on the fact we won't be crossing the gap.)
346 Check to see if the most recent message looks a lot like the previous one.
347 Return 0 if different, 1 if the new one should just replace it, or a
348 value N > 1 if we should also append " [N times]". */
f82aff7c 349
ff6c30e5
KH
350static int
351message_log_check_duplicate (prev_bol, this_bol)
352 int prev_bol, this_bol;
353{
354 int i;
355 int len = Z - 1 - this_bol;
356 int seen_dots = 0;
f82aff7c
RS
357 unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
358 unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
ff6c30e5
KH
359
360 for (i = 0; i < len; i++)
361 {
362 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
363 && p1[i] != '\n')
364 seen_dots = 1;
365 if (p1[i] != p2[i])
366 return seen_dots;
367 }
368 p1 += len;
369 if (*p1 == '\n')
370 return 2;
371 if (*p1++ == ' ' && *p1++ == '[')
372 {
373 int n = 0;
374 while (*p1 >= '0' && *p1 <= '9')
375 n = n * 10 + *p1++ - '0';
376 if (strncmp (p1, " times]\n", 8) == 0)
377 return n+1;
378 }
379 return 0;
380}
1adc55de 381\f
f88eb0b6 382/* Display an echo area message M with a specified length of LEN chars.
1adc55de 383 The string may include null characters. If M is 0, clear out any
f88eb0b6 384 existing message, and let the minibuffer text show through.
1adc55de
RS
385
386 The buffer M must continue to exist until after the echo area
387 gets cleared or some other message gets displayed there.
388
389 Do not pass text that is stored in a Lisp string.
390 Do not pass text in a buffer that was alloca'd. */
f88eb0b6
KH
391
392void
393message2 (m, len)
394 char *m;
395 int len;
396{
397 /* First flush out any partial line written with print. */
3c6595e0 398 message_log_maybe_newline ();
f88eb0b6
KH
399 if (m)
400 message_dolog (m, len, 1);
5992c4f7
KH
401 message2_nolog (m, len);
402}
403
404
1adc55de 405/* The non-logging counterpart of message2. */
5992c4f7
KH
406
407void
408message2_nolog (m, len)
409 char *m;
410 int len;
90adcf20
RS
411{
412 if (noninteractive)
413 {
414 if (noninteractive_need_newline)
415 putc ('\n', stderr);
416 noninteractive_need_newline = 0;
417 fwrite (m, len, 1, stderr);
418 if (cursor_in_echo_area == 0)
419 fprintf (stderr, "\n");
420 fflush (stderr);
421 }
422 /* A null message buffer means that the frame hasn't really been
423 initialized yet. Error messages get reported properly by
424 cmd_error, so this must be just an informative message; toss it. */
425 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
426 {
73af359d
RS
427 Lisp_Object mini_window;
428 FRAME_PTR f;
90adcf20 429
73af359d
RS
430 /* Get the frame containing the minibuffer
431 that the selected frame is using. */
432 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
433 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
434
73af359d 435 FRAME_SAMPLE_VISIBILITY (f);
90adcf20 436 if (FRAME_VISIBLE_P (selected_frame)
73af359d
RS
437 && ! FRAME_VISIBLE_P (f))
438 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
90adcf20
RS
439
440 if (m)
441 {
442 echo_area_glyphs = m;
443 echo_area_glyphs_length = len;
b6436d4e
RS
444
445 if (minibuffer_auto_raise)
446 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
90adcf20 447 }
ded34426
JB
448 else
449 echo_area_glyphs = previous_echo_glyphs = 0;
450
451 do_pending_window_change ();
452 echo_area_display ();
73af359d 453 update_frame (f, 1, 1);
ded34426 454 do_pending_window_change ();
853cf346 455 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
73af359d 456 (*frame_up_to_date_hook) (f);
ded34426
JB
457 }
458}
1adc55de
RS
459\f
460/* Display a null-terminated echo area message M. If M is 0, clear out any
461 existing message, and let the minibuffer text show through.
462
463 The buffer M must continue to exist until after the echo area
464 gets cleared or some other message gets displayed there.
465
466 Do not pass text that is stored in a Lisp string.
467 Do not pass text in a buffer that was alloca'd. */
ded34426 468
48ae5f0a
KH
469void
470message1 (m)
471 char *m;
472{
473 message2 (m, (m ? strlen (m) : 0));
474}
475
0b1005ef
KH
476void
477message1_nolog (m)
478 char *m;
479{
480 message2_nolog (m, (m ? strlen (m) : 0));
481}
482
76412d64
RS
483/* Truncate what will be displayed in the echo area
484 the next time we display it--but don't redisplay it now. */
485
486void
487truncate_echo_area (len)
488 int len;
489{
490 /* A null message buffer means that the frame hasn't really been
491 initialized yet. Error messages get reported properly by
492 cmd_error, so this must be just an informative message; toss it. */
493 if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
494 echo_area_glyphs_length = len;
495}
496
44fa5b1e 497/* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
9c74a0dd
JB
498 zero if being used by message. */
499int message_buf_print;
500
1adc55de 501/* Dump an informative message to the minibuf. If M is 0, clear out
81d478f3 502 any existing message, and let the minibuffer text show through. */
1adc55de 503
a2889657 504/* VARARGS 1 */
a2889657
JB
505void
506message (m, a1, a2, a3)
507 char *m;
5d5ed907 508 EMACS_INT a1, a2, a3;
a2889657
JB
509{
510 if (noninteractive)
511 {
81d478f3
JB
512 if (m)
513 {
514 if (noninteractive_need_newline)
515 putc ('\n', stderr);
516 noninteractive_need_newline = 0;
517 fprintf (stderr, m, a1, a2, a3);
c4f14ccb
RS
518 if (cursor_in_echo_area == 0)
519 fprintf (stderr, "\n");
81d478f3
JB
520 fflush (stderr);
521 }
a2889657 522 }
1f40cad2 523 else if (INTERACTIVE)
a2889657 524 {
1f40cad2
JB
525 /* The frame whose minibuffer we're going to display the message on.
526 It may be larger than the selected frame, so we need
527 to use its buffer, not the selected frame's buffer. */
73af359d
RS
528 Lisp_Object mini_window;
529 FRAME_PTR f;
530
531 /* Get the frame containing the minibuffer
532 that the selected frame is using. */
533 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
534 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
1f40cad2
JB
535
536 /* A null message buffer means that the frame hasn't really been
537 initialized yet. Error messages get reported properly by
538 cmd_error, so this must be just an informative message; toss it. */
73af359d 539 if (FRAME_MESSAGE_BUF (f))
81d478f3 540 {
1f40cad2
JB
541 if (m)
542 {
90adcf20 543 int len;
a2889657 544#ifdef NO_ARG_ARRAY
5d5ed907 545 EMACS_INT a[3];
90adcf20
RS
546 a[0] = a1;
547 a[1] = a2;
548 a[2] = a3;
a2889657 549
73af359d 550 len = doprnt (FRAME_MESSAGE_BUF (f),
0f26b958 551 (int) FRAME_WIDTH (f), m, (char *)0, 3, a);
a2889657 552#else
73af359d 553 len = doprnt (FRAME_MESSAGE_BUF (f),
0f26b958 554 (int) FRAME_WIDTH (f), m, (char *)0, 3, &a1);
1f40cad2 555#endif /* NO_ARG_ARRAY */
1f40cad2 556
73af359d 557 message2 (FRAME_MESSAGE_BUF (f), len);
1f40cad2
JB
558 }
559 else
560 message1 (0);
561
562 /* Print should start at the beginning of the message
563 buffer next time. */
564 message_buf_print = 0;
81d478f3 565 }
a2889657
JB
566 }
567}
568
1adc55de 569/* The non-logging version of message. */
6c4429a5
KH
570void
571message_nolog (m, a1, a2, a3)
572 char *m;
573 EMACS_INT a1, a2, a3;
574{
575 Lisp_Object old_log_max;
576 old_log_max = Vmessage_log_max;
577 Vmessage_log_max = Qnil;
578 message (m, a1, a2, a3);
579 Vmessage_log_max = old_log_max;
580}
581
131f2133
RS
582void
583update_echo_area ()
584{
585 message2 (echo_area_glyphs, echo_area_glyphs_length);
586}
1adc55de 587\f
a2889657
JB
588static void
589echo_area_display ()
590{
591 register int vpos;
44fa5b1e 592 FRAME_PTR f;
73af359d 593 Lisp_Object mini_window;
a2889657 594
73af359d
RS
595 /* Choose the minibuffer window for this display.
596 It is the minibuffer window used by the selected frame. */
597 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
598 /* This is the frame that window is in. */
599 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
a2889657 600
44fa5b1e 601 if (! FRAME_VISIBLE_P (f))
a2889657 602 return;
a2889657 603
44fa5b1e 604 if (frame_garbaged)
a2889657 605 {
02a9b6e4 606 redraw_garbaged_frames ();
44fa5b1e 607 frame_garbaged = 0;
a2889657
JB
608 }
609
610 if (echo_area_glyphs || minibuf_level == 0)
611 {
a2f016e3
RS
612 int i;
613
73af359d
RS
614 echo_area_window = mini_window;
615
616 vpos = XFASTINT (XWINDOW (mini_window)->top);
44fa5b1e 617 get_display_line (f, vpos, 0);
a2f016e3
RS
618
619 /* Make sure the columns that overlap a left-hand scroll bar
620 are always clear. */
621 for (i = 0; i < FRAME_LEFT_SCROLL_BAR_WIDTH (f); i++)
622 f->desired_glyphs->glyphs[vpos][i] = SPACEGLYPH;
623
73af359d 624 display_string (XWINDOW (mini_window), vpos,
a2889657 625 echo_area_glyphs ? echo_area_glyphs : "",
90adcf20 626 echo_area_glyphs ? echo_area_glyphs_length : -1,
73f194f1
RS
627 FRAME_LEFT_SCROLL_BAR_WIDTH (f),
628 0, 0, 0, FRAME_WIDTH (f));
a2889657 629
b6f0fe04 630#if 0 /* This just gets in the way. update_frame does the job. */
a2889657 631 /* If desired cursor location is on this line, put it at end of text */
b5bbc9a5
KH
632 if (cursor_in_echo_area)
633 FRAME_CURSOR_Y (f) = vpos;
44fa5b1e
JB
634 if (FRAME_CURSOR_Y (f) == vpos)
635 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
b6f0fe04 636#endif
daa37602
JB
637
638 /* Fill the rest of the minibuffer window with blank lines. */
639 {
640 int i;
641
b2a76982 642 for (i = vpos + 1;
73af359d 643 i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
daa37602 644 {
44fa5b1e 645 get_display_line (f, i, 0);
73af359d 646 display_string (XWINDOW (mini_window), vpos,
73f194f1
RS
647 "", 0,
648 FRAME_LEFT_SCROLL_BAR_WIDTH (f),
649 0, 0, 0, FRAME_WIDTH (f));
daa37602
JB
650 }
651 }
a2889657 652 }
73af359d 653 else if (!EQ (mini_window, selected_window))
a2889657
JB
654 windows_or_buffers_changed++;
655
73af359d 656 if (EQ (mini_window, selected_window))
a2889657
JB
657 this_line_bufpos = 0;
658
659 previous_echo_glyphs = echo_area_glyphs;
660}
1adc55de
RS
661\f
662/* Update frame titles. */
96a410bc 663
8f3343d0 664#ifdef HAVE_WINDOW_SYSTEM
d39b6696
KH
665static char frame_title_buf[512];
666static char *frame_title_ptr;
96a410bc 667
d39b6696
KH
668static int
669store_frame_title (str, mincol, maxcol)
670 char *str;
671 int mincol, maxcol;
672{
673 char *limit;
674 if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
675 maxcol = sizeof (frame_title_buf);
676 limit = &frame_title_buf[maxcol];
677 while (*str != '\0' && frame_title_ptr < limit)
678 *frame_title_ptr++ = *str++;
679 while (frame_title_ptr < &frame_title_buf[mincol])
680 *frame_title_ptr++ = ' ';
681 return frame_title_ptr - frame_title_buf;
682}
96a410bc 683
96a410bc
KH
684static void
685x_consider_frame_title (frame)
686 Lisp_Object frame;
687{
d39b6696
KH
688 Lisp_Object fmt;
689 struct buffer *obuf;
690 int len;
96a410bc
KH
691 FRAME_PTR f = XFRAME (frame);
692
8f3343d0 693 if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
d39b6696 694 return;
3450d04c
KH
695
696 /* Do we have more than one visible frame on this X display? */
697 {
698 Lisp_Object tail;
699
700 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
701 {
702 FRAME_PTR tf = XFRAME (XCONS (tail)->car);
703
c9492f08
KH
704 if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
705 && !FRAME_MINIBUF_ONLY_P (tf)
3450d04c
KH
706 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
707 break;
708 }
709
710 multiple_frames = CONSP (tail);
711 }
712
d39b6696
KH
713 obuf = current_buffer;
714 Fset_buffer (XWINDOW (f->selected_window)->buffer);
715 fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
716 frame_title_ptr = frame_title_buf;
717 len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
718 0, sizeof (frame_title_buf), fmt);
719 frame_title_ptr = 0;
720 set_buffer_internal (obuf);
721 /* Set the name only if it's changed. This avoids consing
722 in the common case where it hasn't. (If it turns out that we've
723 already wasted too much time by walking through the list with
724 display_mode_element, then we might need to optimize at a higher
725 level than this.) */
726 if (! STRINGP (f->name) || XSTRING (f->name)->size != len
727 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
728 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
96a410bc 729}
c7c9ca97
KH
730#else
731#define frame_title_ptr ((char *)0)
e39322d9 732#define store_frame_title(str, mincol, maxcol) 0
96a410bc 733#endif
a2889657 734\f
90adcf20 735/* Prepare for redisplay by updating menu-bar item lists when appropriate.
87382820 736 This can call eval. */
90adcf20
RS
737
738void
739prepare_menu_bars ()
740{
741 register struct window *w = XWINDOW (selected_window);
742 int all_windows;
08b610e4 743 struct gcpro gcpro1, gcpro2;
90adcf20 744
ecf7de9b 745 all_windows = (update_mode_lines || buffer_shared > 1
28995e67 746 || windows_or_buffers_changed);
90adcf20 747
feb0c42f
KH
748 /* Update all frame titles based on their buffer names, etc.
749 We do this before the menu bars so that the buffer-menu
750 will show the up-to-date frame titles.
751
752 This used to be done after the menu bars, for a reason that
753 was stated as follows but which I do not understand:
754 "We do this after the menu bars so that the frame will first
755 create its menu bar using the name `emacs' if no other name
756 has yet been specified."
757 I think that is no longer a concern. */
8f3343d0 758#ifdef HAVE_WINDOW_SYSTEM
d3f46cff 759 if (windows_or_buffers_changed || update_mode_lines)
feb0c42f
KH
760 {
761 Lisp_Object tail, frame;
762
763 FOR_EACH_FRAME (tail, frame)
764 if (FRAME_VISIBLE_P (XFRAME (frame))
765 || FRAME_ICONIFIED_P (XFRAME (frame)))
766 x_consider_frame_title (frame);
767 }
768#endif
769
90adcf20
RS
770 /* Update the menu bar item lists, if appropriate.
771 This has to be done before any actual redisplay
772 or generation of display lines. */
773 if (all_windows)
774 {
775 Lisp_Object tail, frame;
a2725ab2
RS
776 int count = specpdl_ptr - specpdl;
777
778 record_unwind_protect (Fstore_match_data, Fmatch_data ());
90adcf20
RS
779
780 FOR_EACH_FRAME (tail, frame)
08b610e4
RS
781 {
782 /* If a window on this frame changed size,
783 report that to the user and clear the size-change flag. */
784 if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
785 {
786 Lisp_Object functions;
14510fee
RS
787 /* Clear flag first in case we get error below. */
788 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
08b610e4
RS
789 functions = Vwindow_size_change_functions;
790 GCPRO2 (tail, functions);
791 while (CONSP (functions))
792 {
793 call1 (XCONS (functions)->car, frame);
794 functions = XCONS (functions)->cdr;
795 }
796 UNGCPRO;
08b610e4
RS
797 }
798 GCPRO1 (tail);
a2725ab2 799 update_menu_bar (XFRAME (frame), 0);
08b610e4
RS
800 UNGCPRO;
801 }
a2725ab2
RS
802
803 unbind_to (count, Qnil);
90adcf20 804 }
ecf7de9b 805 else
a2725ab2 806 update_menu_bar (selected_frame, 1);
cd6dfed6
RS
807
808 /* Motif needs this. See comment in xmenu.c.
809 Turn it off when pending_menu_activation is not defined. */
810#ifdef USE_X_TOOLKIT
811 pending_menu_activation = 0;
812#endif
90adcf20
RS
813}
814\f
44fa5b1e 815/* Do a frame update, taking possible shortcuts into account.
a2889657
JB
816 This is the main external entry point for redisplay.
817
818 If the last redisplay displayed an echo area message and that
819 message is no longer requested, we clear the echo area
820 or bring back the minibuffer if that is in use.
821
90adcf20
RS
822 Do not call eval from within this function.
823 Calls to eval after the call to echo_area_display would confuse
824 the display_line mechanism and would cause a crash.
825 Calls to eval before that point will work most of the time,
826 but can still lose, because this function
827 can be called from signal handlers; with alarms set up;
a2889657 828 or with synchronous processes running.
90adcf20 829
a2889657
JB
830 See Fcall_process; if you called it from here, it could be
831 entered recursively. */
832
0d231165
RS
833static int do_verify_charstarts;
834
463f6b91
RS
835/* Counter is used to clear the face cache
836 no more than once ever 1000 redisplays. */
837static int clear_face_cache_count;
838
20de20dc
RS
839/* Record the previous terminal frame we displayed. */
840static FRAME_PTR previous_terminal_frame;
841
a2889657
JB
842void
843redisplay ()
e9874cee
RS
844{
845 redisplay_internal (0);
846}
847
848/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay
849 is not in response to any user action; therefore, we should
94a66eea
RS
850 preserve the echo area. (Actually, our caller does that job.)
851 Perhaps in the future avoid recentering windows
e9874cee
RS
852 if it is not necessary; currently that causes some problems. */
853
854static void
855redisplay_internal (preserve_echo_area)
856 int preserve_echo_area;
a2889657
JB
857{
858 register struct window *w = XWINDOW (selected_window);
859 register int pause;
860 int must_finish = 0;
861 int all_windows;
862 register int tlbufpos, tlendpos;
863 struct position pos;
a2889657
JB
864
865 if (noninteractive)
866 return;
867
15f0cf78
RS
868#ifdef USE_X_TOOLKIT
869 if (popup_activated ())
870 return;
871#endif
872
fd8ff63d 873 if (! FRAME_WINDOW_P (selected_frame)
20de20dc
RS
874 && previous_terminal_frame != selected_frame)
875 {
876 /* Since frames on an ASCII terminal share the same display area,
877 displaying a different frame means redisplay the whole thing. */
878 windows_or_buffers_changed++;
879 SET_FRAME_GARBAGED (selected_frame);
880 XSETFRAME (Vterminal_frame, selected_frame);
881 }
882 previous_terminal_frame = selected_frame;
20de20dc 883
d724d989
JB
884 /* Set the visible flags for all frames.
885 Do this before checking for resized or garbaged frames; they want
886 to know if their frames are visible.
887 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
888 {
35f56f96 889 Lisp_Object tail, frame;
d724d989 890
35f56f96 891 FOR_EACH_FRAME (tail, frame)
f82aff7c
RS
892 {
893 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
894
895 /* Clear out all the display lines in which we will generate the
896 glyphs to display. */
897 init_desired_glyphs (XFRAME (frame));
898 }
d724d989
JB
899 }
900
44fa5b1e 901 /* Notice any pending interrupt request to change frame size. */
a2889657
JB
902 do_pending_window_change ();
903
44fa5b1e 904 if (frame_garbaged)
a2889657 905 {
02a9b6e4 906 redraw_garbaged_frames ();
44fa5b1e 907 frame_garbaged = 0;
a2889657
JB
908 }
909
f82aff7c
RS
910 prepare_menu_bars ();
911
28995e67 912 if (windows_or_buffers_changed)
a2889657
JB
913 update_mode_lines++;
914
538f13d4
RS
915 /* Detect case that we need to write or remove a star in the mode line. */
916 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
917 {
918 w->update_mode_line = Qt;
919 if (buffer_shared > 1)
920 update_mode_lines++;
921 }
922
28995e67
RS
923 /* If %c is in use, update it if needed. */
924 if (!NILP (w->column_number_displayed)
925 /* This alternative quickly identifies a common case
926 where no change is needed. */
927 && !(PT == XFASTINT (w->last_point)
8850a573
RS
928 && XFASTINT (w->last_modified) >= MODIFF
929 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
930 && XFASTINT (w->column_number_displayed) != current_column ())
931 w->update_mode_line = Qt;
932
44fa5b1e 933 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657
JB
934
935 all_windows = update_mode_lines || buffer_shared > 1;
a2889657
JB
936
937 /* If specs for an arrow have changed, do thorough redisplay
938 to ensure we remove any arrow that should no longer exist. */
ded34426
JB
939 if (! EQ (Voverlay_arrow_position, last_arrow_position)
940 || ! EQ (Voverlay_arrow_string, last_arrow_string))
28995e67 941 all_windows = 1;
a2889657 942
90adcf20
RS
943 /* Normally the message* functions will have already displayed and
944 updated the echo area, but the frame may have been trashed, or
945 the update may have been preempted, so display the echo area
946 again here. */
947 if (echo_area_glyphs || previous_echo_glyphs)
948 {
949 echo_area_display ();
950 must_finish = 1;
951 }
952
bd66d1ba
RS
953 /* If showing region, and mark has changed, must redisplay whole window. */
954 if (((!NILP (Vtransient_mark_mode)
955 && !NILP (XBUFFER (w->buffer)->mark_active))
956 != !NILP (w->region_showing))
82d04750
JB
957 || (!NILP (w->region_showing)
958 && !EQ (w->region_showing,
959 Fmarker_position (XBUFFER (w->buffer)->mark))))
bd66d1ba
RS
960 this_line_bufpos = -1;
961
a2889657
JB
962 tlbufpos = this_line_bufpos;
963 tlendpos = this_line_endpos;
265a9e55 964 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
73af359d 965 && !current_buffer->clip_changed
44fa5b1e 966 && FRAME_VISIBLE_P (XFRAME (w->frame))
a2889657
JB
967 /* Make sure recorded data applies to current buffer, etc */
968 && this_line_buffer == current_buffer
969 && current_buffer == XBUFFER (w->buffer)
265a9e55 970 && NILP (w->force_start)
a2889657 971 /* Point must be on the line that we have info recorded about */
ae3b1442
KH
972 && PT >= tlbufpos
973 && PT <= Z - tlendpos
a2889657
JB
974 /* All text outside that line, including its final newline,
975 must be unchanged */
8850a573
RS
976 && ((XFASTINT (w->last_modified) >= MODIFF
977 && (XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF))
a2889657
JB
978 || (beg_unchanged >= tlbufpos - 1
979 && GPT >= tlbufpos
05ba02eb
JB
980 /* If selective display, can't optimize
981 if the changes start at the beginning of the line. */
e24c997d 982 && ((INTEGERP (current_buffer->selective_display)
05ba02eb
JB
983 && XINT (current_buffer->selective_display) > 0
984 ? (beg_unchanged >= tlbufpos
985 && GPT > tlbufpos)
986 : 1))
a2889657
JB
987 && end_unchanged >= tlendpos
988 && Z - GPT >= tlendpos)))
989 {
990 if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n'
991 && (tlbufpos == ZV
992 || FETCH_CHAR (tlbufpos) == '\n'))
993 /* Former continuation line has disappeared by becoming empty */
994 goto cancel;
995 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 996 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
997 || MINI_WINDOW_P (w))
998 {
999 cursor_vpos = -1;
1000 overlay_arrow_seen = 0;
ca26e1c8 1001 zv_strings_seen = 0;
a2889657 1002 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
0f9c0ff0 1003 pos_tab_offset (w, tlbufpos), 0);
a2889657
JB
1004 /* If line contains point, is not continued,
1005 and ends at same distance from eob as before, we win */
1006 if (cursor_vpos >= 0 && this_line_bufpos
1007 && this_line_endpos == tlendpos)
1008 {
0d231165
RS
1009 /* If this is not the window's last line,
1010 we must adjust the charstarts of the lines below. */
1011 if (this_line_vpos + 1
1012 < XFASTINT (w->top) + window_internal_height (w))
85bcef6c 1013 {
73f194f1 1014 int left = WINDOW_LEFT_MARGIN (w);
85bcef6c
RS
1015 int *charstart_next_line
1016 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
85bcef6c
RS
1017 int adjust;
1018
1019 if (Z - tlendpos == ZV)
1020 /* This line ends at end of (accessible part of) buffer.
1021 There is no newline to count. */
1022 adjust = Z - tlendpos - charstart_next_line[left];
1023 else
1024 /* This line ends in a newline.
1025 Must take account of the newline and the rest of the
1026 text that follows. */
1027 adjust = Z - tlendpos + 1 - charstart_next_line[left];
1028
1029 adjust_window_charstarts (w, this_line_vpos, adjust);
1030 }
46db8486 1031
73f194f1 1032 if (!WINDOW_FULL_WIDTH_P (w))
a2889657
JB
1033 preserve_other_columns (w);
1034 goto update;
1035 }
1036 else
1037 goto cancel;
1038 }
b6f0fe04
RS
1039 else if (PT == XFASTINT (w->last_point)
1040 /* Make sure the cursor was last displayed
1041 in this window. Otherwise we have to reposition it. */
1042 && XINT (w->top) <= FRAME_CURSOR_Y (selected_frame)
1043 && (XINT (w->top) + XINT (w->height)
1044 > FRAME_CURSOR_Y (selected_frame)))
a2889657
JB
1045 {
1046 if (!must_finish)
1047 {
1048 do_pending_window_change ();
1049 return;
1050 }
1051 goto update;
1052 }
8b51f1e3
KH
1053 /* If highlighting the region, or if the cursor is in the echo area,
1054 then we can't just move the cursor. */
bd66d1ba
RS
1055 else if (! (!NILP (Vtransient_mark_mode)
1056 && !NILP (current_buffer->mark_active))
2bf32c5d 1057 && w == XWINDOW (current_buffer->last_selected_window)
8b51f1e3
KH
1058 && NILP (w->region_showing)
1059 && !cursor_in_echo_area)
a2889657
JB
1060 {
1061 pos = *compute_motion (tlbufpos, 0,
1062 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
ca26e1c8 1063 0,
68be917d 1064 PT, 2, - (1 << (BITS_PER_SHORT - 1)),
b1d1124b 1065 window_internal_width (w) - 1,
de3e8b15 1066 XINT (w->hscroll),
e37f06d7 1067 pos_tab_offset (w, tlbufpos), w);
a2889657
JB
1068 if (pos.vpos < 1)
1069 {
210e752f 1070 int width = window_internal_width (w) - 1;
44fa5b1e 1071 FRAME_CURSOR_X (selected_frame)
73f194f1 1072 = WINDOW_LEFT_MARGIN (w) + minmax (0, pos.hpos, width);
44fa5b1e 1073 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
a2889657
JB
1074 goto update;
1075 }
1076 else
1077 goto cancel;
1078 }
1079 cancel:
1080 /* Text changed drastically or point moved off of line */
44fa5b1e 1081 cancel_line (this_line_vpos, selected_frame);
a2889657
JB
1082 }
1083
1084 this_line_bufpos = 0;
1085 all_windows |= buffer_shared > 1;
1086
463f6b91
RS
1087 clear_face_cache_count++;
1088
a2889657
JB
1089 if (all_windows)
1090 {
35f56f96 1091 Lisp_Object tail, frame;
a2889657 1092
87485d6f 1093#ifdef HAVE_FACES
463f6b91
RS
1094 /* Clear the face cache, only when we do a full redisplay
1095 and not too often either. */
1096 if (clear_face_cache_count > 1000)
1097 {
1098 clear_face_cache ();
1099 clear_face_cache_count = 0;
1100 }
31b24551
JB
1101#endif
1102
a2889657 1103 /* Recompute # windows showing selected buffer.
8de2d90b 1104 This will be incremented each time such a window is displayed. */
a2889657
JB
1105 buffer_shared = 0;
1106
35f56f96 1107 FOR_EACH_FRAME (tail, frame)
30c566e4 1108 {
35f56f96 1109 FRAME_PTR f = XFRAME (frame);
fd8ff63d 1110 if (FRAME_WINDOW_P (f) || f == selected_frame)
9769686d 1111 {
35f56f96 1112
9769686d
RS
1113 /* Mark all the scroll bars to be removed; we'll redeem the ones
1114 we want when we redisplay their windows. */
1115 if (condemn_scroll_bars_hook)
1116 (*condemn_scroll_bars_hook) (f);
30c566e4 1117
9769686d 1118 if (FRAME_VISIBLE_P (f))
e9874cee 1119 redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
30c566e4 1120
9769686d
RS
1121 /* Any scroll bars which redisplay_windows should have nuked
1122 should now go away. */
1123 if (judge_scroll_bars_hook)
1124 (*judge_scroll_bars_hook) (f);
1125 }
30c566e4 1126 }
a2889657 1127 }
44fa5b1e 1128 else if (FRAME_VISIBLE_P (selected_frame))
a2889657 1129 {
e9874cee 1130 redisplay_window (selected_window, 1, preserve_echo_area);
73f194f1 1131 if (!WINDOW_FULL_WIDTH_P (w))
a2889657
JB
1132 preserve_other_columns (w);
1133 }
1134
1135update:
1136 /* Prevent various kinds of signals during display update.
1137 stdio is not robust about handling signals,
1138 which can cause an apparent I/O error. */
1139 if (interrupt_input)
1140 unrequest_sigio ();
1141 stop_polling ();
1142
a2889657
JB
1143 if (all_windows)
1144 {
1145 Lisp_Object tail;
1146
1147 pause = 0;
1148
44fa5b1e 1149 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
a2889657 1150 {
44fa5b1e 1151 FRAME_PTR f;
a2889657 1152
e24c997d 1153 if (!FRAMEP (XCONS (tail)->car))
a2889657
JB
1154 continue;
1155
44fa5b1e 1156 f = XFRAME (XCONS (tail)->car);
1af9f229 1157
fd8ff63d 1158 if ((FRAME_WINDOW_P (f) || f == selected_frame)
1af9f229 1159 && FRAME_VISIBLE_P (f))
a2889657 1160 {
44fa5b1e 1161 pause |= update_frame (f, 0, 0);
a2889657 1162 if (!pause)
efc63ef0
RS
1163 {
1164 mark_window_display_accurate (f->root_window, 1);
1165 if (frame_up_to_date_hook != 0)
1166 (*frame_up_to_date_hook) (f);
1167 }
a2889657
JB
1168 }
1169 }
1170 }
1171 else
6e8290aa 1172 {
44fa5b1e
JB
1173 if (FRAME_VISIBLE_P (selected_frame))
1174 pause = update_frame (selected_frame, 0, 0);
4d641a15
KH
1175 else
1176 pause = 0;
d724d989 1177
8de2d90b 1178 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
1179 function. If the echo area is on another frame, that may
1180 have put text on a frame other than the selected one, so the
1181 above call to update_frame would not have caught it. Catch
8de2d90b
JB
1182 it here. */
1183 {
84faf44c
RS
1184 Lisp_Object mini_window;
1185 FRAME_PTR mini_frame;
1186
1187 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
1188 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
8de2d90b 1189
fd8ff63d 1190 if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
44fa5b1e 1191 pause |= update_frame (mini_frame, 0, 0);
8de2d90b 1192 }
6e8290aa 1193 }
a2889657 1194
44fa5b1e 1195 /* If frame does not match, prevent doing single-line-update next time.
a2889657
JB
1196 Also, don't forget to check every line to update the arrow. */
1197 if (pause)
1198 {
1199 this_line_bufpos = 0;
265a9e55 1200 if (!NILP (last_arrow_position))
a2889657
JB
1201 {
1202 last_arrow_position = Qt;
1203 last_arrow_string = Qt;
1204 }
44fa5b1e 1205 /* If we pause after scrolling, some lines in current_frame
a2889657
JB
1206 may be null, so preserve_other_columns won't be able to
1207 preserve all the vertical-bar separators. So, avoid using it
1208 in that case. */
73f194f1 1209 if (!WINDOW_FULL_WIDTH_P (w))
a2889657
JB
1210 update_mode_lines = 1;
1211 }
1212
44fa5b1e 1213 /* Now text on frame agrees with windows, so
a2889657
JB
1214 put info into the windows for partial redisplay to follow */
1215
1216 if (!pause)
1217 {
1218 register struct buffer *b = XBUFFER (w->buffer);
1219
1220 blank_end_of_window = 0;
a2889657 1221 unchanged_modified = BUF_MODIFF (b);
8850a573 1222 overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b);
a2889657
JB
1223 beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
1224 end_unchanged = BUF_Z (b) - BUF_GPT (b);
1225
c2213350
KH
1226 XSETFASTINT (w->last_point, BUF_PT (b));
1227 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
1228 XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
a2889657
JB
1229
1230 if (all_windows)
11e82b76 1231 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
a2889657
JB
1232 else
1233 {
28995e67 1234 b->clip_changed = 0;
a2889657 1235 w->update_mode_line = Qnil;
c2213350 1236 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
8850a573 1237 XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
538f13d4
RS
1238 w->last_had_star
1239 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
1240 ? Qt : Qnil);
d2f84654 1241 w->window_end_valid = w->buffer;
a2889657
JB
1242 last_arrow_position = Voverlay_arrow_position;
1243 last_arrow_string = Voverlay_arrow_string;
0d231165
RS
1244 if (do_verify_charstarts)
1245 verify_charstarts (w);
efc63ef0
RS
1246 if (frame_up_to_date_hook != 0)
1247 (*frame_up_to_date_hook) (selected_frame);
a2889657
JB
1248 }
1249 update_mode_lines = 0;
1250 windows_or_buffers_changed = 0;
1251 }
1252
1253 /* Start SIGIO interrupts coming again.
1254 Having them off during the code above
1255 makes it less likely one will discard output,
1256 but not impossible, since there might be stuff
1257 in the system buffer here.
1258 But it is much hairier to try to do anything about that. */
1259
1260 if (interrupt_input)
1261 request_sigio ();
1262 start_polling ();
1263
44fa5b1e 1264 /* Change frame size now if a change is pending. */
a2889657 1265 do_pending_window_change ();
d8e242fd
RS
1266
1267 /* If we just did a pending size change, redisplay again
1268 for the new size. */
3c8c72e0 1269 if (windows_or_buffers_changed && !pause)
d8e242fd 1270 redisplay ();
a2889657
JB
1271}
1272
1273/* Redisplay, but leave alone any recent echo area message
1274 unless another message has been requested in its place.
1275
1276 This is useful in situations where you need to redisplay but no
1277 user action has occurred, making it inappropriate for the message
1278 area to be cleared. See tracking_off and
1279 wait_reading_process_input for examples of these situations. */
1280
1281redisplay_preserve_echo_area ()
1282{
1283 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
1284 {
1285 echo_area_glyphs = previous_echo_glyphs;
e9874cee 1286 redisplay_internal (1);
a2889657
JB
1287 echo_area_glyphs = 0;
1288 }
1289 else
e9874cee 1290 redisplay_internal (1);
a2889657
JB
1291}
1292
1293void
1294mark_window_display_accurate (window, flag)
1295 Lisp_Object window;
1296 int flag;
1297{
1298 register struct window *w;
1299
265a9e55 1300 for (;!NILP (window); window = w->next)
a2889657 1301 {
e24c997d 1302 if (!WINDOWP (window)) abort ();
a2889657
JB
1303 w = XWINDOW (window);
1304
265a9e55 1305 if (!NILP (w->buffer))
bd66d1ba 1306 {
c2213350
KH
1307 XSETFASTINT (w->last_modified,
1308 !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
8850a573
RS
1309 XSETFASTINT (w->last_overlay_modified,
1310 !flag ? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)));
538f13d4
RS
1311 w->last_had_star
1312 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
1313 ? Qt : Qnil);
bd66d1ba
RS
1314
1315 /* Record if we are showing a region, so can make sure to
1316 update it fully at next redisplay. */
1317 w->region_showing = (!NILP (Vtransient_mark_mode)
2bf32c5d 1318 && w == XWINDOW (current_buffer->last_selected_window)
bd66d1ba
RS
1319 && !NILP (XBUFFER (w->buffer)->mark_active)
1320 ? Fmarker_position (XBUFFER (w->buffer)->mark)
1321 : Qnil);
1322 }
1323
d2f84654 1324 w->window_end_valid = w->buffer;
a2889657 1325 w->update_mode_line = Qnil;
051e7076 1326 if (!NILP (w->buffer) && flag)
28995e67 1327 XBUFFER (w->buffer)->clip_changed = 0;
a2889657 1328
265a9e55 1329 if (!NILP (w->vchild))
a2889657 1330 mark_window_display_accurate (w->vchild, flag);
265a9e55 1331 if (!NILP (w->hchild))
a2889657
JB
1332 mark_window_display_accurate (w->hchild, flag);
1333 }
1334
1335 if (flag)
1336 {
1337 last_arrow_position = Voverlay_arrow_position;
1338 last_arrow_string = Voverlay_arrow_string;
1339 }
1340 else
1341 {
1342 /* t is unequal to any useful value of Voverlay_arrow_... */
1343 last_arrow_position = Qt;
1344 last_arrow_string = Qt;
1345 }
1346}
1347\f
ecf7de9b 1348/* Update the menu bar item list for frame F.
90adcf20 1349 This has to be done before we start to fill in any display lines,
a2725ab2
RS
1350 because it can call eval.
1351
1352 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
90adcf20
RS
1353
1354static void
a2725ab2 1355update_menu_bar (f, save_match_data)
ecf7de9b 1356 FRAME_PTR f;
a2725ab2 1357 int save_match_data;
90adcf20 1358{
90adcf20 1359 struct buffer *old = current_buffer;
ecf7de9b
RS
1360 Lisp_Object window;
1361 register struct window *w;
a2725ab2 1362
ecf7de9b
RS
1363 window = FRAME_SELECTED_WINDOW (f);
1364 w = XWINDOW (window);
90adcf20
RS
1365
1366 if (update_mode_lines)
1367 w->update_mode_line = Qt;
1368
d1e74921 1369 if (FRAME_WINDOW_P (f)
d3413a53 1370 ?
dc937613 1371#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
cf074754 1372 FRAME_EXTERNAL_MENU_BAR (f)
78614721 1373#else
cf074754 1374 FRAME_MENU_BAR_LINES (f) > 0
78614721 1375#endif
d3413a53 1376 : FRAME_MENU_BAR_LINES (f) > 0)
90adcf20
RS
1377 {
1378 /* If the user has switched buffers or windows, we need to
1379 recompute to reflect the new bindings. But we'll
1380 recompute when update_mode_lines is set too; that means
1381 that people can use force-mode-line-update to request
1382 that the menu bar be recomputed. The adverse effect on
1383 the rest of the redisplay algorithm is about the same as
1384 windows_or_buffers_changed anyway. */
1385 if (windows_or_buffers_changed
cf074754 1386 || !NILP (w->update_mode_line)
538f13d4
RS
1387 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
1388 < BUF_MODIFF (XBUFFER (w->buffer)))
1389 != !NILP (w->last_had_star))
94bb7f9b
KH
1390 || ((!NILP (Vtransient_mark_mode)
1391 && !NILP (XBUFFER (w->buffer)->mark_active))
1392 != !NILP (w->region_showing)))
90adcf20
RS
1393 {
1394 struct buffer *prev = current_buffer;
a2725ab2
RS
1395 int count = specpdl_ptr - specpdl;
1396
399164b4 1397 set_buffer_internal_1 (XBUFFER (w->buffer));
eac4251c 1398 if (save_match_data)
a2725ab2 1399 record_unwind_protect (Fstore_match_data, Fmatch_data ());
399164b4 1400 if (NILP (Voverriding_local_map_menu_flag))
d46fb96a
KH
1401 {
1402 specbind (Qoverriding_terminal_local_map, Qnil);
1403 specbind (Qoverriding_local_map, Qnil);
1404 }
a2725ab2 1405
34acc8e6
KH
1406 /* Run the Lucid hook. */
1407 call1 (Vrun_hooks, Qactivate_menubar_hook);
1408 /* If it has changed current-menubar from previous value,
1409 really recompute the menubar from the value. */
1410 if (! NILP (Vlucid_menu_bar_dirty_flag))
1411 call0 (Qrecompute_lucid_menubar);
e02500d4 1412 safe_run_hooks (Qmenu_bar_update_hook);
8351baf2 1413 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
538f13d4 1414 /* Redisplay the menu bar in case we changed it. */
8f3343d0 1415#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
d1e74921 1416 if (FRAME_WINDOW_P (f))
d3413a53 1417 set_frame_menubar (f, 0, 0);
538f13d4
RS
1418 else
1419 /* On a terminal screen, the menu bar is an ordinary screen
1420 line, and this makes it get updated. */
1421 w->update_mode_line = Qt;
1422#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
1423 /* In the non-toolkit version, the menu bar is an ordinary screen
1424 line, and this makes it get updated. */
1425 w->update_mode_line = Qt;
1426#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
a2725ab2
RS
1427
1428 unbind_to (count, Qnil);
399164b4 1429 set_buffer_internal_1 (prev);
90adcf20
RS
1430 }
1431 }
1432}
1433\f
a2889657
JB
1434int do_id = 1;
1435
90adcf20
RS
1436/* Redisplay WINDOW and its subwindows and siblings. */
1437
a2889657 1438static void
e9874cee 1439redisplay_windows (window, preserve_echo_area)
a2889657 1440 Lisp_Object window;
e9874cee 1441 int preserve_echo_area;
a2889657 1442{
265a9e55 1443 for (; !NILP (window); window = XWINDOW (window)->next)
e9874cee 1444 redisplay_window (window, 0, preserve_echo_area);
a2889657
JB
1445}
1446
90adcf20
RS
1447/* Redisplay window WINDOW and its subwindows. */
1448
a2889657 1449static void
e9874cee 1450redisplay_window (window, just_this_one, preserve_echo_area)
a2889657 1451 Lisp_Object window;
e9874cee 1452 int just_this_one, preserve_echo_area;
a2889657
JB
1453{
1454 register struct window *w = XWINDOW (window);
30c566e4 1455 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
a2889657 1456 int height;
ae3b1442 1457 register int lpoint = PT;
a2889657 1458 struct buffer *old = current_buffer;
b1d1124b 1459 register int width = window_internal_width (w) - 1;
a2889657
JB
1460 register int startp;
1461 register int hscroll = XINT (w->hscroll);
1462 struct position pos;
ae3b1442 1463 int opoint = PT;
a2889657 1464 int tem;
e481f960 1465 int update_mode_line;
f908610f 1466 struct Lisp_Char_Table *dp = window_display_table (w);
a2889657 1467
44fa5b1e 1468 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
a2889657
JB
1469
1470 /* If this is a combination window, do its children; that's all. */
1471
265a9e55 1472 if (!NILP (w->vchild))
a2889657 1473 {
f9c467a3 1474 redisplay_windows (w->vchild, preserve_echo_area);
a2889657
JB
1475 return;
1476 }
265a9e55 1477 if (!NILP (w->hchild))
a2889657 1478 {
f9c467a3 1479 redisplay_windows (w->hchild, preserve_echo_area);
a2889657
JB
1480 return;
1481 }
265a9e55 1482 if (NILP (w->buffer))
a2889657 1483 abort ();
8de2d90b
JB
1484
1485 height = window_internal_height (w);
4d641a15 1486 update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
73af359d
RS
1487 if (XBUFFER (w->buffer)->clip_changed)
1488 update_mode_line = 1;
8de2d90b
JB
1489
1490 if (MINI_WINDOW_P (w))
1491 {
73af359d
RS
1492 if (w == XWINDOW (echo_area_window) && echo_area_glyphs)
1493 /* We've already displayed the echo area glyphs in this window. */
1494 goto finish_scroll_bars;
1495 else if (w != XWINDOW (minibuf_window))
8de2d90b 1496 {
73af359d
RS
1497 /* This is a minibuffer, but it's not the currently active one,
1498 so clear it. */
1499 int vpos = XFASTINT (w->top);
8de2d90b
JB
1500 int i;
1501
1502 for (i = 0; i < height; i++)
1503 {
44fa5b1e 1504 get_display_line (f, vpos + i, 0);
73f194f1
RS
1505 display_string (w, vpos + i, "", 0,
1506 FRAME_LEFT_SCROLL_BAR_WIDTH (f),
1507 0, 1, 0, width);
8de2d90b
JB
1508 }
1509
88f22aff 1510 goto finish_scroll_bars;
8de2d90b
JB
1511 }
1512 }
a2889657 1513
a2889657
JB
1514 /* Otherwise set up data on this window; select its buffer and point value */
1515
e481f960 1516 if (update_mode_line)
f72df6ac 1517 set_buffer_internal_1 (XBUFFER (w->buffer));
e481f960
RS
1518 else
1519 set_buffer_temp (XBUFFER (w->buffer));
1520
ae3b1442 1521 opoint = PT;
a2889657 1522
28995e67
RS
1523 /* If %c is in mode line, update it if needed. */
1524 if (!NILP (w->column_number_displayed)
1525 /* This alternative quickly identifies a common case
1526 where no change is needed. */
1527 && !(PT == XFASTINT (w->last_point)
8850a573
RS
1528 && XFASTINT (w->last_modified) >= MODIFF
1529 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
1530 && XFASTINT (w->column_number_displayed) != current_column ())
1531 update_mode_line = 1;
1532
42640f83
RS
1533 /* Count number of windows showing the selected buffer.
1534 An indirect buffer counts as its base buffer. */
a2889657 1535
42640f83
RS
1536 if (!just_this_one)
1537 {
1538 struct buffer *current_base, *window_base;
1539 current_base = current_buffer;
1540 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
1541 if (current_base->base_buffer)
1542 current_base = current_base->base_buffer;
1543 if (window_base->base_buffer)
1544 window_base = window_base->base_buffer;
1545 if (current_base == window_base)
1546 buffer_shared++;
1547 }
a2889657
JB
1548
1549 /* POINT refers normally to the selected window.
1550 For any other window, set up appropriate value. */
1551
1552 if (!EQ (window, selected_window))
1553 {
f67a0f51
RS
1554 int new_pt = marker_position (w->pointm);
1555 if (new_pt < BEGV)
a2889657 1556 {
f67a0f51
RS
1557 new_pt = BEGV;
1558 Fset_marker (w->pointm, make_number (new_pt), Qnil);
a2889657 1559 }
f67a0f51 1560 else if (new_pt > (ZV - 1))
a2889657 1561 {
f67a0f51
RS
1562 new_pt = ZV;
1563 Fset_marker (w->pointm, make_number (new_pt), Qnil);
a2889657 1564 }
f67a0f51
RS
1565 /* We don't use SET_PT so that the point-motion hooks don't run. */
1566 BUF_PT (current_buffer) = new_pt;
a2889657
JB
1567 }
1568
f4faa47c
JB
1569 /* If any of the character widths specified in the display table
1570 have changed, invalidate the width run cache. It's true that this
1571 may be a bit late to catch such changes, but the rest of
1572 redisplay goes (non-fatally) haywire when the display table is
1573 changed, so why should we worry about doing any better? */
1574 if (current_buffer->width_run_cache)
1575 {
f908610f 1576 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
1577
1578 if (! disptab_matches_widthtab (disptab,
1579 XVECTOR (current_buffer->width_table)))
1580 {
1581 invalidate_region_cache (current_buffer,
1582 current_buffer->width_run_cache,
1583 BEG, Z);
1584 recompute_width_table (current_buffer, disptab);
1585 }
1586 }
1587
a2889657 1588 /* If window-start is screwed up, choose a new one. */
a2889657
JB
1589 if (XMARKER (w->start)->buffer != current_buffer)
1590 goto recenter;
1591
1592 startp = marker_position (w->start);
1593
cf0df6ab
RS
1594 /* If someone specified a new starting point but did not insist,
1595 check whether it can be used. */
1596 if (!NILP (w->optional_new_start))
1597 {
1598 w->optional_new_start = Qnil;
1599 /* Check whether this start pos is usable given where point is. */
1600
1601 pos = *compute_motion (startp, 0,
1602 (((EQ (window, minibuf_window)
1603 && startp == BEG)
1604 ? minibuf_prompt_width : 0)
1605 + (hscroll ? 1 - hscroll : 0)),
1606 0,
1607 PT, height, 0,
1608 width, hscroll, pos_tab_offset (w, startp), w);
1609 /* If PT does fit on the screen, we will use this start pos,
1610 so do so by setting force_start. */
1611 if (pos.bufpos == PT)
1612 w->force_start = Qt;
1613 }
1614
8de2d90b 1615 /* Handle case where place to start displaying has been specified,
aa6d10fa 1616 unless the specified location is outside the accessible range. */
265a9e55 1617 if (!NILP (w->force_start))
a2889657 1618 {
e63574d7 1619 w->force_start = Qnil;
aa6d10fa
RS
1620 /* Forget any recorded base line for line number display. */
1621 w->base_line_number = Qnil;
75c43375
RS
1622 /* Redisplay the mode line. Select the buffer properly for that.
1623 Also, run the hook window-scroll-functions
1624 because we have scrolled. */
e63574d7
RS
1625 /* Note, we do this after clearing force_start because
1626 if there's an error, it is better to forget about force_start
1627 than to get into an infinite loop calling the hook functions
1628 and having them get more errors. */
75c43375
RS
1629 if (!update_mode_line
1630 || ! NILP (Vwindow_scroll_functions))
e481f960 1631 {
75c43375
RS
1632 Lisp_Object temp[3];
1633
e481f960 1634 set_buffer_temp (old);
f72df6ac 1635 set_buffer_internal_1 (XBUFFER (w->buffer));
e481f960
RS
1636 update_mode_line = 1;
1637 w->update_mode_line = Qt;
75c43375 1638 if (! NILP (Vwindow_scroll_functions))
3dcd07e3
KH
1639 {
1640 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1641 make_number (startp));
1642 startp = marker_position (w->start);
1643 }
e481f960 1644 }
c2213350 1645 XSETFASTINT (w->last_modified, 0);
8850a573 1646 XSETFASTINT (w->last_overlay_modified, 0);
8de2d90b
JB
1647 if (startp < BEGV) startp = BEGV;
1648 if (startp > ZV) startp = ZV;
a2889657
JB
1649 try_window (window, startp);
1650 if (cursor_vpos < 0)
1651 {
1652 /* If point does not appear, move point so it does appear */
1653 pos = *compute_motion (startp, 0,
ca26e1c8
KH
1654 (((EQ (window, minibuf_window)
1655 && startp == BEG)
1656 ? minibuf_prompt_width : 0)
1657 + (hscroll ? 1 - hscroll : 0)),
1658 0,
1659 ZV, height / 2,
68be917d 1660 - (1 << (BITS_PER_SHORT - 1)),
ca26e1c8 1661 width, hscroll, pos_tab_offset (w, startp), w);
f67a0f51 1662 BUF_PT (current_buffer) = pos.bufpos;
90adcf20 1663 if (w != XWINDOW (selected_window))
ae3b1442 1664 Fset_marker (w->pointm, make_number (PT), Qnil);
a2889657
JB
1665 else
1666 {
9d6a6bb9 1667 if (current_buffer == old)
ae3b1442 1668 lpoint = PT;
73f194f1 1669 FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
210e752f 1670 + minmax (0, pos.hpos, width));
44fa5b1e 1671 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
a2889657 1672 }
df0b5ea1
RS
1673 /* If we are highlighting the region,
1674 then we just changed the region, so redisplay to show it. */
df0b5ea1
RS
1675 if (!NILP (Vtransient_mark_mode)
1676 && !NILP (current_buffer->mark_active))
6f27fa9b
RS
1677 {
1678 cancel_my_columns (XWINDOW (window));
1679 try_window (window, startp);
1680 }
a2889657
JB
1681 }
1682 goto done;
1683 }
1684
1685 /* Handle case where text has not changed, only point,
208aee63 1686 and it has not moved off the frame. */
a2889657
JB
1687
1688 /* This code is not used for minibuffer for the sake of
1689 the case of redisplaying to replace an echo area message;
1690 since in that case the minibuffer contents per se are usually unchanged.
1691 This code is of no real use in the minibuffer since
1692 the handling of this_line_bufpos, etc.,
1693 in redisplay handles the same cases. */
1694
1695 if (XFASTINT (w->last_modified) >= MODIFF
8850a573 1696 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF
86bee31c 1697 && PT >= startp && !current_buffer->clip_changed
73f194f1 1698 && (just_this_one || WINDOW_FULL_WIDTH_P (w))
b1aa6cb3
RS
1699 /* If force-mode-line-update was called, really redisplay;
1700 that's how redisplay is forced after e.g. changing
1701 buffer-invisibility-spec. */
632ab665 1702 && NILP (w->update_mode_line)
bd66d1ba
RS
1703 /* Can't use this case if highlighting a region. */
1704 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1705 && NILP (w->region_showing)
15495c73
KH
1706 /* If end pos is out of date, scroll bar and percentage will be wrong */
1707 && INTEGERP (w->window_end_vpos)
1708 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
a2889657
JB
1709 && !EQ (window, minibuf_window))
1710 {
9afd2168
RS
1711 int this_scroll_margin = scroll_margin;
1712
ca26e1c8 1713 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
632ab665 1714 PT, height, 0, width, hscroll,
e37f06d7 1715 pos_tab_offset (w, startp), w);
a2889657 1716
9afd2168
RS
1717 /* Don't use a scroll margin that is negative or too large. */
1718 if (this_scroll_margin < 0)
1719 this_scroll_margin = 0;
1720
1721 if (XINT (w->height) < 4 * scroll_margin)
1722 this_scroll_margin = XINT (w->height) / 4;
1723
1724 /* If point fits on the screen, and not within the scroll margin,
1725 we are ok. */
1726 if (pos.vpos < height - this_scroll_margin
1727 && (pos.vpos >= this_scroll_margin || startp == BEGV))
a2889657 1728 {
44fa5b1e
JB
1729 /* Ok, point is still on frame */
1730 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
a2889657
JB
1731 {
1732 /* These variables are supposed to be origin 1 */
73f194f1 1733 FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
210e752f 1734 + minmax (0, pos.hpos, width));
44fa5b1e 1735 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
a2889657
JB
1736 }
1737 /* This doesn't do the trick, because if a window to the right of
1738 this one must be redisplayed, this does nothing because there
44fa5b1e 1739 is nothing in DesiredFrame yet, and then the other window is
a2889657 1740 redisplayed, making likes that are empty in this window's columns.
73f194f1 1741 if (WINDOW_FULL_WIDTH_P (w))
a2889657
JB
1742 preserve_my_columns (w);
1743 */
1744 goto done;
1745 }
1746 /* Don't bother trying redisplay with same start;
1747 we already know it will lose */
1748 }
1749 /* If current starting point was originally the beginning of a line
1750 but no longer is, find a new starting point. */
265a9e55 1751 else if (!NILP (w->start_at_line_beg)
b16234d8 1752 && !(startp <= BEGV
a2889657
JB
1753 || FETCH_CHAR (startp - 1) == '\n'))
1754 {
1755 goto recenter;
1756 }
1757 else if (just_this_one && !MINI_WINDOW_P (w)
ae3b1442 1758 && PT >= startp
a2889657 1759 && XFASTINT (w->last_modified)
14709f21
JB
1760 /* or else vmotion on first line won't work. */
1761 && ! NILP (w->start_at_line_beg)
a2889657 1762 && ! EQ (w->window_end_valid, Qnil)
86bee31c 1763 && do_id && !current_buffer->clip_changed
a2889657 1764 && !blank_end_of_window
73f194f1 1765 && WINDOW_FULL_WIDTH_P (w)
bd66d1ba
RS
1766 /* Can't use this case if highlighting a region. */
1767 && !(!NILP (Vtransient_mark_mode)
1768 && !NILP (current_buffer->mark_active))
23c852cb
KH
1769 /* Don't use try_window_id if newline
1770 doesn't display as the end of a line. */
1771 && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
bd66d1ba 1772 && NILP (w->region_showing)
a2889657
JB
1773 && EQ (last_arrow_position, Voverlay_arrow_position)
1774 && EQ (last_arrow_string, Voverlay_arrow_string)
44fa5b1e 1775 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
a2889657
JB
1776 && tem != -2)
1777 {
1778 /* tem > 0 means success. tem == -1 means choose new start.
1779 tem == -2 means try again with same start,
1780 and nothing but whitespace follows the changed stuff.
1781 tem == 0 means try again with same start. */
1782 if (tem > 0)
1783 goto done;
1784 }
1785 else if (startp >= BEGV && startp <= ZV
e9874cee
RS
1786 && (startp < ZV
1787 /* Avoid starting at end of buffer. */
1788#if 0 /* This change causes trouble for M-! finger & RET.
1789 It will have to be considered later. */
1790 || ! EQ (window, selected_window)
1791 /* Don't do the recentering if redisplay
1792 is not for no user action. */
1793 || preserve_echo_area
1794#endif
1795 || startp == BEGV
8850a573
RS
1796 || (XFASTINT (w->last_modified) >= MODIFF
1797 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657
JB
1798 {
1799 /* Try to redisplay starting at same place as before */
44fa5b1e 1800 /* If point has not moved off frame, accept the results */
a2889657
JB
1801 try_window (window, startp);
1802 if (cursor_vpos >= 0)
aa6d10fa 1803 {
28995e67
RS
1804 if (!just_this_one || current_buffer->clip_changed
1805 || beg_unchanged < startp)
aa6d10fa
RS
1806 /* Forget any recorded base line for line number display. */
1807 w->base_line_number = Qnil;
1808 goto done;
1809 }
a2889657
JB
1810 else
1811 cancel_my_columns (w);
1812 }
1813
c2213350 1814 XSETFASTINT (w->last_modified, 0);
8850a573 1815 XSETFASTINT (w->last_overlay_modified, 0);
e481f960
RS
1816 /* Redisplay the mode line. Select the buffer properly for that. */
1817 if (!update_mode_line)
1818 {
1819 set_buffer_temp (old);
f72df6ac 1820 set_buffer_internal_1 (XBUFFER (w->buffer));
e481f960
RS
1821 update_mode_line = 1;
1822 w->update_mode_line = Qt;
1823 }
a2889657
JB
1824
1825 /* Try to scroll by specified few lines */
1826
0789adb2
RS
1827 if (scroll_conservatively && !current_buffer->clip_changed
1828 && startp >= BEGV && startp <= ZV)
1829 {
f9c8af06
RS
1830 int this_scroll_margin = scroll_margin;
1831
1832 /* Don't use a scroll margin that is negative or too large. */
1833 if (this_scroll_margin < 0)
1834 this_scroll_margin = 0;
1835
1836 if (XINT (w->height) < 4 * scroll_margin)
1837 this_scroll_margin = XINT (w->height) / 4;
1838
0789adb2
RS
1839 if (PT >= Z - XFASTINT (w->window_end_pos))
1840 {
1841 struct position pos;
1842 pos = *compute_motion (Z - XFASTINT (w->window_end_pos), 0, 0, 0,
1843 PT, XFASTINT (w->height), 0,
1844 XFASTINT (w->width), XFASTINT (w->hscroll),
1845 pos_tab_offset (w, startp), w);
1846 if (pos.vpos > scroll_conservatively)
1847 goto scroll_fail_1;
1848
f9c8af06 1849 pos = *vmotion (startp, pos.vpos + 1 + this_scroll_margin, w);
0789adb2
RS
1850
1851 if (! NILP (Vwindow_scroll_functions))
1852 {
1853 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
1854 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1855 make_number (pos.bufpos));
1856 pos.bufpos = marker_position (w->start);
1857 }
1858 try_window (window, pos.bufpos);
1859 if (cursor_vpos >= 0)
1860 {
1861 if (!just_this_one || current_buffer->clip_changed
1862 || beg_unchanged < startp)
1863 /* Forget any recorded base line for line number display. */
1864 w->base_line_number = Qnil;
1865 goto done;
1866 }
1867 else
1868 cancel_my_columns (w);
1869 }
1870 if (PT < startp)
1871 {
1872 struct position pos;
1873 pos = *compute_motion (PT, 0, 0, 0,
1874 startp, XFASTINT (w->height), 0,
1875 XFASTINT (w->width), XFASTINT (w->hscroll),
1876 pos_tab_offset (w, startp), w);
1877 if (pos.vpos >= scroll_conservatively)
1878 goto scroll_fail_1;
1879
f9c8af06 1880 pos = *vmotion (startp, - pos.vpos - this_scroll_margin, w);
0789adb2
RS
1881
1882 if (! NILP (Vwindow_scroll_functions))
1883 {
1884 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
1885 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1886 make_number (pos.bufpos));
1887 pos.bufpos = marker_position (w->start);
1888 }
1889 try_window (window, pos.bufpos);
1890 if (cursor_vpos >= 0)
1891 {
1892 if (!just_this_one || current_buffer->clip_changed
1893 || beg_unchanged < startp)
1894 /* Forget any recorded base line for line number display. */
1895 w->base_line_number = Qnil;
1896 goto done;
1897 }
1898 else
1899 cancel_my_columns (w);
1900 }
1901 scroll_fail_1: ;
1902 }
1903
2c081c2d
KH
1904 if (scroll_step && !current_buffer->clip_changed
1905 && startp >= BEGV && startp <= ZV)
a2889657 1906 {
ae3b1442 1907 if (PT > startp)
a2889657 1908 {
210e752f 1909 pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
a2889657
JB
1910 if (pos.vpos >= height)
1911 goto scroll_fail;
1912 }
1913
210e752f 1914 pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
a2889657 1915
ae3b1442 1916 if (PT >= pos.bufpos)
a2889657 1917 {
75c43375 1918 if (! NILP (Vwindow_scroll_functions))
3dcd07e3 1919 {
4a0f786c 1920 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
3dcd07e3
KH
1921 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1922 make_number (pos.bufpos));
1923 pos.bufpos = marker_position (w->start);
1924 }
a2889657
JB
1925 try_window (window, pos.bufpos);
1926 if (cursor_vpos >= 0)
aa6d10fa 1927 {
28995e67
RS
1928 if (!just_this_one || current_buffer->clip_changed
1929 || beg_unchanged < startp)
aa6d10fa
RS
1930 /* Forget any recorded base line for line number display. */
1931 w->base_line_number = Qnil;
1932 goto done;
1933 }
a2889657
JB
1934 else
1935 cancel_my_columns (w);
1936 }
1937 scroll_fail: ;
1938 }
1939
1940 /* Finally, just choose place to start which centers point */
1941
1942recenter:
aa6d10fa
RS
1943 /* Forget any previously recorded base line for line number display. */
1944 w->base_line_number = Qnil;
1945
210e752f 1946 pos = *vmotion (PT, - (height / 2), w);
e63574d7
RS
1947 /* Set startp here explicitly in case that helps avoid an infinite loop
1948 in case the window-scroll-functions functions get errors. */
208aee63 1949 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
75c43375 1950 if (! NILP (Vwindow_scroll_functions))
3dcd07e3
KH
1951 {
1952 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1953 make_number (pos.bufpos));
1954 pos.bufpos = marker_position (w->start);
1955 }
a2889657
JB
1956 try_window (window, pos.bufpos);
1957
1958 startp = marker_position (w->start);
ca26e1c8 1959 w->start_at_line_beg
b16234d8 1960 = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
a2889657
JB
1961
1962done:
e481f960 1963 if ((update_mode_line
aa6d10fa
RS
1964 /* If window not full width, must redo its mode line
1965 if the window to its side is being redone */
73f194f1 1966 || (!just_this_one && !WINDOW_FULL_WIDTH_P (w))
155ef550
KH
1967 || INTEGERP (w->base_line_pos)
1968 || (!NILP (w->column_number_displayed)
1969 && XFASTINT (w->column_number_displayed) != current_column ()))
a2889657
JB
1970 && height != XFASTINT (w->height))
1971 display_mode_line (w);
aa6d10fa
RS
1972 if (! line_number_displayed
1973 && ! BUFFERP (w->base_line_pos))
1974 {
1975 w->base_line_pos = Qnil;
1976 w->base_line_number = Qnil;
1977 }
a2889657 1978
7ce2c095 1979 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 1980 if (update_mode_line
d1e74921 1981 && (FRAME_WINDOW_P (f)
d3413a53 1982 ?
dc937613 1983#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
d3413a53 1984 FRAME_EXTERNAL_MENU_BAR (f)
76412d64 1985#else
d3413a53 1986 FRAME_MENU_BAR_LINES (f) > 0
76412d64 1987#endif
d3413a53 1988 : FRAME_MENU_BAR_LINES (f) > 0)
7ce2c095
RS
1989 && EQ (FRAME_SELECTED_WINDOW (f), window))
1990 display_menu_bar (w);
1991
88f22aff
JB
1992 finish_scroll_bars:
1993 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 1994 {
b1d1124b 1995 int start, end, whole;
30c566e4 1996
b1d1124b 1997 /* Calculate the start and end positions for the current window.
3505ea70
JB
1998 At some point, it would be nice to choose between scrollbars
1999 which reflect the whole buffer size, with special markers
2000 indicating narrowing, and scrollbars which reflect only the
2001 visible region.
2002
b1d1124b
JB
2003 Note that minibuffers sometimes aren't displaying any text. */
2004 if (! MINI_WINDOW_P (w)
2005 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
2006 {
8a9311d7 2007 whole = ZV - BEGV;
4d641a15 2008 start = marker_position (w->start) - BEGV;
b1d1124b
JB
2009 /* I don't think this is guaranteed to be right. For the
2010 moment, we'll pretend it is. */
85f26be9 2011 end = (Z - XINT (w->window_end_pos)) - BEGV;
3505ea70
JB
2012
2013 if (end < start) end = start;
8a9311d7 2014 if (whole < (end - start)) whole = end - start;
b1d1124b
JB
2015 }
2016 else
2017 start = end = whole = 0;
30c566e4 2018
88f22aff 2019 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 2020 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 2021
88f22aff 2022 /* Note that we actually used the scroll bar attached to this window,
30c566e4 2023 so it shouldn't be deleted at the end of redisplay. */
88f22aff 2024 (*redeem_scroll_bar_hook) (w);
30c566e4 2025 }
b1d1124b 2026
f67a0f51 2027 BUF_PT (current_buffer) = opoint;
e481f960 2028 if (update_mode_line)
f72df6ac 2029 set_buffer_internal_1 (old);
e481f960
RS
2030 else
2031 set_buffer_temp (old);
f67a0f51 2032 BUF_PT (current_buffer) = lpoint;
a2889657
JB
2033}
2034\f
2035/* Do full redisplay on one window, starting at position `pos'. */
2036
2037static void
2038try_window (window, pos)
2039 Lisp_Object window;
2040 register int pos;
2041{
2042 register struct window *w = XWINDOW (window);
2043 register int height = window_internal_height (w);
2044 register int vpos = XFASTINT (w->top);
2045 register int last_text_vpos = vpos;
2046 int tab_offset = pos_tab_offset (w, pos);
44fa5b1e 2047 FRAME_PTR f = XFRAME (w->frame);
b1d1124b 2048 int width = window_internal_width (w) - 1;
a2889657
JB
2049 struct position val;
2050
2051 Fset_marker (w->start, make_number (pos), Qnil);
2052 cursor_vpos = -1;
2053 overlay_arrow_seen = 0;
ca26e1c8 2054 zv_strings_seen = 0;
a2889657 2055 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
0f9c0ff0 2056 val.ovstring_chars_done = 0;
a2889657
JB
2057
2058 while (--height >= 0)
2059 {
0f9c0ff0
RS
2060 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset,
2061 val.ovstring_chars_done);
a2889657 2062 tab_offset += width;
2b050fec
RS
2063 /* For the first line displayed, display_text_line
2064 subtracts the prompt width from the tab offset.
2065 But it does not affect the value of our variable tab_offset.
2066 So we do the subtraction again,
2067 for the sake of continuation lines of that first line. */
2068 if (MINI_WINDOW_P (w) && vpos == XFASTINT (w->top))
2069 tab_offset -= minibuf_prompt_width;
2070
a2889657
JB
2071 if (val.vpos) tab_offset = 0;
2072 vpos++;
2073 if (pos != val.bufpos)
642eefc6
RS
2074 {
2075 int invis = 0;
e885523c 2076#ifdef USE_TEXT_PROPERTIES
642eefc6
RS
2077 Lisp_Object invis_prop;
2078 invis_prop = Fget_char_property (val.bufpos-1, Qinvisible, window);
2079 invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
e885523c 2080#endif
642eefc6
RS
2081
2082 last_text_vpos
2083 /* Next line, unless prev line ended in end of buffer with no cr */
2084 = vpos - (val.vpos
2085 && (FETCH_CHAR (val.bufpos - 1) != '\n' || invis));
2086 }
a2889657
JB
2087 pos = val.bufpos;
2088 }
2089
2090 /* If last line is continued in middle of character,
44fa5b1e 2091 include the split character in the text considered on the frame */
a2889657
JB
2092 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
2093 pos++;
2094
44fa5b1e 2095 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
2096 if (XFASTINT (w->window_end_pos) == 0
2097 && Z != pos)
2098 w->update_mode_line = Qt;
2099
44fa5b1e 2100 /* Say where last char on frame will be, once redisplay is finished. */
c2213350
KH
2101 XSETFASTINT (w->window_end_pos, Z - pos);
2102 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
a2889657
JB
2103 /* But that is not valid info until redisplay finishes. */
2104 w->window_end_valid = Qnil;
2105}
2106\f
2107/* Try to redisplay when buffer is modified locally,
2108 computing insert/delete line to preserve text outside
2109 the bounds of the changes.
2110 Return 1 if successful, 0 if if cannot tell what to do,
2111 or -1 to tell caller to find a new window start,
2112 or -2 to tell caller to do normal redisplay with same window start. */
2113
2114static int
2115try_window_id (window)
2116 Lisp_Object window;
2117{
2118 int pos;
2119 register struct window *w = XWINDOW (window);
2120 register int height = window_internal_height (w);
44fa5b1e 2121 FRAME_PTR f = XFRAME (w->frame);
a2889657
JB
2122 int top = XFASTINT (w->top);
2123 int start = marker_position (w->start);
b1d1124b 2124 int width = window_internal_width (w) - 1;
a2889657
JB
2125 int hscroll = XINT (w->hscroll);
2126 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
ca26e1c8 2127 int did_motion;
a2889657
JB
2128 register int vpos;
2129 register int i, tem;
2130 int last_text_vpos = 0;
2131 int stop_vpos;
e24c997d
KH
2132 int selective = (INTEGERP (current_buffer->selective_display)
2133 ? XINT (current_buffer->selective_display)
2134 : !NILP (current_buffer->selective_display) ? -1 : 0);
a2889657
JB
2135
2136 struct position val, bp, ep, xp, pp;
2137 int scroll_amount = 0;
2138 int delta;
d3413a53 2139 int tab_offset, epto, old_tick;
a2889657
JB
2140
2141 if (GPT - BEG < beg_unchanged)
2142 beg_unchanged = GPT - BEG;
2143 if (Z - GPT < end_unchanged)
2144 end_unchanged = Z - GPT;
2145
6a1dc7ac 2146 if (beg_unchanged + BEG < start)
a2889657
JB
2147 return 0; /* Give up if changes go above top of window */
2148
2149 /* Find position before which nothing is changed. */
ca26e1c8 2150 bp = *compute_motion (start, 0, lmargin, 0,
632ab665 2151 min (ZV, beg_unchanged + BEG), height, 0,
e37f06d7 2152 width, hscroll, pos_tab_offset (w, start), w);
a2889657 2153 if (bp.vpos >= height)
6e8290aa 2154 {
632ab665 2155 if (PT < bp.bufpos)
6e8290aa 2156 {
67481ae5
RS
2157 /* All changes are beyond the window end, and point is on the screen.
2158 We don't need to change the text at all.
6e8290aa
JB
2159 But we need to update window_end_pos to account for
2160 any change in buffer size. */
ca26e1c8 2161 bp = *compute_motion (start, 0, lmargin, 0,
67481ae5 2162 ZV, height, 0,
e37f06d7 2163 width, hscroll, pos_tab_offset (w, start), w);
c2213350
KH
2164 XSETFASTINT (w->window_end_vpos, height);
2165 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
4d641a15 2166 goto findpoint;
6e8290aa
JB
2167 }
2168 return 0;
2169 }
a2889657
JB
2170
2171 vpos = bp.vpos;
2172
44fa5b1e 2173 /* Find beginning of that frame line. Must display from there. */
210e752f 2174 bp = *vmotion (bp.bufpos, 0, w);
a2889657
JB
2175
2176 pos = bp.bufpos;
2177 val.hpos = lmargin;
2178 if (pos < start)
2179 return -1;
2180
ca26e1c8 2181 did_motion = 0;
a2889657 2182 /* If about to start displaying at the beginning of a continuation line,
44fa5b1e 2183 really start with previous frame line, in case it was not
a2889657 2184 continued when last redisplayed */
05ba02eb
JB
2185 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
2186 ||
2187 /* Likewise if we have to worry about selective display. */
9f412332 2188 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
a2889657 2189 {
210e752f 2190 bp = *vmotion (bp.bufpos, -1, w);
a2889657
JB
2191 --vpos;
2192 pos = bp.bufpos;
2193 }
2194
2195 if (bp.contin && bp.hpos != lmargin)
2196 {
2197 val.hpos = bp.prevhpos - width + lmargin;
ca26e1c8 2198 did_motion = 1;
a2889657
JB
2199 pos--;
2200 }
2201
2202 bp.vpos = vpos;
2203
2204 /* Find first visible newline after which no more is changed. */
2205 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
9f412332
KH
2206 if (selective > 0)
2207 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
a2889657
JB
2208 tem = find_next_newline (tem, 1);
2209
2210 /* Compute the cursor position after that newline. */
ca26e1c8 2211 ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
68be917d 2212 height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7 2213 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
a2889657 2214
44fa5b1e
JB
2215 /* If changes reach past the text available on the frame,
2216 just display rest of frame. */
a2889657
JB
2217 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
2218 stop_vpos = height;
2219 else
2220 stop_vpos = ep.vpos;
2221
2222 /* If no newline before ep, the line ep is on includes some changes
2223 that must be displayed. Make sure we don't stop before it. */
2224 /* Also, if changes reach all the way until ep.bufpos,
2225 it is possible that something was deleted after the
2226 newline before it, so the following line must be redrawn. */
2227 if (stop_vpos == ep.vpos
2228 && (ep.bufpos == BEGV
2229 || FETCH_CHAR (ep.bufpos - 1) != '\n'
2230 || ep.bufpos == Z - end_unchanged))
2231 stop_vpos = ep.vpos + 1;
2232
2233 cursor_vpos = -1;
2234 overlay_arrow_seen = 0;
ca26e1c8 2235 zv_strings_seen = 0;
a2889657
JB
2236
2237 /* If changes do not reach to bottom of window,
2238 figure out how much to scroll the rest of the window */
2239 if (stop_vpos < height)
2240 {
2241 /* Now determine how far up or down the rest of the window has moved */
2242 epto = pos_tab_offset (w, ep.bufpos);
ca26e1c8 2243 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
a2889657 2244 Z - XFASTINT (w->window_end_pos),
e37f06d7 2245 10000, 0, width, hscroll, epto, w);
a2889657
JB
2246 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
2247
44fa5b1e 2248 /* Is everything on frame below the changes whitespace?
a2889657
JB
2249 If so, no scrolling is really necessary. */
2250 for (i = ep.bufpos; i < xp.bufpos; i++)
2251 {
2252 tem = FETCH_CHAR (i);
2253 if (tem != ' ' && tem != '\n' && tem != '\t')
2254 break;
2255 }
2256 if (i == xp.bufpos)
2257 return -2;
2258
e8e536a9
KH
2259 XSETFASTINT (w->window_end_vpos,
2260 XFASTINT (w->window_end_vpos) + scroll_amount);
a2889657 2261
44fa5b1e 2262 /* Before doing any scrolling, verify that point will be on frame. */
ae3b1442 2263 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
a2889657 2264 {
ae3b1442 2265 if (PT <= xp.bufpos)
a2889657 2266 {
ca26e1c8 2267 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
68be917d 2268 PT, height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7 2269 width, hscroll, epto, w);
a2889657
JB
2270 }
2271 else
2272 {
ca26e1c8 2273 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
68be917d 2274 PT, height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7
KH
2275 width, hscroll,
2276 pos_tab_offset (w, xp.bufpos), w);
a2889657 2277 }
ae3b1442 2278 if (pp.bufpos < PT || pp.vpos == height)
a2889657
JB
2279 return 0;
2280 cursor_vpos = pp.vpos + top;
73f194f1 2281 cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, pp.hpos, width);
a2889657
JB
2282 }
2283
2284 if (stop_vpos - scroll_amount >= height
2285 || ep.bufpos == xp.bufpos)
2286 {
2287 if (scroll_amount < 0)
2288 stop_vpos -= scroll_amount;
2289 scroll_amount = 0;
2290 /* In this path, we have altered window_end_vpos
2291 and not left it negative.
2292 We must make sure that, in case display is preempted
44fa5b1e 2293 before the frame changes to reflect what we do here,
a2889657 2294 further updates will not come to try_window_id
44fa5b1e 2295 and assume the frame and window_end_vpos match. */
a2889657
JB
2296 blank_end_of_window = 1;
2297 }
2298 else if (!scroll_amount)
0d231165
RS
2299 {
2300 /* Even if we don't need to scroll, we must adjust the
2301 charstarts of subsequent lines (that we won't redisplay)
2302 according to the amount of text inserted or deleted. */
2303 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2304 int adjust = ep.bufpos - oldpos;
2305 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
2306 }
a2889657
JB
2307 else if (bp.bufpos == Z - end_unchanged)
2308 {
2309 /* If reprinting everything is nearly as fast as scrolling,
2310 don't bother scrolling. Can happen if lines are short. */
44fa5b1e 2311 if (scroll_cost (f, bp.vpos + top - scroll_amount,
a2889657
JB
2312 top + height - max (0, scroll_amount),
2313 scroll_amount)
2314 > xp.bufpos - bp.bufpos - 20)
2315 /* Return "try normal display with same window-start."
2316 Too bad we can't prevent further scroll-thinking. */
2317 return -2;
2318 /* If pure deletion, scroll up as many lines as possible.
2319 In common case of killing a line, this can save the
2320 following line from being overwritten by scrolling
2321 and therefore having to be redrawn. */
44fa5b1e 2322 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
d1cb44a4
RS
2323 top + height - max (0, scroll_amount),
2324 scroll_amount, bp.bufpos);
d2f84654
RS
2325 if (!tem)
2326 stop_vpos = height;
2327 else
2328 {
2329 /* scroll_frame_lines did not properly adjust subsequent
2330 lines' charstarts in the case where the text of the
2331 screen line at bp.vpos has changed.
2332 (This can happen in a deletion that ends in mid-line.)
8e6208c5
KH
2333 To adjust properly, we need to make things consistent
2334 at the position ep.
d2f84654
RS
2335 So do a second adjust to make that happen.
2336 Note that stop_vpos >= ep.vpos, so it is sufficient
2337 to update the charstarts for lines at ep.vpos and below. */
2338 int oldstart
2339 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2340 adjust_window_charstarts (w, ep.vpos + top - 1,
2341 ep.bufpos - oldstart);
2342 }
a2889657
JB
2343 }
2344 else if (scroll_amount)
2345 {
2346 /* If reprinting everything is nearly as fast as scrolling,
2347 don't bother scrolling. Can happen if lines are short. */
2348 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2349 overestimate of cost of reprinting, since xp.bufpos
2350 would end up below the bottom of the window. */
44fa5b1e 2351 if (scroll_cost (f, ep.vpos + top - scroll_amount,
a2889657
JB
2352 top + height - max (0, scroll_amount),
2353 scroll_amount)
2354 > xp.bufpos - ep.bufpos - 20)
2355 /* Return "try normal display with same window-start."
2356 Too bad we can't prevent further scroll-thinking. */
2357 return -2;
44fa5b1e 2358 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
a2889657 2359 top + height - max (0, scroll_amount),
d1cb44a4 2360 scroll_amount, ep.bufpos);
a2889657
JB
2361 if (!tem) stop_vpos = height;
2362 }
2363 }
2364
2365 /* In any case, do not display past bottom of window */
2366 if (stop_vpos >= height)
2367 {
2368 stop_vpos = height;
2369 scroll_amount = 0;
2370 }
2371
2372 /* Handle case where pos is before w->start --
2373 can happen if part of line had been clipped and is not clipped now */
2374 if (vpos == 0 && pos < marker_position (w->start))
2375 Fset_marker (w->start, make_number (pos), Qnil);
2376
2377 /* Redisplay the lines where the text was changed */
2378 last_text_vpos = vpos;
2379 tab_offset = pos_tab_offset (w, pos);
2380 /* If we are starting display in mid-character, correct tab_offset
2381 to account for passing the line that that character really starts in. */
2382 if (val.hpos < lmargin)
2383 tab_offset += width;
d3413a53 2384 old_tick = MODIFF;
a2889657
JB
2385 while (vpos < stop_vpos)
2386 {
0f9c0ff0
RS
2387 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset,
2388 val.ovstring_chars_done);
d3413a53
RS
2389 /* If display_text_line ran a hook and changed some text,
2390 redisplay all the way to bottom of buffer
2391 So that we show the changes. */
2392 if (old_tick != MODIFF)
2393 stop_vpos = height;
a2889657
JB
2394 tab_offset += width;
2395 if (val.vpos) tab_offset = 0;
2396 if (pos != val.bufpos)
2397 last_text_vpos
2398 /* Next line, unless prev line ended in end of buffer with no cr */
2399 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
2400 pos = val.bufpos;
2401 }
2402
2403 /* There are two cases:
2404 1) we have displayed down to the bottom of the window
2405 2) we have scrolled lines below stop_vpos by scroll_amount */
2406
2407 if (vpos == height)
2408 {
2409 /* If last line is continued in middle of character,
44fa5b1e 2410 include the split character in the text considered on the frame */
a2889657
JB
2411 if (val.hpos < lmargin)
2412 val.bufpos++;
c2213350
KH
2413 XSETFASTINT (w->window_end_vpos, last_text_vpos);
2414 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
a2889657
JB
2415 }
2416
2417 /* If scrolling made blank lines at window bottom,
2418 redisplay to fill those lines */
2419 if (scroll_amount < 0)
2420 {
2421 /* Don't consider these lines for general-purpose scrolling.
2422 That will save time in the scrolling computation. */
44fa5b1e 2423 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
a2889657
JB
2424 vpos = xp.vpos;
2425 pos = xp.bufpos;
2426 val.hpos = lmargin;
2427 if (pos == ZV)
2428 vpos = height + scroll_amount;
2429 else if (xp.contin && xp.hpos != lmargin)
2430 {
2431 val.hpos = xp.prevhpos - width + lmargin;
2432 pos--;
2433 }
2434
2435 blank_end_of_window = 1;
2436 tab_offset = pos_tab_offset (w, pos);
2437 /* If we are starting display in mid-character, correct tab_offset
2438 to account for passing the line that that character starts in. */
2439 if (val.hpos < lmargin)
2440 tab_offset += width;
2441
2442 while (vpos < height)
2443 {
0f9c0ff0
RS
2444 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset,
2445 val.ovstring_chars_done);
a2889657
JB
2446 tab_offset += width;
2447 if (val.vpos) tab_offset = 0;
2448 pos = val.bufpos;
2449 }
2450
2451 /* Here is a case where display_text_line sets cursor_vpos wrong.
2452 Make it be fixed up, below. */
2453 if (xp.bufpos == ZV
ae3b1442 2454 && xp.bufpos == PT)
a2889657
JB
2455 cursor_vpos = -1;
2456 }
2457
44fa5b1e 2458 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
2459 if (XFASTINT (w->window_end_pos) == 0
2460 && Z != val.bufpos)
2461 w->update_mode_line = Qt;
2462
2463 /* Attempt to adjust end-of-text positions to new bottom line */
2464 if (scroll_amount)
2465 {
2466 delta = height - xp.vpos;
2467 if (delta < 0
2468 || (delta > 0 && xp.bufpos <= ZV)
2469 || (delta == 0 && xp.hpos))
2470 {
210e752f 2471 val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
c2213350 2472 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
e8e536a9
KH
2473 XSETFASTINT (w->window_end_vpos,
2474 XFASTINT (w->window_end_vpos) + val.vpos);
a2889657
JB
2475 }
2476 }
2477
2478 w->window_end_valid = Qnil;
2479
2480 /* If point was not in a line that was displayed, find it */
2481 if (cursor_vpos < 0)
2482 {
4d641a15 2483 findpoint:
ca26e1c8 2484 val = *compute_motion (start, 0, lmargin, 0, PT, 10000, 10000,
e37f06d7 2485 width, hscroll, pos_tab_offset (w, start), w);
44fa5b1e 2486 /* Admit failure if point is off frame now */
a2889657
JB
2487 if (val.vpos >= height)
2488 {
2489 for (vpos = 0; vpos < height; vpos++)
44fa5b1e 2490 cancel_line (vpos + top, f);
a2889657
JB
2491 return 0;
2492 }
2493 cursor_vpos = val.vpos + top;
73f194f1 2494 cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width);
a2889657
JB
2495 }
2496
210e752f 2497 FRAME_CURSOR_X (f) = cursor_hpos;
44fa5b1e 2498 FRAME_CURSOR_Y (f) = cursor_vpos;
a2889657
JB
2499
2500 if (debug_end_pos)
2501 {
ca26e1c8 2502 val = *compute_motion (start, 0, lmargin, 0, ZV,
68be917d 2503 height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7 2504 width, hscroll, pos_tab_offset (w, start), w);
a2889657
JB
2505 if (val.vpos != XFASTINT (w->window_end_vpos))
2506 abort ();
2507 if (XFASTINT (w->window_end_pos)
2508 != Z - val.bufpos)
2509 abort ();
2510 }
2511
2512 return 1;
2513}
2514\f
278feba9 2515/* Copy LEN glyphs starting address FROM to the rope TO.
f7430cb6 2516 But don't actually copy the parts that would come in before S.
278feba9
RS
2517 Value is TO, advanced past the copied data.
2518 F is the frame we are displaying in. */
a2889657 2519
278feba9
RS
2520static GLYPH *
2521copy_part_of_rope (f, to, s, from, len, face)
2522 FRAME_PTR f;
2523 register GLYPH *to; /* Copy to here. */
a2889657 2524 register GLYPH *s; /* Starting point. */
278feba9
RS
2525 Lisp_Object *from; /* Data to copy. */
2526 int len;
1c2250c2 2527 int face; /* Face to apply to glyphs which don't specify one. */
a2889657 2528{
278feba9
RS
2529 int n = len;
2530 register Lisp_Object *fp = from;
2531 /* These cache the results of the last call to compute_glyph_face. */
2532 int last_code = -1;
2533 int last_merged = 0;
c581d710 2534
87485d6f 2535#ifdef HAVE_FACES
4cdc65eb
KH
2536 if (! FRAME_TERMCAP_P (f))
2537 while (n--)
2538 {
dedd1182 2539 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb
KH
2540 int facecode;
2541
2542 if (FAST_GLYPH_FACE (glyph) == 0)
2543 /* If GLYPH has no face code, use FACE. */
2544 facecode = face;
2545 else if (FAST_GLYPH_FACE (glyph) == last_code)
2546 /* If it's same as previous glyph, use same result. */
2547 facecode = last_merged;
2548 else
2549 {
2550 /* Merge this glyph's face and remember the result. */
2551 last_code = FAST_GLYPH_FACE (glyph);
2552 last_merged = facecode = compute_glyph_face (f, last_code, face);
2553 }
b2a76982 2554
4cdc65eb
KH
2555 if (to >= s)
2556 *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
2557 ++to;
2558 ++fp;
2559 }
2560 else
2561#endif
2562 while (n--)
2563 {
dedd1182 2564 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb
KH
2565 ++to;
2566 ++fp;
2567 }
278feba9 2568 return to;
c581d710
RS
2569}
2570
278feba9
RS
2571/* Correct a glyph by replacing its specified user-level face code
2572 with a displayable computed face code. */
c581d710 2573
278feba9 2574static GLYPH
659a218f 2575fix_glyph (f, glyph, cface)
278feba9
RS
2576 FRAME_PTR f;
2577 GLYPH glyph;
659a218f 2578 int cface;
c581d710 2579{
87485d6f 2580#ifdef HAVE_FACES
659a218f
KH
2581 if (! FRAME_TERMCAP_P (f))
2582 {
2583 if (FAST_GLYPH_FACE (glyph) != 0)
2584 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
2585 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
2586 }
4cdc65eb
KH
2587#endif
2588 return glyph;
a2889657
JB
2589}
2590\f
f4faa47c
JB
2591/* Display one line of window W, starting at position START in W's buffer.
2592
2593 Display starting at horizontal position HPOS, expressed relative to
2594 W's left edge. In situations where the text at START shouldn't
2595 start at the left margin (i.e. when the window is hscrolled, or
2596 we're continuing a line which left off in the midst of a
2597 multi-column character), HPOS should be negative; we throw away
2598 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2599 account.
a2889657
JB
2600
2601 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2602
0f9c0ff0
RS
2603 OVSTR_DONE is the number of chars of overlay before/after strings
2604 at this position which have already been processed.
2605
f4faa47c
JB
2606 Display on position VPOS on the frame. It is origin 0, relative to
2607 the top of the frame, not W.
a2889657
JB
2608
2609 Returns a STRUCT POSITION giving character to start next line with
2610 and where to display it, including a zero or negative hpos.
2611 The vpos field is not really a vpos; it is 1 unless the line is continued */
2612
2613struct position val_display_text_line;
2614
2615static struct position *
0f9c0ff0 2616display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
a2889657
JB
2617 struct window *w;
2618 int start;
2619 int vpos;
2620 int hpos;
2621 int taboffset;
0f9c0ff0 2622 int ovstr_done;
a2889657
JB
2623{
2624 register int pos = start;
2625 register int c;
2626 register GLYPH *p1;
a2889657
JB
2627 register int pause;
2628 register unsigned char *p;
2629 GLYPH *endp;
d2f84654 2630 register GLYPH *leftmargin;
ca26e1c8 2631 register GLYPH *p1prev;
efc63ef0 2632 register GLYPH *p1start;
ca26e1c8 2633 int prevpos;
efc63ef0 2634 int *charstart;
44fa5b1e 2635 FRAME_PTR f = XFRAME (w->frame);
a2889657 2636 int tab_width = XINT (current_buffer->tab_width);
265a9e55 2637 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
b1d1124b 2638 int width = window_internal_width (w) - 1;
a2889657
JB
2639 struct position val;
2640 int lastpos;
2641 int invis;
642eefc6
RS
2642 int last_invis_skip = 0;
2643 Lisp_Object last_invis_prop;
a2889657 2644 int hscroll = XINT (w->hscroll);
d2f84654
RS
2645 int truncate = (hscroll
2646 || (truncate_partial_width_windows
73f194f1 2647 && !WINDOW_FULL_WIDTH_P (w))
d2f84654 2648 || !NILP (current_buffer->truncate_lines));
bd66d1ba
RS
2649
2650 /* 1 if we should highlight the region. */
2651 int highlight_region
2bf32c5d
RS
2652 = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)
2653 && XWINDOW (current_buffer->last_selected_window) == w);
bd66d1ba
RS
2654 int region_beg, region_end;
2655
e24c997d
KH
2656 int selective = (INTEGERP (current_buffer->selective_display)
2657 ? XINT (current_buffer->selective_display)
2658 : !NILP (current_buffer->selective_display) ? -1 : 0);
44fa5b1e 2659 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
f908610f 2660 register struct Lisp_Char_Table *dp = window_display_table (w);
68a37fa8
RS
2661
2662 Lisp_Object default_invis_vector[3];
642eefc6
RS
2663 /* Number of characters of ellipsis to display after an invisible line
2664 if it calls for an ellipsis.
2665 Note that this value can be nonzero regardless of whether
2666 selective display is enabled--you must check that separately. */
a2889657 2667 int selective_rlen
642eefc6 2668 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
68a37fa8 2669 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
642eefc6 2670 : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
68a37fa8
RS
2671 /* This is the sequence of Lisp objects to display
2672 when there are invisible lines. */
2673 Lisp_Object *invis_vector_contents
e24c997d 2674 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
68a37fa8
RS
2675 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2676 : default_invis_vector);
2677
e24c997d 2678 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
278feba9 2679 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
e24c997d 2680 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
278feba9 2681 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
a2889657 2682
31b24551
JB
2683 /* The next buffer location at which the face should change, due
2684 to overlays or text property changes. */
2685 int next_face_change;
2686
ca26e1c8
KH
2687 /* The next location where the `invisible' property changes, or an
2688 overlay starts or ends. */
2689 int next_boundary;
2690
31b24551 2691 /* The face we're currently using. */
1c2250c2 2692 int current_face = 0;
efc63ef0 2693 int i;
31b24551 2694
c2213350 2695 XSETFASTINT (default_invis_vector[2], '.');
68a37fa8
RS
2696 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2697
73f194f1
RS
2698 hpos += WINDOW_LEFT_MARGIN (w);
2699 get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
54ff581a 2700 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657 2701
bd66d1ba 2702 /* Show where to highlight the region. */
1613b757 2703 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
fba9ce76
RS
2704 /* Maybe highlight only in selected window. */
2705 && (highlight_nonselected_windows
6f139a45 2706 || w == XWINDOW (selected_window)))
bd66d1ba
RS
2707 {
2708 region_beg = marker_position (current_buffer->mark);
2709 if (PT < region_beg)
2710 {
2711 region_end = region_beg;
2712 region_beg = PT;
2713 }
2714 else
2715 region_end = PT;
2716 w->region_showing = Qt;
2717 }
2718 else
2719 region_beg = region_end = -1;
2720
f4faa47c 2721 if (MINI_WINDOW_P (w)
ca26e1c8 2722 && start == BEG
a2889657
JB
2723 && vpos == XFASTINT (w->top))
2724 {
8c5b6a0a 2725 if (! NILP (minibuf_prompt))
f7b4b63a
KH
2726 {
2727 minibuf_prompt_width
8c5b6a0a
KH
2728 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2729 XSTRING (minibuf_prompt)->size, hpos,
ce006f69
RS
2730 /* Display a space if we truncate. */
2731 ' ',
2732 1, -1,
2733 /* Truncate the prompt a little before the
2734 margin, so user input can at least start
2735 on the first line. */
2736 w->width > 10 ? w->width - 4 : -1)
f7b4b63a
KH
2737 - hpos);
2738 hpos += minibuf_prompt_width;
2b050fec 2739 taboffset -= minibuf_prompt_width;
f7b4b63a
KH
2740 }
2741 else
2742 minibuf_prompt_width = 0;
a2889657
JB
2743 }
2744
f4faa47c
JB
2745 /* If we're hscrolled at all, use compute_motion to skip over any
2746 text off the left edge of the window. compute_motion may know
2747 tricks to do this faster than we can. */
2748 if (hpos < 0)
2749 {
2750 struct position *left_edge
ca26e1c8
KH
2751 = compute_motion (pos, vpos, hpos, 0,
2752 ZV, vpos, 0,
f4faa47c
JB
2753 width, hscroll, taboffset, w);
2754
2755 /* Retrieve the buffer position and column provided by
2756 compute_motion. We can't assume that the column will be
2757 zero, because you may have multi-column characters crossing
2758 the left margin.
2759
2760 compute_motion may have moved us past the screen position we
2761 requested, if we hit a multi-column character, or the end of
2762 the line. If so, back up. */
2763 if (left_edge->vpos > vpos
2764 || left_edge->hpos > 0)
2765 {
2766 pos = left_edge->bufpos - 1;
2767 hpos = left_edge->prevhpos;
2768 }
2769 else
2770 {
2771 pos = left_edge->bufpos;
2772 hpos = left_edge->hpos;
2773 }
2774 }
2775
2776 desired_glyphs->bufp[vpos] = start;
a2889657 2777 p1 = desired_glyphs->glyphs[vpos] + hpos;
efc63ef0
RS
2778 p1start = p1;
2779 charstart = desired_glyphs->charstarts[vpos] + hpos;
2780 /* In case we don't ever write anything into it... */
73f194f1
RS
2781 desired_glyphs->charstarts[vpos][WINDOW_LEFT_MARGIN (w)] = -1;
2782 leftmargin = desired_glyphs->glyphs[vpos] + WINDOW_LEFT_MARGIN (w);
d2f84654 2783 endp = leftmargin + width;
a2889657 2784
1c2250c2
JB
2785 /* Arrange the overlays nicely for our purposes. Usually, we call
2786 display_text_line on only one line at a time, in which case this
2787 can't really hurt too much, or we call it on lines which appear
2788 one after another in the buffer, in which case all calls to
2789 recenter_overlay_lists but the first will be pretty cheap. */
2790 recenter_overlay_lists (current_buffer, pos);
2791
a2889657
JB
2792 /* Loop generating characters.
2793 Stop at end of buffer, before newline,
31b24551
JB
2794 if reach or pass continuation column,
2795 or at face change. */
a2889657 2796 pause = pos;
31b24551 2797 next_face_change = pos;
ca26e1c8
KH
2798 next_boundary = pos;
2799 p1prev = p1;
2800 prevpos = pos;
85bcef6c 2801 while (1)
a2889657 2802 {
31b24551 2803 if (pos >= pause)
a2889657 2804 {
67481ae5
RS
2805 int e_t_h;
2806
ca26e1c8 2807 while (pos == next_boundary)
a2889657 2808 {
ca26e1c8
KH
2809 Lisp_Object position, limit, prop, ww;
2810
2811 /* Display the overlay strings here, unless we're at ZV
2812 and have already displayed the appropriate strings
2813 on an earlier line. */
2814 if (pos < ZV || !zv_strings_seen++)
2815 {
2816 int ovlen;
b4222ffa 2817 unsigned char *ovstr;
ca26e1c8 2818 ovlen = overlay_strings (pos, w, &ovstr);
0f9c0ff0
RS
2819
2820 if (ovlen > 0)
ca26e1c8 2821 {
0f9c0ff0
RS
2822 /* Skip the ones we did in a previous line. */
2823 ovstr += ovstr_done;
2824 ovlen -= ovstr_done;
2825
2826 /* Start outputting. */
2827 for (; ovlen; ovlen--, ovstr++)
2828 {
2829 if (p1 >= leftmargin && p1 < endp)
2830 *p1 = MAKE_GLYPH (f, *ovstr, current_face);
2831 p1++;
2832 ovstr_done++;
2833 }
2834 /* If we did all the overlay strings
2835 and we have room for text, clear ovstr_done
2836 just for neatness' sake. */
2837 if (ovlen == 0 && p1 < endp)
2838 ovstr_done = 0;
ca26e1c8
KH
2839 }
2840 }
2841
2842 /* Did we reach point? Record the cursor location. */
2843 if (pos == PT && cursor_vpos < 0)
2844 {
2845 cursor_vpos = vpos;
2846 cursor_hpos = p1 - leftmargin;
2847 }
2848
2849 if (pos >= ZV)
2850 break;
a2889657 2851
c2213350 2852 XSETFASTINT (position, pos);
ca26e1c8
KH
2853 limit = Fnext_overlay_change (position);
2854#ifdef USE_TEXT_PROPERTIES
dfabd9a0
RS
2855 /* This is just an estimate to give reasonable
2856 performance; nothing should go wrong if it is too small. */
fe3d6921 2857 if (XFASTINT (limit) > pos + 50)
c2213350 2858 XSETFASTINT (limit, pos + 50);
ca26e1c8
KH
2859 limit = Fnext_single_property_change (position, Qinvisible,
2860 Fcurrent_buffer (), limit);
2861#endif
2862 next_boundary = XFASTINT (limit);
2863 /* if the `invisible' property is set, we can skip to
2864 the next property change. */
2865 XSETWINDOW (ww, w);
2866 prop = Fget_char_property (position, Qinvisible, ww);
642eefc6 2867 if (TEXT_PROP_MEANS_INVISIBLE (prop))
dfabd9a0 2868 {
ca26e1c8 2869 if (pos < PT && next_boundary >= PT)
dfabd9a0
RS
2870 {
2871 cursor_vpos = vpos;
d2f84654 2872 cursor_hpos = p1 - leftmargin;
dfabd9a0 2873 }
ca26e1c8 2874 pos = next_boundary;
642eefc6
RS
2875 last_invis_skip = pos;
2876 last_invis_prop = prop;
dfabd9a0 2877 }
b0a0fbda 2878 }
ca26e1c8
KH
2879
2880 /* Did we reach point? Record the cursor location. */
2881 if (pos == PT && cursor_vpos < 0)
2882 {
2883 cursor_vpos = vpos;
2884 cursor_hpos = p1 - leftmargin;
2885 }
2886
2887 /* Did we hit the end of the visible region of the buffer?
2888 Stop here. */
2889 if (pos >= ZV)
eff87c2c
RS
2890 {
2891 /* Update charstarts for the end of this line. */
2892 /* Do nothing if off the left edge or at the right edge. */
2893 if (p1 >= leftmargin && p1 + 1 != endp)
2894 {
2895 int *p2x = &charstart[(p1 < leftmargin
2896 ? leftmargin : p1)
2897 - p1start];
2898 *p2x++ = pos;
2899 }
2900 break;
2901 }
b0a0fbda 2902
67481ae5
RS
2903 /* Figure out where (if at all) the
2904 redisplay_end_trigger-hook should run. */
f6fd109b
RS
2905 if (MARKERP (w->redisplay_end_trigger)
2906 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
d3413a53
RS
2907 e_t_h = marker_position (w->redisplay_end_trigger);
2908 else if (INTEGERP (w->redisplay_end_trigger))
2909 e_t_h = XINT (w->redisplay_end_trigger);
67481ae5
RS
2910 else
2911 e_t_h = ZV;
2912
2913 /* If we've gone past the place to run a hook,
2914 run the hook. */
2915 if (pos >= e_t_h && e_t_h != ZV)
2916 {
e0bfbde6
RS
2917 Lisp_Object args[3];
2918
2919 args[0] = Qredisplay_end_trigger_functions;
2920 XSETWINDOW (args[1], w);
2921 XSETINT (args[2], e_t_h);
e0bfbde6 2922
9c49d3d7
KH
2923 /* Since we are *trying* to run these functions,
2924 don't try to run them again, even if they get an error. */
d3413a53 2925 w->redisplay_end_trigger = Qnil;
9c49d3d7
KH
2926 Frun_hook_with_args (3, args);
2927
67481ae5 2928 e_t_h = ZV;
f6fd109b
RS
2929 /* Notice if it changed the face of this character. */
2930 next_face_change = pos;
67481ae5
RS
2931 }
2932
f6fd109b
RS
2933#ifdef HAVE_FACES
2934 /* Did we hit a face change? Figure out what face we should
2935 use now. We also hit this the first time through the
2936 loop, to see what face we should start with. */
ab6ce60e
RS
2937 if (pos >= next_face_change
2938 && (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f)))
f6fd109b
RS
2939 current_face = compute_char_face (f, w, pos,
2940 region_beg, region_end,
2941 &next_face_change, pos + 50, 0);
2942#endif
2943
67481ae5
RS
2944 /* Compute the next place we need to stop
2945 and do something special; set PAUSE. */
2946
ca26e1c8 2947 pause = ZV;
1c2250c2 2948
ca26e1c8
KH
2949 if (pos < next_boundary && next_boundary < pause)
2950 pause = next_boundary;
1c2250c2
JB
2951 if (pos < next_face_change && next_face_change < pause)
2952 pause = next_face_change;
2953
67481ae5
RS
2954 if (e_t_h < pause)
2955 pause = e_t_h;
2956
31b24551
JB
2957 /* Wouldn't you hate to read the next line to someone over
2958 the phone? */
ae3b1442
KH
2959 if (pos < PT && PT < pause)
2960 pause = PT;
a2889657
JB
2961 if (pos < GPT && GPT < pause)
2962 pause = GPT;
2963
2964 p = &FETCH_CHAR (pos);
2965 }
ca26e1c8 2966
ca26e1c8
KH
2967 if (p1 >= endp)
2968 break;
2969
2970 p1prev = p1;
2971
a2889657 2972 c = *p++;
376b0e59
RS
2973 /* Let a display table override all standard display methods. */
2974 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
2975 {
2976 p1 = copy_part_of_rope (f, p1, leftmargin,
2977 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
2978 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
2979 current_face);
2980 }
2981 else if (c >= 040 && c < 0177)
a2889657 2982 {
d2f84654 2983 if (p1 >= leftmargin)
4cdc65eb 2984 *p1 = MAKE_GLYPH (f, c, current_face);
a2889657
JB
2985 p1++;
2986 }
2987 else if (c == '\n')
2988 {
2989 invis = 0;
642eefc6
RS
2990 if (last_invis_skip == pos
2991 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
2992 invis = 1;
ca26e1c8 2993 while (pos + 1 < ZV
a2889657 2994 && selective > 0
9f412332 2995 && indented_beyond_p (pos + 1, selective))
a2889657
JB
2996 {
2997 invis = 1;
2998 pos = find_next_newline (pos + 1, 1);
2999 if (FETCH_CHAR (pos - 1) == '\n')
3000 pos--;
3001 }
d2f84654 3002 if (invis && selective_rlen > 0 && p1 >= leftmargin)
a2889657
JB
3003 {
3004 p1 += selective_rlen;
d2f84654 3005 if (p1 - leftmargin > width)
a2889657 3006 p1 = endp;
278feba9 3007 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c2250c2 3008 (p1 - p1prev), current_face);
a2889657 3009 }
87485d6f 3010#ifdef HAVE_FACES
3c5c35c5
JB
3011 /* Draw the face of the newline character as extending all the
3012 way to the end of the frame line. */
3013 if (current_face)
1105ff20
KH
3014 {
3015 if (p1 < leftmargin)
3016 p1 = leftmargin;
3017 while (p1 < endp)
3018 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
3019 }
3c5c35c5 3020#endif
545e04f6
KH
3021
3022 /* Update charstarts for the newline that ended this line. */
3023 /* Do nothing here for a char that's entirely off the left edge
3024 or if it starts at the right edge. */
3025 if (p1 >= leftmargin && p1prev != endp)
3026 {
3027 /* Store the newline's position into charstarts
3028 for the column where the newline starts.
3029 Store -1 for the rest of the glyphs it occupies. */
3030 int *p2x = &charstart[(p1prev < leftmargin
3031 ? leftmargin : p1prev)
3032 - p1start];
3033 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3034
3035 *p2x++ = pos;
3036 while (p2x < p2)
3037 *p2x++ = -1;
3038 }
3039
68a37fa8 3040 break;
a2889657
JB
3041 }
3042 else if (c == '\t')
3043 {
3044 do
3045 {
d2f84654 3046 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 3047 *p1 = MAKE_GLYPH (f, ' ', current_face);
a2889657
JB
3048 p1++;
3049 }
d2f84654 3050 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
a2889657
JB
3051 % tab_width);
3052 }
6e8290aa 3053 else if (c == Ctl ('M') && selective == -1)
a2889657
JB
3054 {
3055 pos = find_next_newline (pos, 1);
3056 if (FETCH_CHAR (pos - 1) == '\n')
3057 pos--;
3058 if (selective_rlen > 0)
3059 {
3060 p1 += selective_rlen;
d2f84654 3061 if (p1 - leftmargin > width)
a2889657 3062 p1 = endp;
278feba9 3063 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c2250c2 3064 (p1 - p1prev), current_face);
a2889657 3065 }
87485d6f 3066#ifdef HAVE_FACES
3c5c35c5
JB
3067 /* Draw the face of the newline character as extending all the
3068 way to the end of the frame line. */
3069 if (current_face)
1105ff20
KH
3070 {
3071 if (p1 < leftmargin)
3072 p1 = leftmargin;
3073 while (p1 < endp)
3074 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
3075 }
3c5c35c5 3076#endif
545e04f6
KH
3077
3078 /* Update charstarts for the ^M that ended this line. */
3079 /* Do nothing here for a char that's entirely off the left edge
3080 or if it starts at the right edge. */
3081 if (p1 >= leftmargin && p1prev != endp)
3082 {
3083 /* Store the newline's position into charstarts
3084 for the column where the newline starts.
3085 Store -1 for the rest of the glyphs it occupies. */
3086 int *p2x = &charstart[(p1prev < leftmargin
3087 ? leftmargin : p1prev)
3088 - p1start];
3089 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3090
3091 *p2x++ = pos;
3092 while (p2x < p2)
3093 *p2x++ = -1;
3094 }
68a37fa8 3095 break;
a2889657 3096 }
a2889657
JB
3097 else if (c < 0200 && ctl_arrow)
3098 {
d2f84654 3099 if (p1 >= leftmargin)
e24c997d 3100 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
278feba9
RS
3101 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
3102 current_face);
a2889657 3103 p1++;
d2f84654 3104 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 3105 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
a2889657
JB
3106 p1++;
3107 }
3108 else
3109 {
d2f84654 3110 if (p1 >= leftmargin)
e24c997d 3111 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
278feba9
RS
3112 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
3113 current_face);
a2889657 3114 p1++;
d2f84654 3115 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 3116 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
a2889657 3117 p1++;
d2f84654 3118 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 3119 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
a2889657 3120 p1++;
d2f84654 3121 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 3122 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
a2889657
JB
3123 p1++;
3124 }
31b24551 3125
ca26e1c8 3126 prevpos = pos;
a2889657 3127 pos++;
545e04f6
KH
3128
3129 /* Update charstarts for the character just output. */
3130
3131 /* Do nothing here for a char that's entirely off the left edge. */
3132 if (p1 >= leftmargin)
3133 {
3134 /* Store the char's position into charstarts
3135 for the first glyph occupied by this char.
3136 Store -1 for the rest of the glyphs it occupies. */
3137 if (p1 != p1prev)
3138 {
3139 int *p2x = &charstart[(p1prev < leftmargin
3140 ? leftmargin : p1prev)
3141 - p1start];
3142 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3143
3144 if (p2x < p2)
3145 *p2x++ = prevpos;
3146 while (p2x < p2)
3147 *p2x++ = -1;
3148 }
3149 }
a2889657
JB
3150 }
3151
3152 val.hpos = - XINT (w->hscroll);
3153 if (val.hpos)
3154 val.hpos++;
3155
3156 val.vpos = 1;
3157
3158 lastpos = pos;
3159
efc63ef0
RS
3160 /* Store 0 in this charstart line for the positions where
3161 there is no character. But do leave what was recorded
3162 for the character that ended the line. */
85bcef6c
RS
3163 /* Add 1 in the endtest to compensate for the fact that ENDP was
3164 made from WIDTH, which is 1 less than the window's actual
3165 internal width. */
a007eef6
RS
3166 i = p1 - p1start + 1;
3167 if (p1 < leftmargin)
3168 i += leftmargin - p1;
3169 for (; i < endp - p1start + 1; i++)
efc63ef0
RS
3170 charstart[i] = 0;
3171
a2889657
JB
3172 /* Handle continuation in middle of a character */
3173 /* by backing up over it */
3174 if (p1 > endp)
3175 {
5fcbb24d
JB
3176 /* Don't back up if we never actually displayed any text.
3177 This occurs when the minibuffer prompt takes up the whole line. */
3178 if (p1prev)
3179 {
3180 /* Start the next line with that same character */
3181 pos--;
3182 /* but at negative hpos, to skip the columns output on this line. */
3183 val.hpos += p1prev - endp;
3184 }
3185
a2889657
JB
3186 /* Keep in this line everything up to the continuation column. */
3187 p1 = endp;
3188 }
3189
3190 /* Finish deciding which character to start the next line on,
3191 and what hpos to start it at.
3192 Also set `lastpos' to the last position which counts as "on this line"
3193 for cursor-positioning. */
3194
3195 if (pos < ZV)
3196 {
3197 if (FETCH_CHAR (pos) == '\n')
dd5f6267
KH
3198 {
3199 /* If stopped due to a newline, start next line after it */
3200 pos++;
3201 /* Check again for hidden lines, in case the newline occurred exactly
3202 at the right margin. */
3203 while (pos < ZV && selective > 0
3204 && indented_beyond_p (pos, selective))
3205 pos = find_next_newline (pos, 1);
3206 }
a2889657
JB
3207 else
3208 /* Stopped due to right margin of window */
3209 {
3210 if (truncate)
3211 {
278feba9 3212 *p1++ = fix_glyph (f, truncator, 0);
a2889657
JB
3213 /* Truncating => start next line after next newline,
3214 and point is on this line if it is before the newline,
3215 and skip none of first char of next line */
dd5f6267
KH
3216 do
3217 pos = find_next_newline (pos, 1);
3218 while (pos < ZV && selective > 0
3219 && indented_beyond_p (pos, selective));
a2889657
JB
3220 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
3221
3222 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
3223 }
3224 else
3225 {
278feba9 3226 *p1++ = fix_glyph (f, continuer, 0);
a2889657
JB
3227 val.vpos = 0;
3228 lastpos--;
3229 }
3230 }
3231 }
3232
3233 /* If point is at eol or in invisible text at eol,
44fa5b1e 3234 record its frame location now. */
a2889657 3235
ae3b1442 3236 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
a2889657
JB
3237 {
3238 cursor_vpos = vpos;
d2f84654 3239 cursor_hpos = p1 - leftmargin;
a2889657
JB
3240 }
3241
3242 if (cursor_vpos == vpos)
3243 {
3244 if (cursor_hpos < 0) cursor_hpos = 0;
3245 if (cursor_hpos > width) cursor_hpos = width;
73f194f1 3246 cursor_hpos += WINDOW_LEFT_MARGIN (w);
44fa5b1e 3247 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
a2889657 3248 {
b5bbc9a5
KH
3249 if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
3250 && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
3251 {
3252 FRAME_CURSOR_Y (f) = cursor_vpos;
3253 FRAME_CURSOR_X (f) = cursor_hpos;
3254 }
a2889657
JB
3255
3256 if (w == XWINDOW (selected_window))
3257 {
3258 /* Line is not continued and did not start
3259 in middle of character */
73f194f1 3260 if ((hpos - WINDOW_LEFT_MARGIN (w)
a2889657
JB
3261 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
3262 && val.vpos)
3263 {
3264 this_line_bufpos = start;
3265 this_line_buffer = current_buffer;
3266 this_line_vpos = cursor_vpos;
3267 this_line_start_hpos = hpos;
3268 this_line_endpos = Z - lastpos;
3269 }
3270 else
3271 this_line_bufpos = 0;
3272 }
3273 }
3274 }
3275
3276 /* If hscroll and line not empty, insert truncation-at-left marker */
3277 if (hscroll && lastpos != start)
3278 {
d2f84654
RS
3279 *leftmargin = fix_glyph (f, truncator, 0);
3280 if (p1 <= leftmargin)
3281 p1 = leftmargin + 1;
a2889657
JB
3282 }
3283
73f194f1 3284 if (!WINDOW_RIGHTMOST_P (w))
a2889657
JB
3285 {
3286 endp++;
d2f84654 3287 if (p1 < leftmargin) p1 = leftmargin;
a2889657 3288 while (p1 < endp) *p1++ = SPACEGLYPH;
b1d1124b 3289
88f22aff
JB
3290 /* Don't draw vertical bars if we're using scroll bars. They're
3291 covered up by the scroll bars, and it's distracting to see
3292 them when the scroll bar windows are flickering around to be
b1d1124b 3293 reconfigured. */
73f194f1 3294 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
75d13c64
KH
3295 {
3296 int i;
3297 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
3298 *p1++ = SPACEGLYPH;
3299 }
73f194f1 3300 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
75d13c64
KH
3301 *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
3302 ? DISP_BORDER_GLYPH (dp)
3303 : '|');
a2889657
JB
3304 }
3305 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
3306 p1 - desired_glyphs->glyphs[vpos]);
3307 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3308
3309 /* If the start of this line is the overlay arrow-position,
3310 then put the arrow string into the display-line. */
3311
e24c997d 3312 if (MARKERP (Voverlay_arrow_position)
a2889657
JB
3313 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
3314 && start == marker_position (Voverlay_arrow_position)
e24c997d 3315 && STRINGP (Voverlay_arrow_string)
a2889657
JB
3316 && ! overlay_arrow_seen)
3317 {
3318 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
3319 int i;
3320 int len = XSTRING (Voverlay_arrow_string)->size;
142be3dd 3321 int arrow_end;
a2889657 3322
b1d1124b
JB
3323 if (len > width)
3324 len = width;
87485d6f 3325#ifdef HAVE_FACES
c4628384
RS
3326 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
3327 {
3328 /* If the arrow string has text props, obey them when displaying. */
3329 for (i = 0; i < len; i++)
3330 {
3331 int c = p[i];
3332 Lisp_Object face, ilisp;
3333 int newface;
3334
c2213350 3335 XSETFASTINT (ilisp, i);
c4628384
RS
3336 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
3337 newface = compute_glyph_face_1 (f, face, 0);
3338 leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
3339 }
3340 }
3341 else
87485d6f 3342#endif /* HAVE_FACES */
c4628384
RS
3343 {
3344 for (i = 0; i < len; i++)
3345 leftmargin[i] = p[i];
3346 }
142be3dd
JB
3347
3348 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
d2f84654 3349 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
142be3dd
JB
3350 if (desired_glyphs->used[vpos] < arrow_end)
3351 desired_glyphs->used[vpos] = arrow_end;
a2889657
JB
3352
3353 overlay_arrow_seen = 1;
3354 }
3355
3356 val.bufpos = pos;
0f9c0ff0 3357 val.ovstring_chars_done = ovstr_done;
a2889657
JB
3358 val_display_text_line = val;
3359 return &val_display_text_line;
3360}
3361\f
7ce2c095
RS
3362/* Redisplay the menu bar in the frame for window W. */
3363
3364static void
3365display_menu_bar (w)
3366 struct window *w;
3367{
3368 Lisp_Object items, tail;
3369 register int vpos = 0;
3370 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3371 int maxendcol = FRAME_WIDTH (f);
3372 int hpos = 0;
8351baf2 3373 int i;
7ce2c095 3374
dc937613 3375#ifdef HAVE_NTGUI
d129c4c2
KH
3376 if (!NILP (Vwindow_system))
3377 return;
dc937613
RS
3378#endif
3379
3380#ifdef USE_X_TOOLKIT
d3413a53 3381 if (FRAME_X_P (f))
7ce2c095 3382 return;
dc937613 3383#endif /* USE_X_TOOLKIT */
7ce2c095
RS
3384
3385 get_display_line (f, vpos, 0);
3386
8351baf2 3387 items = FRAME_MENU_BAR_ITEMS (f);
469937ac 3388 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 3389 {
8351baf2
RS
3390 Lisp_Object pos, string;
3391 string = XVECTOR (items)->contents[i + 1];
3392 if (NILP (string))
3393 break;
2d66ad19 3394
469937ac 3395 XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
7ce2c095
RS
3396
3397 if (hpos < maxendcol)
3398 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
3399 XSTRING (string)->data,
90adcf20 3400 XSTRING (string)->size,
278feba9 3401 hpos, 0, 0, hpos, maxendcol);
6b1bbc46 3402 /* Put a space between items. */
2d66ad19
RS
3403 if (hpos < maxendcol)
3404 {
6b1bbc46 3405 int hpos1 = hpos + 1;
278feba9 3406 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
2d66ad19
RS
3407 min (hpos1, maxendcol), maxendcol);
3408 }
7ce2c095
RS
3409 }
3410
3411 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3412 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2d66ad19
RS
3413
3414 /* Fill out the line with spaces. */
3415 if (maxendcol > hpos)
278feba9 3416 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
db6f348c
JB
3417
3418 /* Clear the rest of the lines allocated to the menu bar. */
3419 vpos++;
3420 while (vpos < FRAME_MENU_BAR_LINES (f))
3421 get_display_line (f, vpos++, 0);
7ce2c095
RS
3422}
3423\f
a2889657
JB
3424/* Display the mode line for window w */
3425
3426static void
3427display_mode_line (w)
3428 struct window *w;
3429{
3430 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
73f194f1
RS
3431 register int left = WINDOW_LEFT_MARGIN (w);
3432 register int right = WINDOW_RIGHT_MARGIN (w);
44fa5b1e 3433 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
a2889657 3434
aa6d10fa 3435 line_number_displayed = 0;
155ef550 3436 w->column_number_displayed = Qnil;
aa6d10fa 3437
44fa5b1e 3438 get_display_line (f, vpos, left);
03b294dc
RS
3439
3440 /* Temporarily make frame F's kboard the current kboard
3441 so that kboard-local variables in the mode_line_format
3442 will get the right values. */
3443 push_frame_kboard (f);
3444
3445 display_mode_element (w, vpos, left, 0, right, right,
3446 current_buffer->mode_line_format);
3447
3448 pop_frame_kboard ();
3449
44fa5b1e 3450 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
a2889657 3451
73f194f1
RS
3452 /* Put the mode line in inverse video.
3453 Use faces if possible, since that lets us handle
3454 partial-width windows and avoid inverting the scroll bar columns. */
87485d6f 3455#ifdef HAVE_FACES
73f194f1 3456 if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
d7eb09a0
RS
3457 {
3458 /* For a partial width window, explicitly set face of each glyph. */
3459 int i;
3460 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
3461 for (i = left; i < right; ++i)
4cdc65eb 3462 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
d7eb09a0 3463 }
4cdc65eb 3464#endif
73f194f1
RS
3465
3466 /* Make the mode line inverse video if the entire line
3467 is made of mode lines.
3468 I.e. if this window is full width,
3469 or if it is the child of a full width window
3470 (which implies that that window is split side-by-side
3471 and the rest of this line is mode lines of the sibling windows). */
3472 else if (WINDOW_FULL_WIDTH_P (w)
3473 || WINDOW_FULL_WIDTH_P (XWINDOW (w->parent)))
3474 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
a2889657
JB
3475}
3476
3477/* Contribute ELT to the mode line for window W.
3478 How it translates into text depends on its data type.
3479
3480 VPOS is the position of the mode line being displayed.
3481
44fa5b1e 3482 HPOS is the position (absolute on frame) where this element's text
a2889657
JB
3483 should start. The output is truncated automatically at the right
3484 edge of window W.
3485
3486 DEPTH is the depth in recursion. It is used to prevent
3487 infinite recursion here.
3488
3489 MINENDCOL is the hpos before which the element may not end.
3490 The element is padded at the right with spaces if nec
3491 to reach this column.
3492
3493 MAXENDCOL is the hpos past which this element may not extend.
3494 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3495 (This is necessary to make nested padding and truncation work.)
3496
3497 Returns the hpos of the end of the text generated by ELT.
3498 The next element will receive that value as its HPOS arg,
3499 so as to concatenate the elements. */
3500
3501static int
3502display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
3503 struct window *w;
3504 register int vpos, hpos;
3505 int depth;
3506 int minendcol;
3507 register int maxendcol;
3508 register Lisp_Object elt;
3509{
3510 tail_recurse:
3511 if (depth > 10)
3512 goto invalid;
3513
3514 depth++;
3515
0220c518 3516 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
3517 {
3518 case Lisp_String:
3519 {
3520 /* A string: output it and check for %-constructs within it. */
3521 register unsigned char c;
3522 register unsigned char *this = XSTRING (elt)->data;
3523
3524 while (hpos < maxendcol && *this)
3525 {
3526 unsigned char *last = this;
3527 while ((c = *this++) != '\0' && c != '%')
3528 ;
3529 if (this - 1 != last)
3530 {
3531 register int lim = --this - last + hpos;
d39b6696
KH
3532 if (frame_title_ptr)
3533 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
3534 else
3535 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
3536 hpos, min (lim, maxendcol));
a2889657
JB
3537 }
3538 else /* c == '%' */
3539 {
766525bc 3540 register int minendcol;
a2889657
JB
3541 register int spec_width = 0;
3542
3543 /* We can't allow -ve args due to the "%-" construct */
3544 /* Argument specifies minwidth but not maxwidth
3545 (maxwidth can be specified by
3546 (<negative-number> . <stuff>) mode-line elements) */
3547
3548 while ((c = *this++) >= '0' && c <= '9')
3549 {
3550 spec_width = spec_width * 10 + (c - '0');
3551 }
3552
766525bc
RS
3553 minendcol = hpos + spec_width;
3554 if (minendcol > maxendcol)
3555 {
3556 spec_width = maxendcol - hpos;
3557 minendcol = maxendcol;
3558 }
a2889657
JB
3559
3560 if (c == 'M')
3561 hpos = display_mode_element (w, vpos, hpos, depth,
3562 spec_width, maxendcol,
3563 Vglobal_mode_string);
3564 else if (c != 0)
d39b6696 3565 {
766525bc
RS
3566 char *spec = decode_mode_spec (w, c, spec_width,
3567 maxendcol - hpos);
d39b6696 3568 if (frame_title_ptr)
766525bc 3569 hpos = store_frame_title (spec, minendcol, maxendcol);
d39b6696
KH
3570 else
3571 hpos = display_string (w, vpos, spec, -1,
3572 hpos, 0, 1,
766525bc 3573 minendcol, maxendcol);
d39b6696 3574 }
a2889657
JB
3575 }
3576 }
3577 }
3578 break;
3579
3580 case Lisp_Symbol:
3581 /* A symbol: process the value of the symbol recursively
3582 as if it appeared here directly. Avoid error if symbol void.
3583 Special case: if value of symbol is a string, output the string
3584 literally. */
3585 {
3586 register Lisp_Object tem;
3587 tem = Fboundp (elt);
265a9e55 3588 if (!NILP (tem))
a2889657
JB
3589 {
3590 tem = Fsymbol_value (elt);
3591 /* If value is a string, output that string literally:
3592 don't check for % within it. */
e24c997d 3593 if (STRINGP (tem))
d39b6696
KH
3594 {
3595 if (frame_title_ptr)
3596 hpos = store_frame_title (XSTRING (tem)->data,
3597 minendcol, maxendcol);
3598 else
3599 hpos = display_string (w, vpos, XSTRING (tem)->data,
3600 XSTRING (tem)->size,
3601 hpos, 0, 1, minendcol, maxendcol);
3602 }
a2889657
JB
3603 /* Give up right away for nil or t. */
3604 else if (!EQ (tem, elt))
3605 { elt = tem; goto tail_recurse; }
3606 }
3607 }
3608 break;
3609
3610 case Lisp_Cons:
3611 {
3612 register Lisp_Object car, tem;
3613
3614 /* A cons cell: three distinct cases.
3615 If first element is a string or a cons, process all the elements
3616 and effectively concatenate them.
3617 If first element is a negative number, truncate displaying cdr to
3618 at most that many characters. If positive, pad (with spaces)
3619 to at least that many characters.
3620 If first element is a symbol, process the cadr or caddr recursively
3621 according to whether the symbol's value is non-nil or nil. */
3622 car = XCONS (elt)->car;
e24c997d 3623 if (SYMBOLP (car))
a2889657
JB
3624 {
3625 tem = Fboundp (car);
3626 elt = XCONS (elt)->cdr;
e24c997d 3627 if (!CONSP (elt))
a2889657
JB
3628 goto invalid;
3629 /* elt is now the cdr, and we know it is a cons cell.
3630 Use its car if CAR has a non-nil value. */
265a9e55 3631 if (!NILP (tem))
a2889657
JB
3632 {
3633 tem = Fsymbol_value (car);
265a9e55 3634 if (!NILP (tem))
a2889657
JB
3635 { elt = XCONS (elt)->car; goto tail_recurse; }
3636 }
3637 /* Symbol's value is nil (or symbol is unbound)
3638 Get the cddr of the original list
3639 and if possible find the caddr and use that. */
3640 elt = XCONS (elt)->cdr;
265a9e55 3641 if (NILP (elt))
a2889657 3642 break;
e24c997d 3643 else if (!CONSP (elt))
a2889657
JB
3644 goto invalid;
3645 elt = XCONS (elt)->car;
3646 goto tail_recurse;
3647 }
e24c997d 3648 else if (INTEGERP (car))
a2889657
JB
3649 {
3650 register int lim = XINT (car);
3651 elt = XCONS (elt)->cdr;
3652 if (lim < 0)
3653 /* Negative int means reduce maximum width.
3654 DO NOT change MINENDCOL here!
3655 (20 -10 . foo) should truncate foo to 10 col
3656 and then pad to 20. */
3657 maxendcol = min (maxendcol, hpos - lim);
3658 else if (lim > 0)
3659 {
3660 /* Padding specified. Don't let it be more than
3661 current maximum. */
3662 lim += hpos;
3663 if (lim > maxendcol)
3664 lim = maxendcol;
3665 /* If that's more padding than already wanted, queue it.
3666 But don't reduce padding already specified even if
3667 that is beyond the current truncation point. */
3668 if (lim > minendcol)
3669 minendcol = lim;
3670 }
3671 goto tail_recurse;
3672 }
e24c997d 3673 else if (STRINGP (car) || CONSP (car))
a2889657
JB
3674 {
3675 register int limit = 50;
3676 /* LIMIT is to protect against circular lists. */
e24c997d 3677 while (CONSP (elt) && --limit > 0
a2889657
JB
3678 && hpos < maxendcol)
3679 {
3680 hpos = display_mode_element (w, vpos, hpos, depth,
3681 hpos, maxendcol,
3682 XCONS (elt)->car);
3683 elt = XCONS (elt)->cdr;
3684 }
3685 }
3686 }
3687 break;
3688
3689 default:
3690 invalid:
d39b6696
KH
3691 if (frame_title_ptr)
3692 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
3693 else
3694 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
3695 minendcol, maxendcol);
3696 return hpos;
a2889657
JB
3697 }
3698
a2889657 3699 if (minendcol > hpos)
d39b6696
KH
3700 if (frame_title_ptr)
3701 hpos = store_frame_title ("", minendcol, maxendcol);
3702 else
3703 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
a2889657
JB
3704 return hpos;
3705}
3706\f
766525bc
RS
3707/* Write a null-terminated, right justified decimal representation of
3708 the positive integer D to BUF using a minimal field width WIDTH. */
3709
3710static void
3711pint2str (buf, width, d)
3712 register char *buf;
3713 register int width;
3714 register int d;
3715{
3716 register char *p = buf;
3717
3718 if (d <= 0)
3719 *p++ = '0';
3720 else
3721 while (d > 0)
3722 {
3723 *p++ = d % 10 + '0';
3724 d /= 10;
3725 }
3726 for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
3727 *p-- = '\0';
3728 while (p > buf)
3729 {
3730 d = *buf;
3731 *buf++ = *p;
3732 *p-- = d;
3733 }
3734}
3735
a2889657 3736/* Return a string for the output of a mode line %-spec for window W,
766525bc
RS
3737 generated by character C. SPEC_WIDTH is the field width when
3738 padding to the left (%c, %l). The value returned from this
3739 function will later be truncated to width MAXWIDTH. */
a2889657 3740
11e82b76
JB
3741static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3742
a2889657 3743static char *
766525bc 3744decode_mode_spec (w, c, spec_width, maxwidth)
a2889657
JB
3745 struct window *w;
3746 register char c;
766525bc 3747 register int spec_width;
a2889657
JB
3748 register int maxwidth;
3749{
0b67772d 3750 Lisp_Object obj;
44fa5b1e
JB
3751 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3752 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
d39b6696 3753 struct buffer *b = XBUFFER (w->buffer);
a2889657 3754
0b67772d 3755 obj = Qnil;
44fa5b1e
JB
3756 if (maxwidth > FRAME_WIDTH (f))
3757 maxwidth = FRAME_WIDTH (f);
a2889657
JB
3758
3759 switch (c)
3760 {
1af9f229
RS
3761 case '*':
3762 if (!NILP (b->read_only))
3763 return "%";
3764 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3765 return "*";
3766 return "-";
3767
3768 case '+':
3769 /* This differs from %* only for a modified read-only buffer. */
3770 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3771 return "*";
3772 if (!NILP (b->read_only))
3773 return "%";
3774 return "-";
3775
3776 case '&':
3777 /* This differs from %* in ignoring read-only-ness. */
3778 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3779 return "*";
3780 return "-";
3781
3782 case '%':
3783 return "%";
3784
3785 case '[':
3786 {
3787 int i;
3788 char *p;
3789
3790 if (command_loop_level > 5)
3791 return "[[[... ";
3792 p = decode_mode_spec_buf;
3793 for (i = 0; i < command_loop_level; i++)
3794 *p++ = '[';
3795 *p = 0;
3796 return decode_mode_spec_buf;
3797 }
3798
3799 case ']':
3800 {
3801 int i;
3802 char *p;
3803
3804 if (command_loop_level > 5)
3805 return " ...]]]";
3806 p = decode_mode_spec_buf;
3807 for (i = 0; i < command_loop_level; i++)
3808 *p++ = ']';
3809 *p = 0;
3810 return decode_mode_spec_buf;
3811 }
3812
3813 case '-':
3814 {
3815 register char *p;
3816 register int i;
3817
3818 if (maxwidth < sizeof (lots_of_dashes))
3819 return lots_of_dashes;
3820 else
3821 {
3822 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
3823 *p++ = '-';
3824 *p = '\0';
3825 }
3826 return decode_mode_spec_buf;
3827 }
3828
a2889657 3829 case 'b':
d39b6696 3830 obj = b->name;
a2889657
JB
3831#if 0
3832 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
3833 {
3834 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
3835 decode_mode_spec_buf[maxwidth - 1] = '\\';
3836 decode_mode_spec_buf[maxwidth] = '\0';
3837 return decode_mode_spec_buf;
3838 }
3839#endif
3840 break;
3841
1af9f229
RS
3842 case 'c':
3843 {
3844 int col = current_column ();
3845 XSETFASTINT (w->column_number_displayed, col);
766525bc 3846 pint2str (decode_mode_spec_buf, spec_width, col);
1af9f229
RS
3847 return decode_mode_spec_buf;
3848 }
3849
3850 case 'F':
3851 /* %F displays the frame name. */
95184b48
RS
3852 if (!NILP (f->title))
3853 return (char *) XSTRING (f->title)->data;
fd8ff63d 3854 if (f->explicit_name || ! FRAME_WINDOW_P (f))
95184b48 3855 return (char *) XSTRING (f->name)->data;
9c6da96f 3856 return "Emacs";
1af9f229 3857
a2889657 3858 case 'f':
d39b6696 3859 obj = b->filename;
a2889657 3860#if 0
265a9e55 3861 if (NILP (obj))
a2889657 3862 return "[none]";
e24c997d 3863 else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
a2889657
JB
3864 {
3865 bcopy ("...", decode_mode_spec_buf, 3);
3866 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
3867 decode_mode_spec_buf + 3, maxwidth - 3);
3868 return decode_mode_spec_buf;
3869 }
3870#endif
3871 break;
3872
aa6d10fa
RS
3873 case 'l':
3874 {
3875 int startpos = marker_position (w->start);
3876 int line, linepos, topline;
3877 int nlines, junk;
3878 Lisp_Object tem;
3879 int height = XFASTINT (w->height);
3880
3881 /* If we decided that this buffer isn't suitable for line numbers,
3882 don't forget that too fast. */
3883 if (EQ (w->base_line_pos, w->buffer))
766525bc 3884 goto no_value;
5300fd39
RS
3885 /* But do forget it, if the window shows a different buffer now. */
3886 else if (BUFFERP (w->base_line_pos))
3887 w->base_line_pos = Qnil;
aa6d10fa
RS
3888
3889 /* If the buffer is very big, don't waste time. */
d39b6696 3890 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
aa6d10fa
RS
3891 {
3892 w->base_line_pos = Qnil;
3893 w->base_line_number = Qnil;
766525bc 3894 goto no_value;
aa6d10fa
RS
3895 }
3896
3897 if (!NILP (w->base_line_number)
3898 && !NILP (w->base_line_pos)
3899 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
3900 {
3901 line = XFASTINT (w->base_line_number);
3902 linepos = XFASTINT (w->base_line_pos);
3903 }
3904 else
3905 {
3906 line = 1;
d39b6696 3907 linepos = BUF_BEGV (b);
aa6d10fa
RS
3908 }
3909
3910 /* Count lines from base line to window start position. */
3911 nlines = display_count_lines (linepos, startpos, startpos, &junk);
3912
3913 topline = nlines + line;
3914
3915 /* Determine a new base line, if the old one is too close
3916 or too far away, or if we did not have one.
3917 "Too close" means it's plausible a scroll-down would
3918 go back past it. */
d39b6696 3919 if (startpos == BUF_BEGV (b))
aa6d10fa 3920 {
c2213350
KH
3921 XSETFASTINT (w->base_line_number, topline);
3922 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
3923 }
3924 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 3925 || linepos == BUF_BEGV (b))
aa6d10fa 3926 {
d39b6696 3927 int limit = BUF_BEGV (b);
aa6d10fa
RS
3928 int position;
3929 int distance = (height * 2 + 30) * 200;
3930
3931 if (startpos - distance > limit)
3932 limit = startpos - distance;
3933
3934 nlines = display_count_lines (startpos, limit,
3935 -(height * 2 + 30),
3936 &position);
3937 /* If we couldn't find the lines we wanted within
3938 200 chars per line,
3939 give up on line numbers for this window. */
3940 if (position == startpos - distance)
3941 {
3942 w->base_line_pos = w->buffer;
3943 w->base_line_number = Qnil;
766525bc 3944 goto no_value;
aa6d10fa
RS
3945 }
3946
c2213350
KH
3947 XSETFASTINT (w->base_line_number, topline - nlines);
3948 XSETFASTINT (w->base_line_pos, position);
aa6d10fa
RS
3949 }
3950
3951 /* Now count lines from the start pos to point. */
3952 nlines = display_count_lines (startpos, PT, PT, &junk);
3953
3954 /* Record that we did display the line number. */
3955 line_number_displayed = 1;
3956
3957 /* Make the string to show. */
766525bc 3958 pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
aa6d10fa 3959 return decode_mode_spec_buf;
766525bc
RS
3960 no_value:
3961 {
3962 char* p = decode_mode_spec_buf;
3963 for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
3964 strcpy (p, "??");
3965 return decode_mode_spec_buf;
3966 }
aa6d10fa
RS
3967 }
3968 break;
3969
a2889657 3970 case 'm':
d39b6696 3971 obj = b->mode_name;
a2889657
JB
3972 break;
3973
3974 case 'n':
d39b6696 3975 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
3976 return " Narrow";
3977 break;
3978
a2889657
JB
3979 case 'p':
3980 {
3981 int pos = marker_position (w->start);
d39b6696 3982 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 3983
d39b6696 3984 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 3985 {
d39b6696 3986 if (pos <= BUF_BEGV (b))
a2889657
JB
3987 return "All";
3988 else
3989 return "Bottom";
3990 }
d39b6696 3991 else if (pos <= BUF_BEGV (b))
a2889657
JB
3992 return "Top";
3993 else
3994 {
3c7d31b9
RS
3995 if (total > 1000000)
3996 /* Do it differently for a large value, to avoid overflow. */
3997 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
3998 else
3999 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
4000 /* We can't normally display a 3-digit number,
4001 so get us a 2-digit number that is close. */
4002 if (total == 100)
4003 total = 99;
4004 sprintf (decode_mode_spec_buf, "%2d%%", total);
4005 return decode_mode_spec_buf;
4006 }
4007 }
4008
8ffcb79f
RS
4009 /* Display percentage of size above the bottom of the screen. */
4010 case 'P':
4011 {
4012 int toppos = marker_position (w->start);
d39b6696
KH
4013 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
4014 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 4015
d39b6696 4016 if (botpos >= BUF_ZV (b))
8ffcb79f 4017 {
d39b6696 4018 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
4019 return "All";
4020 else
4021 return "Bottom";
4022 }
4023 else
4024 {
3c7d31b9
RS
4025 if (total > 1000000)
4026 /* Do it differently for a large value, to avoid overflow. */
4027 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
4028 else
4029 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
4030 /* We can't normally display a 3-digit number,
4031 so get us a 2-digit number that is close. */
4032 if (total == 100)
4033 total = 99;
d39b6696 4034 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
4035 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
4036 else
4037 sprintf (decode_mode_spec_buf, "%2d%%", total);
4038 return decode_mode_spec_buf;
4039 }
4040 }
4041
1af9f229
RS
4042 case 's':
4043 /* status of process */
4044 obj = Fget_buffer_process (w->buffer);
4045 if (NILP (obj))
4046 return "no process";
4047#ifdef subprocesses
4048 obj = Fsymbol_name (Fprocess_status (obj));
4049#endif
4050 break;
d39b6696 4051
1af9f229
RS
4052 case 't': /* indicate TEXT or BINARY */
4053#ifdef MODE_LINE_BINARY_TEXT
4054 return MODE_LINE_BINARY_TEXT (b);
4055#else
4056 return "T";
4057#endif
a2889657 4058 }
d39b6696 4059
e24c997d 4060 if (STRINGP (obj))
a2889657
JB
4061 return (char *) XSTRING (obj)->data;
4062 else
4063 return "";
4064}
59b49f63
RS
4065\f
4066/* Search for COUNT instances of a line boundary, which means either a
4067 newline or (if selective display enabled) a carriage return.
4068 Start at START. If COUNT is negative, search backwards.
4069
4070 If we find COUNT instances, set *SHORTAGE to zero, and return the
4071 position after the COUNTth match. Note that for reverse motion
4072 this is not the same as the usual convention for Emacs motion commands.
4073
4074 If we don't find COUNT instances before reaching the end of the
4075 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
4076 the number of line boundaries left unfound, and return the end of the
4077 buffer we bumped up against. */
4078
4079static int
4080display_scan_buffer (start, count, shortage)
4081 int *shortage, start;
4082 register int count;
4083{
4084 int limit = ((count > 0) ? ZV - 1 : BEGV);
4085 int direction = ((count > 0) ? 1 : -1);
4086
4087 register unsigned char *cursor;
4088 unsigned char *base;
4089
4090 register int ceiling;
4091 register unsigned char *ceiling_addr;
4092
4093 /* If we are not in selective display mode,
4094 check only for newlines. */
4095 if (! (!NILP (current_buffer->selective_display)
4096 && !INTEGERP (current_buffer->selective_display)))
ae474ea9 4097 return scan_buffer ('\n', start, 0, count, shortage, 0);
59b49f63
RS
4098
4099 /* The code that follows is like scan_buffer
4100 but checks for either newline or carriage return. */
4101
4102 if (shortage != 0)
4103 *shortage = 0;
4104
4105 if (count > 0)
4106 while (start != limit + 1)
4107 {
4108 ceiling = BUFFER_CEILING_OF (start);
4109 ceiling = min (limit, ceiling);
4110 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
4111 base = (cursor = &FETCH_CHAR (start));
4112 while (1)
4113 {
4114 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
4115 ;
4116 if (cursor != ceiling_addr)
4117 {
4118 if (--count == 0)
4119 {
4120 immediate_quit = 0;
4121 return (start + cursor - base + 1);
4122 }
4123 else
4124 if (++cursor == ceiling_addr)
4125 break;
4126 }
4127 else
4128 break;
4129 }
4130 start += cursor - base;
4131 }
4132 else
4133 {
4134 start--; /* first character we scan */
4135 while (start > limit - 1)
4136 { /* we WILL scan under start */
4137 ceiling = BUFFER_FLOOR_OF (start);
4138 ceiling = max (limit, ceiling);
4139 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
4140 base = (cursor = &FETCH_CHAR (start));
4141 cursor++;
4142 while (1)
4143 {
4144 while (--cursor != ceiling_addr
4145 && *cursor != '\n' && *cursor != 015)
4146 ;
4147 if (cursor != ceiling_addr)
4148 {
4149 if (++count == 0)
4150 {
4151 immediate_quit = 0;
4152 return (start + cursor - base + 1);
4153 }
4154 }
4155 else
4156 break;
4157 }
4158 start += cursor - base;
4159 }
4160 }
4161
4162 if (shortage != 0)
4163 *shortage = count * direction;
4164 return (start + ((direction == 1 ? 0 : 1)));
4165}
aa6d10fa
RS
4166
4167/* Count up to N lines starting from FROM.
4168 But don't go beyond LIMIT.
4169 Return the number of lines thus found (always positive).
4170 Store the position after what was found into *POS_PTR. */
4171
4172static int
4173display_count_lines (from, limit, n, pos_ptr)
4174 int from, limit, n;
4175 int *pos_ptr;
4176{
4177 int oldbegv = BEGV;
4178 int oldzv = ZV;
4179 int shortage = 0;
4180
4181 if (limit < from)
4182 BEGV = limit;
4183 else
4184 ZV = limit;
4185
59b49f63 4186 *pos_ptr = display_scan_buffer (from, n, &shortage);
aa6d10fa
RS
4187
4188 ZV = oldzv;
4189 BEGV = oldbegv;
4190
4191 if (n < 0)
4192 /* When scanning backwards, scan_buffer stops *after* the last newline
4193 it finds, but does count it. Compensate for that. */
4194 return - n - shortage - (*pos_ptr != limit);
4195 return n - shortage;
4196}
a2889657
JB
4197\f
4198/* Display STRING on one line of window W, starting at HPOS.
4199 Display at position VPOS. Caller should have done get_display_line.
11e82b76 4200 If VPOS == -1, display it as the current frame's title.
90adcf20 4201 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
a2889657
JB
4202
4203 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
4204
4205 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
4206 MAXCOL is the last column ok to end at. Truncate here.
4207 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
44fa5b1e 4208 Both count from the left edge of the frame, as does HPOS.
a2889657
JB
4209 The right edge of W is an implicit maximum.
4210 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
4211
278feba9
RS
4212 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
4213 at the place where the current window ends in this line
4214 and not display anything beyond there. Otherwise, only MAXCOL
4215 controls where to stop output.
4216
4217 Returns ending hpos. */
a2889657
JB
4218
4219static int
278feba9
RS
4220display_string (w, vpos, string, length, hpos, truncate,
4221 obey_window_width, mincol, maxcol)
a2889657
JB
4222 struct window *w;
4223 unsigned char *string;
90adcf20 4224 int length;
a2889657
JB
4225 int vpos, hpos;
4226 GLYPH truncate;
278feba9 4227 int obey_window_width;
a2889657
JB
4228 int mincol, maxcol;
4229{
4230 register int c;
d3413a53 4231 int truncated;
a2889657
JB
4232 register GLYPH *p1;
4233 int hscroll = XINT (w->hscroll);
253c7d2f 4234 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
a2889657
JB
4235 register GLYPH *start;
4236 register GLYPH *end;
b1d1124b
JB
4237 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
4238 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
a2889657
JB
4239 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
4240 int window_width = XFASTINT (w->width);
4241
4242 /* Use the standard display table, not the window's display table.
4243 We don't want the mode line in rot13. */
f908610f 4244 register struct Lisp_Char_Table *dp = 0;
efc63ef0 4245 int i;
a2889657 4246
f908610f
RS
4247 if (DISP_TABLE_P (Vstandard_display_table))
4248 dp = XCHAR_TABLE (Vstandard_display_table);
a2889657 4249
54ff581a 4250 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657
JB
4251
4252 p1 = p1start;
4253 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
a2889657 4254
278feba9 4255 if (obey_window_width)
b1d1124b 4256 {
278feba9
RS
4257 end = start + window_width - (truncate != 0);
4258
73f194f1 4259 if (!WINDOW_RIGHTMOST_P (w))
b1d1124b 4260 {
73f194f1 4261 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
278feba9
RS
4262 {
4263 int i;
b1d1124b 4264
5802e919 4265 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
278feba9
RS
4266 *end-- = ' ';
4267 }
73f194f1 4268 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
278feba9 4269 *end-- = '|';
b1d1124b 4270 }
b1d1124b 4271 }
a2889657 4272
278feba9
RS
4273 if (! obey_window_width
4274 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
a2889657 4275 end = desired_glyphs->glyphs[vpos] + maxcol;
278feba9 4276
efc63ef0 4277 /* Store 0 in charstart for these columns. */
bd5dec8e 4278 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
efc63ef0
RS
4279 desired_glyphs->charstarts[vpos][i] = 0;
4280
a2889657
JB
4281 if (maxcol >= 0 && mincol > maxcol)
4282 mincol = maxcol;
4283
d3413a53
RS
4284 /* We set truncated to 1 if we get stopped by trying to pass END
4285 (that is, trying to pass MAXCOL.) */
4286 truncated = 0;
4287 while (1)
a2889657 4288 {
90adcf20
RS
4289 if (length == 0)
4290 break;
a2889657 4291 c = *string++;
90adcf20
RS
4292 /* Specified length. */
4293 if (length >= 0)
4294 length--;
4295 /* Unspecified length (null-terminated string). */
4296 else if (c == 0)
4297 break;
4298
d3413a53
RS
4299 if (p1 >= end)
4300 {
4301 truncated = 1;
4302 break;
4303 }
4304
376b0e59
RS
4305 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
4306 {
4307 p1 = copy_part_of_rope (f, p1, start,
4308 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
4309 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
4310 0);
4311 }
4312 else if (c >= 040 && c < 0177)
a2889657
JB
4313 {
4314 if (p1 >= start)
4315 *p1 = c;
4316 p1++;
4317 }
4318 else if (c == '\t')
4319 {
4320 do
4321 {
4322 if (p1 >= start && p1 < end)
4323 *p1 = SPACEGLYPH;
4324 p1++;
4325 }
4326 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
4327 }
ded34426 4328 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
a2889657
JB
4329 {
4330 if (p1 >= start)
e24c997d 4331 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
278feba9
RS
4332 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
4333 0);
a2889657 4334 p1++;
6e8290aa 4335 if (p1 >= start && p1 < end)
a2889657
JB
4336 *p1 = c ^ 0100;
4337 p1++;
4338 }
4339 else
4340 {
4341 if (p1 >= start)
e24c997d 4342 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
278feba9
RS
4343 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
4344 0);
a2889657 4345 p1++;
6e8290aa 4346 if (p1 >= start && p1 < end)
a2889657
JB
4347 *p1 = (c >> 6) + '0';
4348 p1++;
6e8290aa 4349 if (p1 >= start && p1 < end)
a2889657
JB
4350 *p1 = (7 & (c >> 3)) + '0';
4351 p1++;
6e8290aa 4352 if (p1 >= start && p1 < end)
a2889657
JB
4353 *p1 = (7 & c) + '0';
4354 p1++;
4355 }
4356 }
4357
d3413a53 4358 if (truncated)
a2889657
JB
4359 {
4360 p1 = end;
278feba9 4361 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
a2889657
JB
4362 }
4363 else if (mincol >= 0)
4364 {
4365 end = desired_glyphs->glyphs[vpos] + mincol;
4366 while (p1 < end)
4367 *p1++ = SPACEGLYPH;
4368 }
4369
4370 {
4371 register int len = p1 - desired_glyphs->glyphs[vpos];
4372
4373 if (len > desired_glyphs->used[vpos])
4374 desired_glyphs->used[vpos] = len;
4375 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
4376
4377 return len;
4378 }
4379}
4380\f
642eefc6
RS
4381/* This is like a combination of memq and assq.
4382 Return 1 if PROPVAL appears as an element of LIST
4383 or as the car of an element of LIST.
af460d46
RS
4384 If PROPVAL is a list, compare each element against LIST
4385 in that way, and return 1 if any element of PROPVAL is found in LIST.
642eefc6
RS
4386 Otherwise return 0.
4387 This function cannot quit. */
4388
4389int
4390invisible_p (propval, list)
4391 register Lisp_Object propval;
4392 Lisp_Object list;
4393{
af460d46
RS
4394 register Lisp_Object tail, proptail;
4395 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
642eefc6
RS
4396 {
4397 register Lisp_Object tem;
af460d46 4398 tem = XCONS (tail)->car;
642eefc6
RS
4399 if (EQ (propval, tem))
4400 return 1;
4401 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4402 return 1;
4403 }
af460d46
RS
4404 if (CONSP (propval))
4405 for (proptail = propval; CONSP (proptail);
4406 proptail = XCONS (proptail)->cdr)
4407 {
4408 Lisp_Object propelt;
4409 propelt = XCONS (proptail)->car;
4410 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4411 {
4412 register Lisp_Object tem;
4413 tem = XCONS (tail)->car;
4414 if (EQ (propelt, tem))
4415 return 1;
4416 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4417 return 1;
4418 }
4419 }
642eefc6
RS
4420 return 0;
4421}
4422
4423/* Return 1 if PROPVAL appears as the car of an element of LIST
4424 and the cdr of that element is non-nil.
af460d46
RS
4425 If PROPVAL is a list, check each element of PROPVAL in that way,
4426 and the first time some element is found,
4427 return 1 if the cdr of that element is non-nil.
642eefc6
RS
4428 Otherwise return 0.
4429 This function cannot quit. */
4430
4431int
4432invisible_ellipsis_p (propval, list)
4433 register Lisp_Object propval;
4434 Lisp_Object list;
4435{
af460d46
RS
4436 register Lisp_Object tail, proptail;
4437 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
642eefc6
RS
4438 {
4439 register Lisp_Object tem;
af460d46 4440 tem = XCONS (tail)->car;
642eefc6
RS
4441 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4442 return ! NILP (XCONS (tem)->cdr);
4443 }
af460d46
RS
4444 if (CONSP (propval))
4445 for (proptail = propval; CONSP (proptail);
4446 proptail = XCONS (proptail)->cdr)
4447 {
4448 Lisp_Object propelt;
4449 propelt = XCONS (proptail)->car;
4450 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4451 {
4452 register Lisp_Object tem;
4453 tem = XCONS (tail)->car;
4454 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4455 return ! NILP (XCONS (tem)->cdr);
4456 }
4457 }
642eefc6
RS
4458 return 0;
4459}
4460\f
a2889657
JB
4461void
4462syms_of_xdisp ()
4463{
cf074754
RS
4464 staticpro (&Qmenu_bar_update_hook);
4465 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
4466
d46fb96a 4467 staticpro (&Qoverriding_terminal_local_map);
7079aefa 4468 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 4469
399164b4
KH
4470 staticpro (&Qoverriding_local_map);
4471 Qoverriding_local_map = intern ("overriding-local-map");
4472
75c43375
RS
4473 staticpro (&Qwindow_scroll_functions);
4474 Qwindow_scroll_functions = intern ("window-scroll-functions");
4475
e0bfbde6
RS
4476 staticpro (&Qredisplay_end_trigger_functions);
4477 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
67481ae5 4478
a2889657
JB
4479 staticpro (&last_arrow_position);
4480 staticpro (&last_arrow_string);
4481 last_arrow_position = Qnil;
4482 last_arrow_string = Qnil;
4483
4484 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 4485 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
4486 Vglobal_mode_string = Qnil;
4487
4488 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
4489 "Marker for where to display an arrow on top of the buffer text.\n\
4490This must be the beginning of a line in order to work.\n\
4491See also `overlay-arrow-string'.");
4492 Voverlay_arrow_position = Qnil;
4493
4494 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
4495 "String to display as an arrow. See also `overlay-arrow-position'.");
4496 Voverlay_arrow_string = Qnil;
4497
4498 DEFVAR_INT ("scroll-step", &scroll_step,
4499 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
4500If that fails to bring point back on frame, point is centered instead.\n\
4501If this is zero, point is always centered after it moves off frame.");
a2889657 4502
0789adb2
RS
4503 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
4504 "*Scroll up to this many lines, to bring point back on screen.");
4505 scroll_conservatively = 0;
4506
9afd2168
RS
4507 DEFVAR_INT ("scroll-margin", &scroll_margin,
4508 "*Number of lines of margin at the top and bottom of a window.\n\
4509Recenter the window whenever point gets within this many lines\n\
4510of the top or bottom of the window.");
4511 scroll_margin = 0;
4512
a2889657
JB
4513 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
4514
4515 DEFVAR_BOOL ("truncate-partial-width-windows",
4516 &truncate_partial_width_windows,
44fa5b1e 4517 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
4518 truncate_partial_width_windows = 1;
4519
4520 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
4521 "*Non-nil means use inverse video for the mode line.");
4522 mode_line_inverse_video = 1;
aa6d10fa
RS
4523
4524 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
4525 "*Maximum buffer size for which line number should be displayed.");
4526 line_number_display_limit = 1000000;
fba9ce76
RS
4527
4528 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
4529 "*Non-nil means highlight region even in nonselected windows.");
4530 highlight_nonselected_windows = 1;
d39b6696
KH
4531
4532 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
4533 "Non-nil if more than one frame is visible on this display.\n\
4534Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
4535This variable is not guaranteed to be accurate except while processing\n\
4536`frame-title-format' and `icon-title-format'.");
d39b6696
KH
4537
4538 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
4539 "Template for displaying the titlebar of visible frames.\n\
4540\(Assuming the window manager supports this feature.)\n\
4541This variable has the same structure as `mode-line-format' (which see),\n\
4542and is used only on frames for which no explicit name has been set\n\
4543\(see `modify-frame-parameters').");
4544 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
4545 "Template for displaying the titlebar of an iconified frame.\n\
4546\(Assuming the window manager supports this feature.)\n\
4547This variable has the same structure as `mode-line-format' (which see),\n\
4548and is used only on frames for which no explicit name has been set\n\
4549\(see `modify-frame-parameters').");
4550 Vicon_title_format
4551 = Vframe_title_format
4552 = Fcons (intern ("multiple-frames"),
4553 Fcons (build_string ("%b"),
4554 Fcons (Fcons (build_string (""),
4555 Fcons (intern ("invocation-name"),
4556 Fcons (build_string ("@"),
4557 Fcons (intern ("system-name"),
4558 Qnil)))),
4559 Qnil)));
5992c4f7
KH
4560
4561 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
4562 "Maximum number of lines to keep in the message log buffer.\n\
4563If nil, disable message logging. If t, log messages but don't truncate\n\
4564the buffer when it becomes large.");
4565 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
4566
4567 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
4568 "Functions called before redisplay, if window sizes have changed.\n\
4569The value should be a list of functions that take one argument.\n\
4570Just before redisplay, for each frame, if any of its windows have changed\n\
4571size since the last redisplay, or have been split or deleted,\n\
4572all the functions in the list are called, with the frame as argument.");
4573 Vwindow_size_change_functions = Qnil;
75c43375
RS
4574
4575 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
f908610f 4576 "List of Functions to call before redisplaying a window with scrolling.\n\
75c43375 4577Each function is called with two arguments, the window\n\
8d9583b0
RS
4578and its new display-start position. Note that the value of `window-end'\n\
4579is not valid when these functions are called.");
75c43375 4580 Vwindow_scroll_functions = Qnil;
a2889657
JB
4581}
4582
4583/* initialize the window system */
4584init_xdisp ()
4585{
4586 Lisp_Object root_window;
4587#ifndef COMPILER_REGISTER_BUG
4588 register
4589#endif /* COMPILER_REGISTER_BUG */
4590 struct window *mini_w;
4591
4592 this_line_bufpos = 0;
4593
4594 mini_w = XWINDOW (minibuf_window);
11e82b76 4595 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657
JB
4596
4597 echo_area_glyphs = 0;
4598 previous_echo_glyphs = 0;
4599
4600 if (!noninteractive)
4601 {
44fa5b1e 4602 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
c2213350 4603 XSETFASTINT (XWINDOW (root_window)->top, 0);
44fa5b1e 4604 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
c2213350 4605 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
4606 set_window_height (minibuf_window, 1, 0);
4607
c2213350
KH
4608 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
4609 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
a2889657
JB
4610 }
4611}