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