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