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