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