(x_set_frame_parameters, x_set_menu_bar_lines, Fx_create_frame,
[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. */
641 && ((XTYPE (current_buffer->selective_display) == Lisp_Int
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
44fa5b1e 793 if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
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 {
ded34426 931 if (XTYPE (window) != Lisp_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 {
bd66d1ba 1151 /* ??? What should happen here if highlighting a region? */
a2889657
JB
1152 /* If point does not appear, move point so it does appear */
1153 pos = *compute_motion (startp, 0,
1154 ((EQ (window, minibuf_window) && startp == 1)
1155 ? minibuf_prompt_width : 0)
1156 +
1157 (hscroll ? 1 - hscroll : 0),
1158 ZV, height / 2,
1159 - (1 << (SHORTBITS - 1)),
e37f06d7 1160 width, hscroll, pos_tab_offset (w, startp), w);
f67a0f51 1161 BUF_PT (current_buffer) = pos.bufpos;
90adcf20 1162 if (w != XWINDOW (selected_window))
ae3b1442 1163 Fset_marker (w->pointm, make_number (PT), Qnil);
a2889657
JB
1164 else
1165 {
9d6a6bb9 1166 if (current_buffer == old)
ae3b1442 1167 lpoint = PT;
44fa5b1e
JB
1168 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1169 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
a2889657
JB
1170 }
1171 }
1172 goto done;
1173 }
1174
1175 /* Handle case where text has not changed, only point,
44fa5b1e 1176 and it has not moved off the frame */
a2889657
JB
1177
1178 /* This code is not used for minibuffer for the sake of
1179 the case of redisplaying to replace an echo area message;
1180 since in that case the minibuffer contents per se are usually unchanged.
1181 This code is of no real use in the minibuffer since
1182 the handling of this_line_bufpos, etc.,
1183 in redisplay handles the same cases. */
1184
1185 if (XFASTINT (w->last_modified) >= MODIFF
ae3b1442 1186 && PT >= startp && !clip_changed
44fa5b1e 1187 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
bd66d1ba
RS
1188 /* Can't use this case if highlighting a region. */
1189 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1190 && NILP (w->region_showing)
15495c73
KH
1191 /* If end pos is out of date, scroll bar and percentage will be wrong */
1192 && INTEGERP (w->window_end_vpos)
1193 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
a2889657
JB
1194 && !EQ (window, minibuf_window))
1195 {
1196 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
ae3b1442 1197 PT, height + 1, 10000, width, hscroll,
e37f06d7 1198 pos_tab_offset (w, startp), w);
a2889657
JB
1199
1200 if (pos.vpos < height)
1201 {
44fa5b1e
JB
1202 /* Ok, point is still on frame */
1203 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
a2889657
JB
1204 {
1205 /* These variables are supposed to be origin 1 */
44fa5b1e
JB
1206 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1207 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
a2889657
JB
1208 }
1209 /* This doesn't do the trick, because if a window to the right of
1210 this one must be redisplayed, this does nothing because there
44fa5b1e 1211 is nothing in DesiredFrame yet, and then the other window is
a2889657 1212 redisplayed, making likes that are empty in this window's columns.
44fa5b1e 1213 if (XFASTINT (w->width) != FRAME_WIDTH (f))
a2889657
JB
1214 preserve_my_columns (w);
1215 */
1216 goto done;
1217 }
1218 /* Don't bother trying redisplay with same start;
1219 we already know it will lose */
1220 }
1221 /* If current starting point was originally the beginning of a line
1222 but no longer is, find a new starting point. */
265a9e55 1223 else if (!NILP (w->start_at_line_beg)
b16234d8 1224 && !(startp <= BEGV
a2889657
JB
1225 || FETCH_CHAR (startp - 1) == '\n'))
1226 {
1227 goto recenter;
1228 }
1229 else if (just_this_one && !MINI_WINDOW_P (w)
ae3b1442 1230 && PT >= startp
a2889657 1231 && XFASTINT (w->last_modified)
14709f21
JB
1232 /* or else vmotion on first line won't work. */
1233 && ! NILP (w->start_at_line_beg)
a2889657
JB
1234 && ! EQ (w->window_end_valid, Qnil)
1235 && do_id && !clip_changed
1236 && !blank_end_of_window
44fa5b1e 1237 && XFASTINT (w->width) == FRAME_WIDTH (f)
bd66d1ba
RS
1238 /* Can't use this case if highlighting a region. */
1239 && !(!NILP (Vtransient_mark_mode)
1240 && !NILP (current_buffer->mark_active))
1241 && NILP (w->region_showing)
a2889657
JB
1242 && EQ (last_arrow_position, Voverlay_arrow_position)
1243 && EQ (last_arrow_string, Voverlay_arrow_string)
44fa5b1e 1244 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
a2889657
JB
1245 && tem != -2)
1246 {
1247 /* tem > 0 means success. tem == -1 means choose new start.
1248 tem == -2 means try again with same start,
1249 and nothing but whitespace follows the changed stuff.
1250 tem == 0 means try again with same start. */
1251 if (tem > 0)
1252 goto done;
1253 }
1254 else if (startp >= BEGV && startp <= ZV
1255 /* Avoid starting display at end of buffer! */
8de2d90b 1256 && (startp < ZV || startp == BEGV
a2889657
JB
1257 || (XFASTINT (w->last_modified) >= MODIFF)))
1258 {
1259 /* Try to redisplay starting at same place as before */
44fa5b1e 1260 /* If point has not moved off frame, accept the results */
a2889657
JB
1261 try_window (window, startp);
1262 if (cursor_vpos >= 0)
aa6d10fa
RS
1263 {
1264 if (!just_this_one || clip_changed || beg_unchanged < startp)
1265 /* Forget any recorded base line for line number display. */
1266 w->base_line_number = Qnil;
1267 goto done;
1268 }
a2889657
JB
1269 else
1270 cancel_my_columns (w);
1271 }
1272
1273 XFASTINT (w->last_modified) = 0;
1274 w->update_mode_line = Qt;
1275
1276 /* Try to scroll by specified few lines */
1277
1278 if (scroll_step && !clip_changed)
1279 {
ae3b1442 1280 if (PT > startp)
a2889657
JB
1281 {
1282 pos = *vmotion (Z - XFASTINT (w->window_end_pos),
1283 scroll_step, width, hscroll, window);
1284 if (pos.vpos >= height)
1285 goto scroll_fail;
1286 }
1287
ae3b1442 1288 pos = *vmotion (startp, PT < startp ? - scroll_step : scroll_step,
a2889657
JB
1289 width, hscroll, window);
1290
ae3b1442 1291 if (PT >= pos.bufpos)
a2889657
JB
1292 {
1293 try_window (window, pos.bufpos);
1294 if (cursor_vpos >= 0)
aa6d10fa
RS
1295 {
1296 if (!just_this_one || clip_changed || beg_unchanged < startp)
1297 /* Forget any recorded base line for line number display. */
1298 w->base_line_number = Qnil;
1299 goto done;
1300 }
a2889657
JB
1301 else
1302 cancel_my_columns (w);
1303 }
1304 scroll_fail: ;
1305 }
1306
1307 /* Finally, just choose place to start which centers point */
1308
1309recenter:
aa6d10fa
RS
1310 /* Forget any previously recorded base line for line number display. */
1311 w->base_line_number = Qnil;
1312
ae3b1442 1313 pos = *vmotion (PT, - (height / 2), width, hscroll, window);
a2889657
JB
1314 try_window (window, pos.bufpos);
1315
1316 startp = marker_position (w->start);
b16234d8
RS
1317 w->start_at_line_beg
1318 = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
a2889657
JB
1319
1320done:
265a9e55 1321 if ((!NILP (w->update_mode_line)
aa6d10fa
RS
1322 /* If window not full width, must redo its mode line
1323 if the window to its side is being redone */
1324 || (!just_this_one && width < FRAME_WIDTH (f) - 1)
1325 || INTEGERP (w->base_line_pos))
a2889657
JB
1326 && height != XFASTINT (w->height))
1327 display_mode_line (w);
aa6d10fa
RS
1328 if (! line_number_displayed
1329 && ! BUFFERP (w->base_line_pos))
1330 {
1331 w->base_line_pos = Qnil;
1332 w->base_line_number = Qnil;
1333 }
a2889657 1334
7ce2c095
RS
1335 /* When we reach a frame's selected window, redo the frame's menu bar. */
1336 if (!NILP (w->update_mode_line)
76412d64
RS
1337#ifdef USE_X_TOOLKIT
1338 && FRAME_EXTERNAL_MENU_BAR (f)
1339#else
7ce2c095 1340 && FRAME_MENU_BAR_LINES (f) > 0
76412d64 1341#endif
7ce2c095
RS
1342 && EQ (FRAME_SELECTED_WINDOW (f), window))
1343 display_menu_bar (w);
1344
88f22aff
JB
1345 finish_scroll_bars:
1346 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 1347 {
b1d1124b 1348 int start, end, whole;
30c566e4 1349
b1d1124b 1350 /* Calculate the start and end positions for the current window.
3505ea70
JB
1351 At some point, it would be nice to choose between scrollbars
1352 which reflect the whole buffer size, with special markers
1353 indicating narrowing, and scrollbars which reflect only the
1354 visible region.
1355
b1d1124b
JB
1356 Note that minibuffers sometimes aren't displaying any text. */
1357 if (! MINI_WINDOW_P (w)
1358 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
1359 {
8a9311d7 1360 whole = ZV - BEGV;
6887f623 1361 start = startp - BEGV;
b1d1124b
JB
1362 /* I don't think this is guaranteed to be right. For the
1363 moment, we'll pretend it is. */
85f26be9 1364 end = (Z - XINT (w->window_end_pos)) - BEGV;
3505ea70
JB
1365
1366 if (end < start) end = start;
8a9311d7 1367 if (whole < (end - start)) whole = end - start;
b1d1124b
JB
1368 }
1369 else
1370 start = end = whole = 0;
30c566e4 1371
88f22aff 1372 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 1373 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 1374
88f22aff 1375 /* Note that we actually used the scroll bar attached to this window,
30c566e4 1376 so it shouldn't be deleted at the end of redisplay. */
88f22aff 1377 (*redeem_scroll_bar_hook) (w);
30c566e4 1378 }
b1d1124b 1379
f67a0f51 1380 BUF_PT (current_buffer) = opoint;
b1d1124b 1381 current_buffer = old;
f67a0f51 1382 BUF_PT (current_buffer) = lpoint;
a2889657
JB
1383}
1384\f
1385/* Do full redisplay on one window, starting at position `pos'. */
1386
1387static void
1388try_window (window, pos)
1389 Lisp_Object window;
1390 register int pos;
1391{
1392 register struct window *w = XWINDOW (window);
1393 register int height = window_internal_height (w);
1394 register int vpos = XFASTINT (w->top);
1395 register int last_text_vpos = vpos;
1396 int tab_offset = pos_tab_offset (w, pos);
44fa5b1e 1397 FRAME_PTR f = XFRAME (w->frame);
b1d1124b 1398 int width = window_internal_width (w) - 1;
a2889657
JB
1399 struct position val;
1400
1401 Fset_marker (w->start, make_number (pos), Qnil);
1402 cursor_vpos = -1;
1403 overlay_arrow_seen = 0;
1404 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
1405
1406 while (--height >= 0)
1407 {
1408 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
1409 tab_offset += width;
1410 if (val.vpos) tab_offset = 0;
1411 vpos++;
1412 if (pos != val.bufpos)
1413 last_text_vpos
1414 /* Next line, unless prev line ended in end of buffer with no cr */
b0a0fbda 1415 = vpos - (val.vpos && (FETCH_CHAR (val.bufpos - 1) != '\n'
e885523c 1416#ifdef USE_TEXT_PROPERTIES
3ae8ced7 1417 || ! NILP (Fget_char_property (val.bufpos-1,
b0a0fbda 1418 Qinvisible,
3ae8ced7 1419 window))
e885523c
KH
1420#endif
1421 ));
a2889657
JB
1422 pos = val.bufpos;
1423 }
1424
1425 /* If last line is continued in middle of character,
44fa5b1e 1426 include the split character in the text considered on the frame */
a2889657
JB
1427 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
1428 pos++;
1429
44fa5b1e 1430 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
1431 if (XFASTINT (w->window_end_pos) == 0
1432 && Z != pos)
1433 w->update_mode_line = Qt;
1434
44fa5b1e 1435 /* Say where last char on frame will be, once redisplay is finished. */
a2889657
JB
1436 XFASTINT (w->window_end_pos) = Z - pos;
1437 XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
1438 /* But that is not valid info until redisplay finishes. */
1439 w->window_end_valid = Qnil;
1440}
1441\f
1442/* Try to redisplay when buffer is modified locally,
1443 computing insert/delete line to preserve text outside
1444 the bounds of the changes.
1445 Return 1 if successful, 0 if if cannot tell what to do,
1446 or -1 to tell caller to find a new window start,
1447 or -2 to tell caller to do normal redisplay with same window start. */
1448
1449static int
1450try_window_id (window)
1451 Lisp_Object window;
1452{
1453 int pos;
1454 register struct window *w = XWINDOW (window);
1455 register int height = window_internal_height (w);
44fa5b1e 1456 FRAME_PTR f = XFRAME (w->frame);
a2889657
JB
1457 int top = XFASTINT (w->top);
1458 int start = marker_position (w->start);
b1d1124b 1459 int width = window_internal_width (w) - 1;
a2889657
JB
1460 int hscroll = XINT (w->hscroll);
1461 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1462 register int vpos;
1463 register int i, tem;
1464 int last_text_vpos = 0;
1465 int stop_vpos;
9f412332
KH
1466 int selective
1467 = XTYPE (current_buffer->selective_display) == Lisp_Int
1468 ? XINT (current_buffer->selective_display)
1469 : !NILP (current_buffer->selective_display) ? -1 : 0;
a2889657
JB
1470
1471 struct position val, bp, ep, xp, pp;
1472 int scroll_amount = 0;
1473 int delta;
1474 int tab_offset, epto;
1475
1476 if (GPT - BEG < beg_unchanged)
1477 beg_unchanged = GPT - BEG;
1478 if (Z - GPT < end_unchanged)
1479 end_unchanged = Z - GPT;
1480
6a1dc7ac 1481 if (beg_unchanged + BEG < start)
a2889657
JB
1482 return 0; /* Give up if changes go above top of window */
1483
1484 /* Find position before which nothing is changed. */
1485 bp = *compute_motion (start, 0, lmargin,
6a1dc7ac 1486 min (ZV, beg_unchanged + BEG), height + 1, 0,
e37f06d7 1487 width, hscroll, pos_tab_offset (w, start), w);
a2889657 1488 if (bp.vpos >= height)
6e8290aa 1489 {
ae3b1442 1490 if (PT < bp.bufpos && !bp.contin)
6e8290aa 1491 {
44fa5b1e
JB
1492 /* All changes are below the frame, and point is on the frame.
1493 We don't need to change the frame at all.
6e8290aa
JB
1494 But we need to update window_end_pos to account for
1495 any change in buffer size. */
f7be7f78
JB
1496 bp = *compute_motion (start, 0, lmargin,
1497 Z, height, 0,
e37f06d7 1498 width, hscroll, pos_tab_offset (w, start), w);
6e8290aa
JB
1499 XFASTINT (w->window_end_vpos) = height;
1500 XFASTINT (w->window_end_pos) = Z - bp.bufpos;
1501 return 1;
1502 }
1503 return 0;
1504 }
a2889657
JB
1505
1506 vpos = bp.vpos;
1507
44fa5b1e 1508 /* Find beginning of that frame line. Must display from there. */
a2889657
JB
1509 bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
1510
1511 pos = bp.bufpos;
1512 val.hpos = lmargin;
1513 if (pos < start)
1514 return -1;
1515
1516 /* If about to start displaying at the beginning of a continuation line,
44fa5b1e 1517 really start with previous frame line, in case it was not
a2889657 1518 continued when last redisplayed */
05ba02eb
JB
1519 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
1520 ||
1521 /* Likewise if we have to worry about selective display. */
9f412332 1522 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
a2889657
JB
1523 {
1524 bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
1525 --vpos;
1526 pos = bp.bufpos;
1527 }
1528
1529 if (bp.contin && bp.hpos != lmargin)
1530 {
1531 val.hpos = bp.prevhpos - width + lmargin;
1532 pos--;
1533 }
1534
1535 bp.vpos = vpos;
1536
1537 /* Find first visible newline after which no more is changed. */
1538 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
9f412332
KH
1539 if (selective > 0)
1540 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
a2889657
JB
1541 tem = find_next_newline (tem, 1);
1542
1543 /* Compute the cursor position after that newline. */
1544 ep = *compute_motion (pos, vpos, val.hpos, tem,
1545 height, - (1 << (SHORTBITS - 1)),
e37f06d7 1546 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
a2889657 1547
44fa5b1e
JB
1548 /* If changes reach past the text available on the frame,
1549 just display rest of frame. */
a2889657
JB
1550 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
1551 stop_vpos = height;
1552 else
1553 stop_vpos = ep.vpos;
1554
1555 /* If no newline before ep, the line ep is on includes some changes
1556 that must be displayed. Make sure we don't stop before it. */
1557 /* Also, if changes reach all the way until ep.bufpos,
1558 it is possible that something was deleted after the
1559 newline before it, so the following line must be redrawn. */
1560 if (stop_vpos == ep.vpos
1561 && (ep.bufpos == BEGV
1562 || FETCH_CHAR (ep.bufpos - 1) != '\n'
1563 || ep.bufpos == Z - end_unchanged))
1564 stop_vpos = ep.vpos + 1;
1565
1566 cursor_vpos = -1;
1567 overlay_arrow_seen = 0;
1568
1569 /* If changes do not reach to bottom of window,
1570 figure out how much to scroll the rest of the window */
1571 if (stop_vpos < height)
1572 {
1573 /* Now determine how far up or down the rest of the window has moved */
1574 epto = pos_tab_offset (w, ep.bufpos);
1575 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
1576 Z - XFASTINT (w->window_end_pos),
e37f06d7 1577 10000, 0, width, hscroll, epto, w);
a2889657
JB
1578 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
1579
44fa5b1e 1580 /* Is everything on frame below the changes whitespace?
a2889657
JB
1581 If so, no scrolling is really necessary. */
1582 for (i = ep.bufpos; i < xp.bufpos; i++)
1583 {
1584 tem = FETCH_CHAR (i);
1585 if (tem != ' ' && tem != '\n' && tem != '\t')
1586 break;
1587 }
1588 if (i == xp.bufpos)
1589 return -2;
1590
1591 XFASTINT (w->window_end_vpos) += scroll_amount;
1592
44fa5b1e 1593 /* Before doing any scrolling, verify that point will be on frame. */
ae3b1442 1594 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
a2889657 1595 {
ae3b1442 1596 if (PT <= xp.bufpos)
a2889657
JB
1597 {
1598 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
ae3b1442 1599 PT, height, - (1 << (SHORTBITS - 1)),
e37f06d7 1600 width, hscroll, epto, w);
a2889657
JB
1601 }
1602 else
1603 {
1604 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
ae3b1442 1605 PT, height, - (1 << (SHORTBITS - 1)),
e37f06d7
KH
1606 width, hscroll,
1607 pos_tab_offset (w, xp.bufpos), w);
a2889657 1608 }
ae3b1442 1609 if (pp.bufpos < PT || pp.vpos == height)
a2889657
JB
1610 return 0;
1611 cursor_vpos = pp.vpos + top;
1612 cursor_hpos = pp.hpos + XFASTINT (w->left);
1613 }
1614
1615 if (stop_vpos - scroll_amount >= height
1616 || ep.bufpos == xp.bufpos)
1617 {
1618 if (scroll_amount < 0)
1619 stop_vpos -= scroll_amount;
1620 scroll_amount = 0;
1621 /* In this path, we have altered window_end_vpos
1622 and not left it negative.
1623 We must make sure that, in case display is preempted
44fa5b1e 1624 before the frame changes to reflect what we do here,
a2889657 1625 further updates will not come to try_window_id
44fa5b1e 1626 and assume the frame and window_end_vpos match. */
a2889657
JB
1627 blank_end_of_window = 1;
1628 }
1629 else if (!scroll_amount)
0d231165
RS
1630 {
1631 /* Even if we don't need to scroll, we must adjust the
1632 charstarts of subsequent lines (that we won't redisplay)
1633 according to the amount of text inserted or deleted. */
1634 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1635 int adjust = ep.bufpos - oldpos;
1636 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
1637 }
a2889657
JB
1638 else if (bp.bufpos == Z - end_unchanged)
1639 {
1640 /* If reprinting everything is nearly as fast as scrolling,
1641 don't bother scrolling. Can happen if lines are short. */
44fa5b1e 1642 if (scroll_cost (f, bp.vpos + top - scroll_amount,
a2889657
JB
1643 top + height - max (0, scroll_amount),
1644 scroll_amount)
1645 > xp.bufpos - bp.bufpos - 20)
1646 /* Return "try normal display with same window-start."
1647 Too bad we can't prevent further scroll-thinking. */
1648 return -2;
1649 /* If pure deletion, scroll up as many lines as possible.
1650 In common case of killing a line, this can save the
1651 following line from being overwritten by scrolling
1652 and therefore having to be redrawn. */
44fa5b1e 1653 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
d1cb44a4
RS
1654 top + height - max (0, scroll_amount),
1655 scroll_amount, bp.bufpos);
d2f84654
RS
1656 if (!tem)
1657 stop_vpos = height;
1658 else
1659 {
1660 /* scroll_frame_lines did not properly adjust subsequent
1661 lines' charstarts in the case where the text of the
1662 screen line at bp.vpos has changed.
1663 (This can happen in a deletion that ends in mid-line.)
1664 To adjust properly, we need to make things constent at
1665 the position ep.
1666 So do a second adjust to make that happen.
1667 Note that stop_vpos >= ep.vpos, so it is sufficient
1668 to update the charstarts for lines at ep.vpos and below. */
1669 int oldstart
1670 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1671 adjust_window_charstarts (w, ep.vpos + top - 1,
1672 ep.bufpos - oldstart);
1673 }
a2889657
JB
1674 }
1675 else if (scroll_amount)
1676 {
1677 /* If reprinting everything is nearly as fast as scrolling,
1678 don't bother scrolling. Can happen if lines are short. */
1679 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
1680 overestimate of cost of reprinting, since xp.bufpos
1681 would end up below the bottom of the window. */
44fa5b1e 1682 if (scroll_cost (f, ep.vpos + top - scroll_amount,
a2889657
JB
1683 top + height - max (0, scroll_amount),
1684 scroll_amount)
1685 > xp.bufpos - ep.bufpos - 20)
1686 /* Return "try normal display with same window-start."
1687 Too bad we can't prevent further scroll-thinking. */
1688 return -2;
44fa5b1e 1689 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
a2889657 1690 top + height - max (0, scroll_amount),
d1cb44a4 1691 scroll_amount, ep.bufpos);
a2889657
JB
1692 if (!tem) stop_vpos = height;
1693 }
1694 }
1695
1696 /* In any case, do not display past bottom of window */
1697 if (stop_vpos >= height)
1698 {
1699 stop_vpos = height;
1700 scroll_amount = 0;
1701 }
1702
1703 /* Handle case where pos is before w->start --
1704 can happen if part of line had been clipped and is not clipped now */
1705 if (vpos == 0 && pos < marker_position (w->start))
1706 Fset_marker (w->start, make_number (pos), Qnil);
1707
1708 /* Redisplay the lines where the text was changed */
1709 last_text_vpos = vpos;
1710 tab_offset = pos_tab_offset (w, pos);
1711 /* If we are starting display in mid-character, correct tab_offset
1712 to account for passing the line that that character really starts in. */
1713 if (val.hpos < lmargin)
1714 tab_offset += width;
1715 while (vpos < stop_vpos)
1716 {
1717 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1718 tab_offset += width;
1719 if (val.vpos) tab_offset = 0;
1720 if (pos != val.bufpos)
1721 last_text_vpos
1722 /* Next line, unless prev line ended in end of buffer with no cr */
1723 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
1724 pos = val.bufpos;
1725 }
1726
1727 /* There are two cases:
1728 1) we have displayed down to the bottom of the window
1729 2) we have scrolled lines below stop_vpos by scroll_amount */
1730
1731 if (vpos == height)
1732 {
1733 /* If last line is continued in middle of character,
44fa5b1e 1734 include the split character in the text considered on the frame */
a2889657
JB
1735 if (val.hpos < lmargin)
1736 val.bufpos++;
1737 XFASTINT (w->window_end_vpos) = last_text_vpos;
1738 XFASTINT (w->window_end_pos) = Z - val.bufpos;
1739 }
1740
1741 /* If scrolling made blank lines at window bottom,
1742 redisplay to fill those lines */
1743 if (scroll_amount < 0)
1744 {
1745 /* Don't consider these lines for general-purpose scrolling.
1746 That will save time in the scrolling computation. */
44fa5b1e 1747 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
a2889657
JB
1748 vpos = xp.vpos;
1749 pos = xp.bufpos;
1750 val.hpos = lmargin;
1751 if (pos == ZV)
1752 vpos = height + scroll_amount;
1753 else if (xp.contin && xp.hpos != lmargin)
1754 {
1755 val.hpos = xp.prevhpos - width + lmargin;
1756 pos--;
1757 }
1758
1759 blank_end_of_window = 1;
1760 tab_offset = pos_tab_offset (w, pos);
1761 /* If we are starting display in mid-character, correct tab_offset
1762 to account for passing the line that that character starts in. */
1763 if (val.hpos < lmargin)
1764 tab_offset += width;
1765
1766 while (vpos < height)
1767 {
1768 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1769 tab_offset += width;
1770 if (val.vpos) tab_offset = 0;
1771 pos = val.bufpos;
1772 }
1773
1774 /* Here is a case where display_text_line sets cursor_vpos wrong.
1775 Make it be fixed up, below. */
1776 if (xp.bufpos == ZV
ae3b1442 1777 && xp.bufpos == PT)
a2889657
JB
1778 cursor_vpos = -1;
1779 }
1780
44fa5b1e 1781 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
1782 if (XFASTINT (w->window_end_pos) == 0
1783 && Z != val.bufpos)
1784 w->update_mode_line = Qt;
1785
1786 /* Attempt to adjust end-of-text positions to new bottom line */
1787 if (scroll_amount)
1788 {
1789 delta = height - xp.vpos;
1790 if (delta < 0
1791 || (delta > 0 && xp.bufpos <= ZV)
1792 || (delta == 0 && xp.hpos))
1793 {
1794 val = *vmotion (Z - XFASTINT (w->window_end_pos),
1795 delta, width, hscroll, window);
1796 XFASTINT (w->window_end_pos) = Z - val.bufpos;
1797 XFASTINT (w->window_end_vpos) += val.vpos;
1798 }
1799 }
1800
1801 w->window_end_valid = Qnil;
1802
1803 /* If point was not in a line that was displayed, find it */
1804 if (cursor_vpos < 0)
1805 {
ae3b1442 1806 val = *compute_motion (start, 0, lmargin, PT, 10000, 10000,
e37f06d7 1807 width, hscroll, pos_tab_offset (w, start), w);
44fa5b1e 1808 /* Admit failure if point is off frame now */
a2889657
JB
1809 if (val.vpos >= height)
1810 {
1811 for (vpos = 0; vpos < height; vpos++)
44fa5b1e 1812 cancel_line (vpos + top, f);
a2889657
JB
1813 return 0;
1814 }
1815 cursor_vpos = val.vpos + top;
1816 cursor_hpos = val.hpos + XFASTINT (w->left);
1817 }
1818
44fa5b1e
JB
1819 FRAME_CURSOR_X (f) = max (0, cursor_hpos);
1820 FRAME_CURSOR_Y (f) = cursor_vpos;
a2889657
JB
1821
1822 if (debug_end_pos)
1823 {
1824 val = *compute_motion (start, 0, lmargin, ZV,
1825 height, - (1 << (SHORTBITS - 1)),
e37f06d7 1826 width, hscroll, pos_tab_offset (w, start), w);
a2889657
JB
1827 if (val.vpos != XFASTINT (w->window_end_vpos))
1828 abort ();
1829 if (XFASTINT (w->window_end_pos)
1830 != Z - val.bufpos)
1831 abort ();
1832 }
1833
1834 return 1;
1835}
1836\f
31b24551
JB
1837/* Mark a section of BUF as modified, but only for the sake of redisplay.
1838 This is useful for recording changes to overlays.
1839
1840 We increment the buffer's modification timestamp and set the
1841 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
1842 as if the region of text between START and END had been modified;
1843 the redisplay code will check this against the windows' timestamps,
1844 and redraw the appropriate area of the buffer.
1845
1846 However, if the buffer is unmodified, we bump the last-save
1847 timestamp as well, so that incrementing the timestamp doesn't fool
1848 Emacs into thinking that the buffer's text has been modified.
1849
1850 Tweaking the timestamps shouldn't hurt the first-modification
1851 timestamps recorded in the undo records; those values aren't
1852 written until just before a real text modification is made, so they
1853 will never catch the timestamp value just before this function gets
1854 called. */
1855
1856void
1857redisplay_region (buf, start, end)
1858 struct buffer *buf;
1859 int start, end;
1860{
1861 if (start == end)
1862 return;
1863
1864 if (start > end)
1865 {
1866 int temp = start;
1867 start = end; end = temp;
1868 }
1869
70bcb498
RS
1870 /* If this is a buffer not in the selected window,
1871 we must do other windows. */
1872 if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
1873 windows_or_buffers_changed = 1;
99b9e975
RS
1874 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
1875 else if (buf != current_buffer)
1876 windows_or_buffers_changed = 1;
70bcb498
RS
1877 /* If multiple windows show this buffer, we must do other windows. */
1878 else if (buffer_shared > 1)
31b24551
JB
1879 windows_or_buffers_changed = 1;
1880 else
1881 {
1882 if (unchanged_modified == MODIFF)
1883 {
1884 beg_unchanged = start - BEG;
1885 end_unchanged = Z - end;
1886 }
1887 else
1888 {
1889 if (Z - end < end_unchanged)
1890 end_unchanged = Z - end;
1891 if (start - BEG < beg_unchanged)
1892 beg_unchanged = start - BEG;
1893 }
1894 }
1895
1896 /* Increment the buffer's time stamp, but also increment the save
1897 and autosave timestamps, so as not to screw up that timekeeping. */
1898 if (BUF_MODIFF (buf) == buf->save_modified)
1899 buf->save_modified++;
1900 if (BUF_MODIFF (buf) == buf->auto_save_modified)
1901 buf->auto_save_modified++;
1902
1903 BUF_MODIFF (buf) ++;
1904}
1905
1906\f
278feba9 1907/* Copy LEN glyphs starting address FROM to the rope TO.
f7430cb6 1908 But don't actually copy the parts that would come in before S.
278feba9
RS
1909 Value is TO, advanced past the copied data.
1910 F is the frame we are displaying in. */
a2889657 1911
278feba9
RS
1912static GLYPH *
1913copy_part_of_rope (f, to, s, from, len, face)
1914 FRAME_PTR f;
1915 register GLYPH *to; /* Copy to here. */
a2889657 1916 register GLYPH *s; /* Starting point. */
278feba9
RS
1917 Lisp_Object *from; /* Data to copy. */
1918 int len;
1c2250c2 1919 int face; /* Face to apply to glyphs which don't specify one. */
a2889657 1920{
278feba9
RS
1921 int n = len;
1922 register Lisp_Object *fp = from;
1923 /* These cache the results of the last call to compute_glyph_face. */
1924 int last_code = -1;
1925 int last_merged = 0;
c581d710 1926
4cdc65eb
KH
1927#ifdef HAVE_X_WINDOWS
1928 if (! FRAME_TERMCAP_P (f))
1929 while (n--)
1930 {
dedd1182 1931 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb
KH
1932 int facecode;
1933
1934 if (FAST_GLYPH_FACE (glyph) == 0)
1935 /* If GLYPH has no face code, use FACE. */
1936 facecode = face;
1937 else if (FAST_GLYPH_FACE (glyph) == last_code)
1938 /* If it's same as previous glyph, use same result. */
1939 facecode = last_merged;
1940 else
1941 {
1942 /* Merge this glyph's face and remember the result. */
1943 last_code = FAST_GLYPH_FACE (glyph);
1944 last_merged = facecode = compute_glyph_face (f, last_code, face);
1945 }
b2a76982 1946
4cdc65eb
KH
1947 if (to >= s)
1948 *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
1949 ++to;
1950 ++fp;
1951 }
1952 else
1953#endif
1954 while (n--)
1955 {
dedd1182 1956 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb
KH
1957 ++to;
1958 ++fp;
1959 }
278feba9 1960 return to;
c581d710
RS
1961}
1962
278feba9
RS
1963/* Correct a glyph by replacing its specified user-level face code
1964 with a displayable computed face code. */
c581d710 1965
278feba9 1966static GLYPH
659a218f 1967fix_glyph (f, glyph, cface)
278feba9
RS
1968 FRAME_PTR f;
1969 GLYPH glyph;
659a218f 1970 int cface;
c581d710 1971{
4cdc65eb 1972#ifdef HAVE_X_WINDOWS
659a218f
KH
1973 if (! FRAME_TERMCAP_P (f))
1974 {
1975 if (FAST_GLYPH_FACE (glyph) != 0)
1976 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
1977 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
1978 }
4cdc65eb
KH
1979#endif
1980 return glyph;
a2889657
JB
1981}
1982\f
1983/* Display one line of window w, starting at position START in W's buffer.
1984 Display starting at horizontal position HPOS, which is normally zero
1985 or negative. A negative value causes output up to hpos = 0 to be discarded.
1986 This is done for negative hscroll, or when this is a continuation line
1987 and the continuation occurred in the middle of a multi-column character.
1988
1989 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
1990
44fa5b1e 1991 Display on position VPOS on the frame. (origin 0).
a2889657
JB
1992
1993 Returns a STRUCT POSITION giving character to start next line with
1994 and where to display it, including a zero or negative hpos.
1995 The vpos field is not really a vpos; it is 1 unless the line is continued */
1996
1997struct position val_display_text_line;
1998
1999static struct position *
2000display_text_line (w, start, vpos, hpos, taboffset)
2001 struct window *w;
2002 int start;
2003 int vpos;
2004 int hpos;
2005 int taboffset;
2006{
2007 register int pos = start;
2008 register int c;
2009 register GLYPH *p1;
2010 int end;
2011 register int pause;
2012 register unsigned char *p;
2013 GLYPH *endp;
d2f84654 2014 register GLYPH *leftmargin;
5fcbb24d 2015 register GLYPH *p1prev = 0;
efc63ef0
RS
2016 register GLYPH *p1start;
2017 int *charstart;
44fa5b1e 2018 FRAME_PTR f = XFRAME (w->frame);
a2889657 2019 int tab_width = XINT (current_buffer->tab_width);
265a9e55 2020 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
b1d1124b 2021 int width = window_internal_width (w) - 1;
a2889657
JB
2022 struct position val;
2023 int lastpos;
2024 int invis;
2025 int hscroll = XINT (w->hscroll);
d2f84654
RS
2026 int truncate = (hscroll
2027 || (truncate_partial_width_windows
2028 && XFASTINT (w->width) < FRAME_WIDTH (f))
2029 || !NILP (current_buffer->truncate_lines));
bd66d1ba
RS
2030
2031 /* 1 if we should highlight the region. */
2032 int highlight_region
2033 = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
2034 int region_beg, region_end;
2035
a2889657
JB
2036 int selective
2037 = XTYPE (current_buffer->selective_display) == Lisp_Int
2038 ? XINT (current_buffer->selective_display)
265a9e55 2039 : !NILP (current_buffer->selective_display) ? -1 : 0;
44fa5b1e 2040 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
a2889657 2041 register struct Lisp_Vector *dp = window_display_table (w);
68a37fa8
RS
2042
2043 Lisp_Object default_invis_vector[3];
2044 /* Nonzero means display something where there are invisible lines.
2045 The precise value is the number of glyphs to display. */
a2889657 2046 int selective_rlen
c581d710 2047 = (selective && dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
68a37fa8
RS
2048 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
2049 : selective && !NILP (current_buffer->selective_display_ellipses)
2050 ? 3 : 0);
2051 /* This is the sequence of Lisp objects to display
2052 when there are invisible lines. */
2053 Lisp_Object *invis_vector_contents
2054 = (dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
2055 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2056 : default_invis_vector);
2057
a2889657 2058 GLYPH truncator = (dp == 0 || XTYPE (DISP_TRUNC_GLYPH (dp)) != Lisp_Int
278feba9 2059 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
a2889657 2060 GLYPH continuer = (dp == 0 || XTYPE (DISP_CONTINUE_GLYPH (dp)) != Lisp_Int
278feba9 2061 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
a2889657 2062
31b24551
JB
2063 /* The next buffer location at which the face should change, due
2064 to overlays or text property changes. */
2065 int next_face_change;
2066
b0a0fbda
RS
2067#ifdef USE_TEXT_PROPERTIES
2068 /* The next location where the `invisible' property changes */
2069 int next_invisible;
b0a0fbda
RS
2070#endif
2071
31b24551 2072 /* The face we're currently using. */
1c2250c2 2073 int current_face = 0;
efc63ef0 2074 int i;
31b24551 2075
68a37fa8
RS
2076 XFASTINT (default_invis_vector[2]) = '.';
2077 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2078
a2889657 2079 hpos += XFASTINT (w->left);
44fa5b1e 2080 get_display_line (f, vpos, XFASTINT (w->left));
54ff581a 2081 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657 2082
bd66d1ba 2083 /* Show where to highlight the region. */
1613b757 2084 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
fba9ce76
RS
2085 /* Maybe highlight only in selected window. */
2086 && (highlight_nonselected_windows
6f139a45 2087 || w == XWINDOW (selected_window)))
bd66d1ba
RS
2088 {
2089 region_beg = marker_position (current_buffer->mark);
2090 if (PT < region_beg)
2091 {
2092 region_end = region_beg;
2093 region_beg = PT;
2094 }
2095 else
2096 region_end = PT;
2097 w->region_showing = Qt;
2098 }
2099 else
2100 region_beg = region_end = -1;
2101
a2889657
JB
2102 if (MINI_WINDOW_P (w) && start == 1
2103 && vpos == XFASTINT (w->top))
2104 {
8c5b6a0a 2105 if (! NILP (minibuf_prompt))
f7b4b63a
KH
2106 {
2107 minibuf_prompt_width
8c5b6a0a
KH
2108 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2109 XSTRING (minibuf_prompt)->size, hpos,
a2889657 2110 (!truncate ? continuer : truncator),
f7b4b63a
KH
2111 1, -1, -1)
2112 - hpos);
2113 hpos += minibuf_prompt_width;
2114 }
2115 else
2116 minibuf_prompt_width = 0;
a2889657
JB
2117 }
2118
2119 desired_glyphs->bufp[vpos] = pos;
2120 p1 = desired_glyphs->glyphs[vpos] + hpos;
efc63ef0
RS
2121 p1start = p1;
2122 charstart = desired_glyphs->charstarts[vpos] + hpos;
2123 /* In case we don't ever write anything into it... */
a007eef6 2124 desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
a2889657 2125 end = ZV;
d2f84654
RS
2126 leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
2127 endp = leftmargin + width;
a2889657 2128
1c2250c2
JB
2129 /* Arrange the overlays nicely for our purposes. Usually, we call
2130 display_text_line on only one line at a time, in which case this
2131 can't really hurt too much, or we call it on lines which appear
2132 one after another in the buffer, in which case all calls to
2133 recenter_overlay_lists but the first will be pretty cheap. */
2134 recenter_overlay_lists (current_buffer, pos);
2135
a2889657
JB
2136 /* Loop generating characters.
2137 Stop at end of buffer, before newline,
31b24551
JB
2138 if reach or pass continuation column,
2139 or at face change. */
a2889657 2140 pause = pos;
31b24551 2141 next_face_change = pos;
b0a0fbda
RS
2142#ifdef USE_TEXT_PROPERTIES
2143 next_invisible = pos;
2144#endif
85bcef6c 2145 while (1)
a2889657 2146 {
efc63ef0
RS
2147 /* Record which glyph starts a character,
2148 and the character position of that character. */
d2f84654 2149 if (p1 >= leftmargin)
853cf346 2150 charstart[p1 - p1start] = pos;
efc63ef0 2151
85bcef6c
RS
2152 if (p1 >= endp)
2153 break;
2154
a2889657 2155 p1prev = p1;
31b24551 2156 if (pos >= pause)
a2889657 2157 {
31b24551
JB
2158 /* Did we hit the end of the visible region of the buffer?
2159 Stop here. */
2160 if (pos >= end)
a2889657 2161 break;
31b24551
JB
2162
2163 /* Did we reach point? Record the cursor location. */
ae3b1442 2164 if (pos == PT && cursor_vpos < 0)
a2889657
JB
2165 {
2166 cursor_vpos = vpos;
d2f84654 2167 cursor_hpos = p1 - leftmargin;
a2889657
JB
2168 }
2169
b0a0fbda
RS
2170#ifdef USE_TEXT_PROPERTIES
2171 /* if the `invisible' property is set to t, we can skip to
2172 the next property change */
2173 while (pos == next_invisible && pos < end)
b0a0fbda 2174 {
3ae8ced7 2175 Lisp_Object position, limit, endpos, prop, ww;
dfabd9a0 2176 XFASTINT (position) = pos;
3ae8ced7
KH
2177 XSET (ww, Lisp_Window, w);
2178 prop = Fget_char_property (position, Qinvisible, ww);
dfabd9a0
RS
2179 /* This is just an estimate to give reasonable
2180 performance; nothing should go wrong if it is too small. */
fe3d6921
KH
2181 limit = Fnext_overlay_change (position);
2182 if (XFASTINT (limit) > pos + 50)
2183 XFASTINT (limit) = pos + 50;
2184 endpos = Fnext_single_property_change (position, Qinvisible,
dfabd9a0
RS
2185 Fcurrent_buffer (), limit);
2186 if (INTEGERP (endpos))
2187 next_invisible = XINT (endpos);
2188 else
2189 next_invisible = end;
2190 if (! NILP (prop))
2191 {
ae3b1442 2192 if (pos < PT && next_invisible >= PT)
dfabd9a0
RS
2193 {
2194 cursor_vpos = vpos;
d2f84654 2195 cursor_hpos = p1 - leftmargin;
dfabd9a0
RS
2196 }
2197 pos = next_invisible;
2198 }
b0a0fbda 2199 }
b0a0fbda
RS
2200 if (pos >= end)
2201 break;
2202#endif
2203
9dbd4b48 2204#ifdef HAVE_X_WINDOWS
31b24551
JB
2205 /* Did we hit a face change? Figure out what face we should
2206 use now. We also hit this the first time through the
2207 loop, to see what face we should start with. */
b0a0fbda 2208 if (pos >= next_face_change && FRAME_X_P (f))
bd66d1ba
RS
2209 current_face = compute_char_face (f, w, pos,
2210 region_beg, region_end,
efc63ef0 2211 &next_face_change, pos + 50, 0);
9dbd4b48 2212#endif
31b24551 2213
1c2250c2
JB
2214 pause = end;
2215
b0a0fbda
RS
2216#ifdef USE_TEXT_PROPERTIES
2217 if (pos < next_invisible && next_invisible < pause)
2218 pause = next_invisible;
2219#endif
1c2250c2
JB
2220 if (pos < next_face_change && next_face_change < pause)
2221 pause = next_face_change;
2222
31b24551
JB
2223 /* Wouldn't you hate to read the next line to someone over
2224 the phone? */
ae3b1442
KH
2225 if (pos < PT && PT < pause)
2226 pause = PT;
a2889657
JB
2227 if (pos < GPT && GPT < pause)
2228 pause = GPT;
2229
2230 p = &FETCH_CHAR (pos);
2231 }
2232 c = *p++;
2233 if (c >= 040 && c < 0177
c581d710 2234 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
a2889657 2235 {
d2f84654 2236 if (p1 >= leftmargin)
4cdc65eb 2237 *p1 = MAKE_GLYPH (f, c, current_face);
a2889657
JB
2238 p1++;
2239 }
2240 else if (c == '\n')
2241 {
2242 invis = 0;
d6f08da4 2243 while (pos + 1 < end
a2889657 2244 && selective > 0
9f412332 2245 && indented_beyond_p (pos + 1, selective))
a2889657
JB
2246 {
2247 invis = 1;
2248 pos = find_next_newline (pos + 1, 1);
2249 if (FETCH_CHAR (pos - 1) == '\n')
2250 pos--;
2251 }
d2f84654 2252 if (invis && selective_rlen > 0 && p1 >= leftmargin)
a2889657
JB
2253 {
2254 p1 += selective_rlen;
d2f84654 2255 if (p1 - leftmargin > width)
a2889657 2256 p1 = endp;
278feba9 2257 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c2250c2 2258 (p1 - p1prev), current_face);
a2889657 2259 }
4cdc65eb 2260#ifdef HAVE_X_WINDOWS
3c5c35c5
JB
2261 /* Draw the face of the newline character as extending all the
2262 way to the end of the frame line. */
2263 if (current_face)
1105ff20
KH
2264 {
2265 if (p1 < leftmargin)
2266 p1 = leftmargin;
2267 while (p1 < endp)
2268 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2269 }
3c5c35c5 2270#endif
68a37fa8 2271 break;
a2889657
JB
2272 }
2273 else if (c == '\t')
2274 {
2275 do
2276 {
d2f84654 2277 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2278 *p1 = MAKE_GLYPH (f, ' ', current_face);
a2889657
JB
2279 p1++;
2280 }
d2f84654 2281 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
a2889657
JB
2282 % tab_width);
2283 }
6e8290aa 2284 else if (c == Ctl ('M') && selective == -1)
a2889657
JB
2285 {
2286 pos = find_next_newline (pos, 1);
2287 if (FETCH_CHAR (pos - 1) == '\n')
2288 pos--;
2289 if (selective_rlen > 0)
2290 {
2291 p1 += selective_rlen;
d2f84654 2292 if (p1 - leftmargin > width)
a2889657 2293 p1 = endp;
278feba9 2294 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c2250c2 2295 (p1 - p1prev), current_face);
a2889657 2296 }
4cdc65eb 2297#ifdef HAVE_X_WINDOWS
3c5c35c5
JB
2298 /* Draw the face of the newline character as extending all the
2299 way to the end of the frame line. */
2300 if (current_face)
1105ff20
KH
2301 {
2302 if (p1 < leftmargin)
2303 p1 = leftmargin;
2304 while (p1 < endp)
2305 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2306 }
3c5c35c5 2307#endif
68a37fa8 2308 break;
a2889657 2309 }
c581d710 2310 else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
a2889657 2311 {
d2f84654 2312 p1 = copy_part_of_rope (f, p1, leftmargin,
278feba9
RS
2313 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
2314 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
2315 current_face);
a2889657
JB
2316 }
2317 else if (c < 0200 && ctl_arrow)
2318 {
d2f84654 2319 if (p1 >= leftmargin)
278feba9
RS
2320 *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
2321 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
2322 current_face);
a2889657 2323 p1++;
d2f84654 2324 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2325 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
a2889657
JB
2326 p1++;
2327 }
2328 else
2329 {
d2f84654 2330 if (p1 >= leftmargin)
278feba9
RS
2331 *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
2332 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
2333 current_face);
a2889657 2334 p1++;
d2f84654 2335 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2336 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
a2889657 2337 p1++;
d2f84654 2338 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2339 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
a2889657 2340 p1++;
d2f84654 2341 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2342 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
a2889657
JB
2343 p1++;
2344 }
31b24551 2345
853cf346 2346 /* Do nothing here for a char that's entirely off the left edge. */
d2f84654 2347 if (p1 >= leftmargin)
efc63ef0 2348 {
853cf346
RS
2349 /* For all the glyphs occupied by this character, except for the
2350 first, store -1 in charstarts. */
2351 if (p1 != p1prev)
2352 {
2353 int *p2x = &charstart[p1prev - p1start];
125138e2 2354 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
853cf346
RS
2355
2356 /* The window's left column should always
2357 contain a character position.
2358 And don't clobber anything to the left of that. */
d2f84654 2359 if (p1prev < leftmargin)
853cf346 2360 {
a007eef6
RS
2361 p2x = charstart + (leftmargin - p1start);
2362 *p2x = pos;
853cf346
RS
2363 }
2364
2365 /* This loop skips over the char p2x initially points to. */
a007eef6 2366 while (++p2x < p2)
853cf346
RS
2367 *p2x = -1;
2368 }
efc63ef0 2369 }
853cf346 2370
a2889657
JB
2371 pos++;
2372 }
2373
2374 val.hpos = - XINT (w->hscroll);
2375 if (val.hpos)
2376 val.hpos++;
2377
2378 val.vpos = 1;
2379
2380 lastpos = pos;
2381
efc63ef0
RS
2382 /* Store 0 in this charstart line for the positions where
2383 there is no character. But do leave what was recorded
2384 for the character that ended the line. */
85bcef6c
RS
2385 /* Add 1 in the endtest to compensate for the fact that ENDP was
2386 made from WIDTH, which is 1 less than the window's actual
2387 internal width. */
a007eef6
RS
2388 i = p1 - p1start + 1;
2389 if (p1 < leftmargin)
2390 i += leftmargin - p1;
2391 for (; i < endp - p1start + 1; i++)
efc63ef0
RS
2392 charstart[i] = 0;
2393
a2889657
JB
2394 /* Handle continuation in middle of a character */
2395 /* by backing up over it */
2396 if (p1 > endp)
2397 {
5fcbb24d
JB
2398 /* Don't back up if we never actually displayed any text.
2399 This occurs when the minibuffer prompt takes up the whole line. */
2400 if (p1prev)
2401 {
2402 /* Start the next line with that same character */
2403 pos--;
2404 /* but at negative hpos, to skip the columns output on this line. */
2405 val.hpos += p1prev - endp;
2406 }
2407
a2889657
JB
2408 /* Keep in this line everything up to the continuation column. */
2409 p1 = endp;
2410 }
2411
2412 /* Finish deciding which character to start the next line on,
2413 and what hpos to start it at.
2414 Also set `lastpos' to the last position which counts as "on this line"
2415 for cursor-positioning. */
2416
2417 if (pos < ZV)
2418 {
2419 if (FETCH_CHAR (pos) == '\n')
dd5f6267
KH
2420 {
2421 /* If stopped due to a newline, start next line after it */
2422 pos++;
2423 /* Check again for hidden lines, in case the newline occurred exactly
2424 at the right margin. */
2425 while (pos < ZV && selective > 0
2426 && indented_beyond_p (pos, selective))
2427 pos = find_next_newline (pos, 1);
2428 }
a2889657
JB
2429 else
2430 /* Stopped due to right margin of window */
2431 {
2432 if (truncate)
2433 {
278feba9 2434 *p1++ = fix_glyph (f, truncator, 0);
a2889657
JB
2435 /* Truncating => start next line after next newline,
2436 and point is on this line if it is before the newline,
2437 and skip none of first char of next line */
dd5f6267
KH
2438 do
2439 pos = find_next_newline (pos, 1);
2440 while (pos < ZV && selective > 0
2441 && indented_beyond_p (pos, selective));
a2889657
JB
2442 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
2443
2444 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
2445 }
2446 else
2447 {
278feba9 2448 *p1++ = fix_glyph (f, continuer, 0);
a2889657
JB
2449 val.vpos = 0;
2450 lastpos--;
2451 }
2452 }
2453 }
2454
2455 /* If point is at eol or in invisible text at eol,
44fa5b1e 2456 record its frame location now. */
a2889657 2457
ae3b1442 2458 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
a2889657
JB
2459 {
2460 cursor_vpos = vpos;
d2f84654 2461 cursor_hpos = p1 - leftmargin;
a2889657
JB
2462 }
2463
2464 if (cursor_vpos == vpos)
2465 {
2466 if (cursor_hpos < 0) cursor_hpos = 0;
2467 if (cursor_hpos > width) cursor_hpos = width;
2468 cursor_hpos += XFASTINT (w->left);
44fa5b1e 2469 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
a2889657 2470 {
44fa5b1e
JB
2471 FRAME_CURSOR_Y (f) = cursor_vpos;
2472 FRAME_CURSOR_X (f) = cursor_hpos;
a2889657
JB
2473
2474 if (w == XWINDOW (selected_window))
2475 {
2476 /* Line is not continued and did not start
2477 in middle of character */
2478 if ((hpos - XFASTINT (w->left)
2479 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
2480 && val.vpos)
2481 {
2482 this_line_bufpos = start;
2483 this_line_buffer = current_buffer;
2484 this_line_vpos = cursor_vpos;
2485 this_line_start_hpos = hpos;
2486 this_line_endpos = Z - lastpos;
2487 }
2488 else
2489 this_line_bufpos = 0;
2490 }
2491 }
2492 }
2493
2494 /* If hscroll and line not empty, insert truncation-at-left marker */
2495 if (hscroll && lastpos != start)
2496 {
d2f84654
RS
2497 *leftmargin = fix_glyph (f, truncator, 0);
2498 if (p1 <= leftmargin)
2499 p1 = leftmargin + 1;
a2889657
JB
2500 }
2501
44fa5b1e 2502 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f))
a2889657
JB
2503 {
2504 endp++;
d2f84654 2505 if (p1 < leftmargin) p1 = leftmargin;
a2889657 2506 while (p1 < endp) *p1++ = SPACEGLYPH;
b1d1124b 2507
88f22aff
JB
2508 /* Don't draw vertical bars if we're using scroll bars. They're
2509 covered up by the scroll bars, and it's distracting to see
2510 them when the scroll bar windows are flickering around to be
b1d1124b 2511 reconfigured. */
88f22aff 2512 *p1++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
a45e35e1
JB
2513 ? ' '
2514 : (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
2515 ? DISP_BORDER_GLYPH (dp)
2516 : '|'));
a2889657
JB
2517 }
2518 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
2519 p1 - desired_glyphs->glyphs[vpos]);
2520 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
2521
2522 /* If the start of this line is the overlay arrow-position,
2523 then put the arrow string into the display-line. */
2524
2525 if (XTYPE (Voverlay_arrow_position) == Lisp_Marker
2526 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
2527 && start == marker_position (Voverlay_arrow_position)
2528 && XTYPE (Voverlay_arrow_string) == Lisp_String
2529 && ! overlay_arrow_seen)
2530 {
2531 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
2532 int i;
2533 int len = XSTRING (Voverlay_arrow_string)->size;
142be3dd 2534 int arrow_end;
a2889657 2535
b1d1124b
JB
2536 if (len > width)
2537 len = width;
b4718ffa 2538#ifdef HAVE_X_WINDOWS
c4628384
RS
2539 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
2540 {
2541 /* If the arrow string has text props, obey them when displaying. */
2542 for (i = 0; i < len; i++)
2543 {
2544 int c = p[i];
2545 Lisp_Object face, ilisp;
2546 int newface;
2547
2548 XFASTINT (ilisp) = i;
2549 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
2550 newface = compute_glyph_face_1 (f, face, 0);
2551 leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
2552 }
2553 }
2554 else
b4718ffa 2555#endif /* HAVE_X_WINDOWS */
c4628384
RS
2556 {
2557 for (i = 0; i < len; i++)
2558 leftmargin[i] = p[i];
2559 }
142be3dd
JB
2560
2561 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
d2f84654 2562 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
142be3dd
JB
2563 if (desired_glyphs->used[vpos] < arrow_end)
2564 desired_glyphs->used[vpos] = arrow_end;
a2889657
JB
2565
2566 overlay_arrow_seen = 1;
2567 }
2568
2569 val.bufpos = pos;
2570 val_display_text_line = val;
2571 return &val_display_text_line;
2572}
2573\f
7ce2c095
RS
2574/* Redisplay the menu bar in the frame for window W. */
2575
2576static void
2577display_menu_bar (w)
2578 struct window *w;
2579{
2580 Lisp_Object items, tail;
2581 register int vpos = 0;
2582 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2583 int maxendcol = FRAME_WIDTH (f);
2584 int hpos = 0;
8351baf2 2585 int i;
7ce2c095 2586
76412d64 2587#ifndef USE_X_TOOLKIT
7ce2c095
RS
2588 if (FRAME_MENU_BAR_LINES (f) <= 0)
2589 return;
2590
2591 get_display_line (f, vpos, 0);
2592
8351baf2
RS
2593 items = FRAME_MENU_BAR_ITEMS (f);
2594 for (i = 0; i < XVECTOR (items)->size; i += 3)
7ce2c095 2595 {
8351baf2
RS
2596 Lisp_Object pos, string;
2597 string = XVECTOR (items)->contents[i + 1];
2598 if (NILP (string))
2599 break;
2d66ad19 2600
8351baf2 2601 XFASTINT (XVECTOR (items)->contents[i + 2]) = hpos;
7ce2c095
RS
2602
2603 if (hpos < maxendcol)
2604 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
2605 XSTRING (string)->data,
90adcf20 2606 XSTRING (string)->size,
278feba9 2607 hpos, 0, 0, hpos, maxendcol);
2d66ad19
RS
2608 /* Put a gap of 3 spaces between items. */
2609 if (hpos < maxendcol)
2610 {
2611 int hpos1 = hpos + 3;
278feba9 2612 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
2d66ad19
RS
2613 min (hpos1, maxendcol), maxendcol);
2614 }
7ce2c095
RS
2615 }
2616
2617 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
2618 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2d66ad19
RS
2619
2620 /* Fill out the line with spaces. */
2621 if (maxendcol > hpos)
278feba9 2622 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
db6f348c
JB
2623
2624 /* Clear the rest of the lines allocated to the menu bar. */
2625 vpos++;
2626 while (vpos < FRAME_MENU_BAR_LINES (f))
2627 get_display_line (f, vpos++, 0);
76412d64 2628#endif /* not USE_X_TOOLKIT */
7ce2c095
RS
2629}
2630\f
a2889657
JB
2631/* Display the mode line for window w */
2632
2633static void
2634display_mode_line (w)
2635 struct window *w;
2636{
2637 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
2638 register int left = XFASTINT (w->left);
2639 register int right = XFASTINT (w->width) + left;
44fa5b1e 2640 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
a2889657 2641
aa6d10fa
RS
2642 line_number_displayed = 0;
2643
44fa5b1e 2644 get_display_line (f, vpos, left);
a2889657
JB
2645 display_mode_element (w, vpos, left, 0, right, right,
2646 current_buffer->mode_line_format);
44fa5b1e 2647 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
a2889657
JB
2648
2649 /* Make the mode line inverse video if the entire line
2650 is made of mode lines.
2651 I.e. if this window is full width,
2652 or if it is the child of a full width window
2653 (which implies that that window is split side-by-side
2654 and the rest of this line is mode lines of the sibling windows). */
44fa5b1e
JB
2655 if (XFASTINT (w->width) == FRAME_WIDTH (f)
2656 || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
2657 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
4cdc65eb 2658#ifdef HAVE_X_WINDOWS
d7eb09a0
RS
2659 else if (! FRAME_TERMCAP_P (f))
2660 {
2661 /* For a partial width window, explicitly set face of each glyph. */
2662 int i;
2663 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
2664 for (i = left; i < right; ++i)
4cdc65eb 2665 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
d7eb09a0 2666 }
4cdc65eb 2667#endif
a2889657
JB
2668}
2669
2670/* Contribute ELT to the mode line for window W.
2671 How it translates into text depends on its data type.
2672
2673 VPOS is the position of the mode line being displayed.
2674
44fa5b1e 2675 HPOS is the position (absolute on frame) where this element's text
a2889657
JB
2676 should start. The output is truncated automatically at the right
2677 edge of window W.
2678
2679 DEPTH is the depth in recursion. It is used to prevent
2680 infinite recursion here.
2681
2682 MINENDCOL is the hpos before which the element may not end.
2683 The element is padded at the right with spaces if nec
2684 to reach this column.
2685
2686 MAXENDCOL is the hpos past which this element may not extend.
2687 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
2688 (This is necessary to make nested padding and truncation work.)
2689
2690 Returns the hpos of the end of the text generated by ELT.
2691 The next element will receive that value as its HPOS arg,
2692 so as to concatenate the elements. */
2693
2694static int
2695display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2696 struct window *w;
2697 register int vpos, hpos;
2698 int depth;
2699 int minendcol;
2700 register int maxendcol;
2701 register Lisp_Object elt;
2702{
2703 tail_recurse:
2704 if (depth > 10)
2705 goto invalid;
2706
2707 depth++;
2708
2709#ifdef SWITCH_ENUM_BUG
2710 switch ((int) XTYPE (elt))
2711#else
2712 switch (XTYPE (elt))
2713#endif
2714 {
2715 case Lisp_String:
2716 {
2717 /* A string: output it and check for %-constructs within it. */
2718 register unsigned char c;
2719 register unsigned char *this = XSTRING (elt)->data;
2720
2721 while (hpos < maxendcol && *this)
2722 {
2723 unsigned char *last = this;
2724 while ((c = *this++) != '\0' && c != '%')
2725 ;
2726 if (this - 1 != last)
2727 {
2728 register int lim = --this - last + hpos;
d39b6696
KH
2729 if (frame_title_ptr)
2730 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
2731 else
2732 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
2733 hpos, min (lim, maxendcol));
a2889657
JB
2734 }
2735 else /* c == '%' */
2736 {
2737 register int spec_width = 0;
2738
2739 /* We can't allow -ve args due to the "%-" construct */
2740 /* Argument specifies minwidth but not maxwidth
2741 (maxwidth can be specified by
2742 (<negative-number> . <stuff>) mode-line elements) */
2743
2744 while ((c = *this++) >= '0' && c <= '9')
2745 {
2746 spec_width = spec_width * 10 + (c - '0');
2747 }
2748
2749 spec_width += hpos;
2750 if (spec_width > maxendcol)
2751 spec_width = maxendcol;
2752
2753 if (c == 'M')
2754 hpos = display_mode_element (w, vpos, hpos, depth,
2755 spec_width, maxendcol,
2756 Vglobal_mode_string);
2757 else if (c != 0)
d39b6696
KH
2758 {
2759 char *spec = decode_mode_spec (w, c, maxendcol - hpos);
2760 if (frame_title_ptr)
2761 hpos = store_frame_title (spec, spec_width, maxendcol);
2762 else
2763 hpos = display_string (w, vpos, spec, -1,
2764 hpos, 0, 1,
2765 spec_width, maxendcol);
2766 }
a2889657
JB
2767 }
2768 }
2769 }
2770 break;
2771
2772 case Lisp_Symbol:
2773 /* A symbol: process the value of the symbol recursively
2774 as if it appeared here directly. Avoid error if symbol void.
2775 Special case: if value of symbol is a string, output the string
2776 literally. */
2777 {
2778 register Lisp_Object tem;
2779 tem = Fboundp (elt);
265a9e55 2780 if (!NILP (tem))
a2889657
JB
2781 {
2782 tem = Fsymbol_value (elt);
2783 /* If value is a string, output that string literally:
2784 don't check for % within it. */
2785 if (XTYPE (tem) == Lisp_String)
d39b6696
KH
2786 {
2787 if (frame_title_ptr)
2788 hpos = store_frame_title (XSTRING (tem)->data,
2789 minendcol, maxendcol);
2790 else
2791 hpos = display_string (w, vpos, XSTRING (tem)->data,
2792 XSTRING (tem)->size,
2793 hpos, 0, 1, minendcol, maxendcol);
2794 }
a2889657
JB
2795 /* Give up right away for nil or t. */
2796 else if (!EQ (tem, elt))
2797 { elt = tem; goto tail_recurse; }
2798 }
2799 }
2800 break;
2801
2802 case Lisp_Cons:
2803 {
2804 register Lisp_Object car, tem;
2805
2806 /* A cons cell: three distinct cases.
2807 If first element is a string or a cons, process all the elements
2808 and effectively concatenate them.
2809 If first element is a negative number, truncate displaying cdr to
2810 at most that many characters. If positive, pad (with spaces)
2811 to at least that many characters.
2812 If first element is a symbol, process the cadr or caddr recursively
2813 according to whether the symbol's value is non-nil or nil. */
2814 car = XCONS (elt)->car;
2815 if (XTYPE (car) == Lisp_Symbol)
2816 {
2817 tem = Fboundp (car);
2818 elt = XCONS (elt)->cdr;
2819 if (XTYPE (elt) != Lisp_Cons)
2820 goto invalid;
2821 /* elt is now the cdr, and we know it is a cons cell.
2822 Use its car if CAR has a non-nil value. */
265a9e55 2823 if (!NILP (tem))
a2889657
JB
2824 {
2825 tem = Fsymbol_value (car);
265a9e55 2826 if (!NILP (tem))
a2889657
JB
2827 { elt = XCONS (elt)->car; goto tail_recurse; }
2828 }
2829 /* Symbol's value is nil (or symbol is unbound)
2830 Get the cddr of the original list
2831 and if possible find the caddr and use that. */
2832 elt = XCONS (elt)->cdr;
265a9e55 2833 if (NILP (elt))
a2889657
JB
2834 break;
2835 else if (XTYPE (elt) != Lisp_Cons)
2836 goto invalid;
2837 elt = XCONS (elt)->car;
2838 goto tail_recurse;
2839 }
2840 else if (XTYPE (car) == Lisp_Int)
2841 {
2842 register int lim = XINT (car);
2843 elt = XCONS (elt)->cdr;
2844 if (lim < 0)
2845 /* Negative int means reduce maximum width.
2846 DO NOT change MINENDCOL here!
2847 (20 -10 . foo) should truncate foo to 10 col
2848 and then pad to 20. */
2849 maxendcol = min (maxendcol, hpos - lim);
2850 else if (lim > 0)
2851 {
2852 /* Padding specified. Don't let it be more than
2853 current maximum. */
2854 lim += hpos;
2855 if (lim > maxendcol)
2856 lim = maxendcol;
2857 /* If that's more padding than already wanted, queue it.
2858 But don't reduce padding already specified even if
2859 that is beyond the current truncation point. */
2860 if (lim > minendcol)
2861 minendcol = lim;
2862 }
2863 goto tail_recurse;
2864 }
2865 else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons)
2866 {
2867 register int limit = 50;
2868 /* LIMIT is to protect against circular lists. */
2869 while (XTYPE (elt) == Lisp_Cons && --limit > 0
2870 && hpos < maxendcol)
2871 {
2872 hpos = display_mode_element (w, vpos, hpos, depth,
2873 hpos, maxendcol,
2874 XCONS (elt)->car);
2875 elt = XCONS (elt)->cdr;
2876 }
2877 }
2878 }
2879 break;
2880
2881 default:
2882 invalid:
d39b6696
KH
2883 if (frame_title_ptr)
2884 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
2885 else
2886 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
2887 minendcol, maxendcol);
2888 return hpos;
a2889657
JB
2889 }
2890
a2889657 2891 if (minendcol > hpos)
d39b6696
KH
2892 if (frame_title_ptr)
2893 hpos = store_frame_title ("", minendcol, maxendcol);
2894 else
2895 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
a2889657
JB
2896 return hpos;
2897}
2898\f
2899/* Return a string for the output of a mode line %-spec for window W,
2900 generated by character C and width MAXWIDTH. */
2901
11e82b76
JB
2902static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
2903
a2889657
JB
2904static char *
2905decode_mode_spec (w, c, maxwidth)
2906 struct window *w;
2907 register char c;
2908 register int maxwidth;
2909{
0b67772d 2910 Lisp_Object obj;
44fa5b1e
JB
2911 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2912 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
d39b6696 2913 struct buffer *b = XBUFFER (w->buffer);
a2889657 2914
0b67772d 2915 obj = Qnil;
44fa5b1e
JB
2916 if (maxwidth > FRAME_WIDTH (f))
2917 maxwidth = FRAME_WIDTH (f);
a2889657
JB
2918
2919 switch (c)
2920 {
2921 case 'b':
d39b6696 2922 obj = b->name;
a2889657
JB
2923#if 0
2924 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
2925 {
2926 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
2927 decode_mode_spec_buf[maxwidth - 1] = '\\';
2928 decode_mode_spec_buf[maxwidth] = '\0';
2929 return decode_mode_spec_buf;
2930 }
2931#endif
2932 break;
2933
2934 case 'f':
d39b6696 2935 obj = b->filename;
a2889657 2936#if 0
265a9e55 2937 if (NILP (obj))
a2889657
JB
2938 return "[none]";
2939 else if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth)
2940 {
2941 bcopy ("...", decode_mode_spec_buf, 3);
2942 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
2943 decode_mode_spec_buf + 3, maxwidth - 3);
2944 return decode_mode_spec_buf;
2945 }
2946#endif
2947 break;
2948
aa6d10fa
RS
2949 case 'l':
2950 {
2951 int startpos = marker_position (w->start);
2952 int line, linepos, topline;
2953 int nlines, junk;
2954 Lisp_Object tem;
2955 int height = XFASTINT (w->height);
2956
2957 /* If we decided that this buffer isn't suitable for line numbers,
2958 don't forget that too fast. */
2959 if (EQ (w->base_line_pos, w->buffer))
2960 return "??";
2961
2962 /* If the buffer is very big, don't waste time. */
d39b6696 2963 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
aa6d10fa
RS
2964 {
2965 w->base_line_pos = Qnil;
2966 w->base_line_number = Qnil;
2967 return "??";
2968 }
2969
2970 if (!NILP (w->base_line_number)
2971 && !NILP (w->base_line_pos)
2972 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
2973 {
2974 line = XFASTINT (w->base_line_number);
2975 linepos = XFASTINT (w->base_line_pos);
2976 }
2977 else
2978 {
2979 line = 1;
d39b6696 2980 linepos = BUF_BEGV (b);
aa6d10fa
RS
2981 }
2982
2983 /* Count lines from base line to window start position. */
2984 nlines = display_count_lines (linepos, startpos, startpos, &junk);
2985
2986 topline = nlines + line;
2987
2988 /* Determine a new base line, if the old one is too close
2989 or too far away, or if we did not have one.
2990 "Too close" means it's plausible a scroll-down would
2991 go back past it. */
d39b6696 2992 if (startpos == BUF_BEGV (b))
aa6d10fa
RS
2993 {
2994 XFASTINT (w->base_line_number) = topline;
d39b6696 2995 XFASTINT (w->base_line_pos) = BUF_BEGV (b);
aa6d10fa
RS
2996 }
2997 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 2998 || linepos == BUF_BEGV (b))
aa6d10fa 2999 {
d39b6696 3000 int limit = BUF_BEGV (b);
aa6d10fa
RS
3001 int position;
3002 int distance = (height * 2 + 30) * 200;
3003
3004 if (startpos - distance > limit)
3005 limit = startpos - distance;
3006
3007 nlines = display_count_lines (startpos, limit,
3008 -(height * 2 + 30),
3009 &position);
3010 /* If we couldn't find the lines we wanted within
3011 200 chars per line,
3012 give up on line numbers for this window. */
3013 if (position == startpos - distance)
3014 {
3015 w->base_line_pos = w->buffer;
3016 w->base_line_number = Qnil;
3017 return "??";
3018 }
3019
3020 XFASTINT (w->base_line_number) = topline - nlines;
3021 XFASTINT (w->base_line_pos) = position;
3022 }
3023
3024 /* Now count lines from the start pos to point. */
3025 nlines = display_count_lines (startpos, PT, PT, &junk);
3026
3027 /* Record that we did display the line number. */
3028 line_number_displayed = 1;
3029
3030 /* Make the string to show. */
3031 sprintf (decode_mode_spec_buf, "%d", topline + nlines);
3032 return decode_mode_spec_buf;
3033 }
3034 break;
3035
a2889657 3036 case 'm':
d39b6696 3037 obj = b->mode_name;
a2889657
JB
3038 break;
3039
3040 case 'n':
d39b6696 3041 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
3042 return " Narrow";
3043 break;
3044
3045 case '*':
d39b6696 3046 if (!NILP (b->read_only))
a2889657 3047 return "%";
d39b6696 3048 if (BUF_MODIFF (b) > b->save_modified)
a2889657
JB
3049 return "*";
3050 return "-";
3051
5cc9f80d 3052 case '+':
8d80e227 3053 /* This differs from %* only for a modified read-only buffer. */
d39b6696 3054 if (BUF_MODIFF (b) > b->save_modified)
5cc9f80d 3055 return "*";
d39b6696 3056 if (!NILP (b->read_only))
8d80e227 3057 return "%";
5cc9f80d
RS
3058 return "-";
3059
51b2d337
RS
3060 case '&':
3061 /* This differs from %* in ignoring read-only-ness. */
d39b6696 3062 if (BUF_MODIFF (b) > b->save_modified)
51b2d337
RS
3063 return "*";
3064 return "-";
3065
a2889657
JB
3066 case 's':
3067 /* status of process */
d39b6696 3068 obj = Fget_buffer_process (w->buffer);
265a9e55 3069 if (NILP (obj))
a2889657 3070 return "no process";
76412d64 3071#ifdef subprocesses
a2889657 3072 obj = Fsymbol_name (Fprocess_status (obj));
76412d64 3073#endif
a2889657 3074 break;
a2889657 3075
76412d64 3076 case 't': /* indicate TEXT or BINARY */
dce36b49
KH
3077#ifdef MODE_LINE_BINARY_TEXT
3078 return MODE_LINE_BINARY_TEXT (b);
3079#else
76412d64 3080 return "T";
dce36b49 3081#endif
76412d64 3082
a2889657
JB
3083 case 'p':
3084 {
3085 int pos = marker_position (w->start);
d39b6696 3086 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 3087
d39b6696 3088 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 3089 {
d39b6696 3090 if (pos <= BUF_BEGV (b))
a2889657
JB
3091 return "All";
3092 else
3093 return "Bottom";
3094 }
d39b6696 3095 else if (pos <= BUF_BEGV (b))
a2889657
JB
3096 return "Top";
3097 else
3098 {
d39b6696 3099 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
3100 /* We can't normally display a 3-digit number,
3101 so get us a 2-digit number that is close. */
3102 if (total == 100)
3103 total = 99;
3104 sprintf (decode_mode_spec_buf, "%2d%%", total);
3105 return decode_mode_spec_buf;
3106 }
3107 }
3108
8ffcb79f
RS
3109 /* Display percentage of size above the bottom of the screen. */
3110 case 'P':
3111 {
3112 int toppos = marker_position (w->start);
d39b6696
KH
3113 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
3114 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 3115
d39b6696 3116 if (botpos >= BUF_ZV (b))
8ffcb79f 3117 {
d39b6696 3118 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
3119 return "All";
3120 else
3121 return "Bottom";
3122 }
3123 else
3124 {
d39b6696 3125 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
3126 /* We can't normally display a 3-digit number,
3127 so get us a 2-digit number that is close. */
3128 if (total == 100)
3129 total = 99;
d39b6696 3130 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
3131 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
3132 else
3133 sprintf (decode_mode_spec_buf, "%2d%%", total);
3134 return decode_mode_spec_buf;
3135 }
3136 }
3137
a2889657
JB
3138 case '%':
3139 return "%";
3140
3141 case '[':
3142 {
3143 int i;
3144 char *p;
3145
3146 if (command_loop_level > 5)
3147 return "[[[... ";
3148 p = decode_mode_spec_buf;
3149 for (i = 0; i < command_loop_level; i++)
3150 *p++ = '[';
3151 *p = 0;
3152 return decode_mode_spec_buf;
3153 }
3154
3155 case ']':
3156 {
3157 int i;
3158 char *p;
3159
3160 if (command_loop_level > 5)
3161 return " ...]]]";
3162 p = decode_mode_spec_buf;
3163 for (i = 0; i < command_loop_level; i++)
3164 *p++ = ']';
3165 *p = 0;
3166 return decode_mode_spec_buf;
3167 }
d39b6696 3168
a2889657
JB
3169 case '-':
3170 {
a2889657
JB
3171 register char *p;
3172 register int i;
3173
3174 if (maxwidth < sizeof (lots_of_dashes))
3175 return lots_of_dashes;
3176 else
3177 {
3178 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
3179 *p++ = '-';
3180 *p = '\0';
3181 }
3182 return decode_mode_spec_buf;
3183 }
3184 }
d39b6696 3185
a2889657
JB
3186 if (XTYPE (obj) == Lisp_String)
3187 return (char *) XSTRING (obj)->data;
3188 else
3189 return "";
3190}
59b49f63
RS
3191\f
3192/* Search for COUNT instances of a line boundary, which means either a
3193 newline or (if selective display enabled) a carriage return.
3194 Start at START. If COUNT is negative, search backwards.
3195
3196 If we find COUNT instances, set *SHORTAGE to zero, and return the
3197 position after the COUNTth match. Note that for reverse motion
3198 this is not the same as the usual convention for Emacs motion commands.
3199
3200 If we don't find COUNT instances before reaching the end of the
3201 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3202 the number of line boundaries left unfound, and return the end of the
3203 buffer we bumped up against. */
3204
3205static int
3206display_scan_buffer (start, count, shortage)
3207 int *shortage, start;
3208 register int count;
3209{
3210 int limit = ((count > 0) ? ZV - 1 : BEGV);
3211 int direction = ((count > 0) ? 1 : -1);
3212
3213 register unsigned char *cursor;
3214 unsigned char *base;
3215
3216 register int ceiling;
3217 register unsigned char *ceiling_addr;
3218
3219 /* If we are not in selective display mode,
3220 check only for newlines. */
3221 if (! (!NILP (current_buffer->selective_display)
3222 && !INTEGERP (current_buffer->selective_display)))
3223 return scan_buffer ('\n', start, count, shortage, 0);
3224
3225 /* The code that follows is like scan_buffer
3226 but checks for either newline or carriage return. */
3227
3228 if (shortage != 0)
3229 *shortage = 0;
3230
3231 if (count > 0)
3232 while (start != limit + 1)
3233 {
3234 ceiling = BUFFER_CEILING_OF (start);
3235 ceiling = min (limit, ceiling);
3236 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
3237 base = (cursor = &FETCH_CHAR (start));
3238 while (1)
3239 {
3240 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
3241 ;
3242 if (cursor != ceiling_addr)
3243 {
3244 if (--count == 0)
3245 {
3246 immediate_quit = 0;
3247 return (start + cursor - base + 1);
3248 }
3249 else
3250 if (++cursor == ceiling_addr)
3251 break;
3252 }
3253 else
3254 break;
3255 }
3256 start += cursor - base;
3257 }
3258 else
3259 {
3260 start--; /* first character we scan */
3261 while (start > limit - 1)
3262 { /* we WILL scan under start */
3263 ceiling = BUFFER_FLOOR_OF (start);
3264 ceiling = max (limit, ceiling);
3265 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
3266 base = (cursor = &FETCH_CHAR (start));
3267 cursor++;
3268 while (1)
3269 {
3270 while (--cursor != ceiling_addr
3271 && *cursor != '\n' && *cursor != 015)
3272 ;
3273 if (cursor != ceiling_addr)
3274 {
3275 if (++count == 0)
3276 {
3277 immediate_quit = 0;
3278 return (start + cursor - base + 1);
3279 }
3280 }
3281 else
3282 break;
3283 }
3284 start += cursor - base;
3285 }
3286 }
3287
3288 if (shortage != 0)
3289 *shortage = count * direction;
3290 return (start + ((direction == 1 ? 0 : 1)));
3291}
aa6d10fa
RS
3292
3293/* Count up to N lines starting from FROM.
3294 But don't go beyond LIMIT.
3295 Return the number of lines thus found (always positive).
3296 Store the position after what was found into *POS_PTR. */
3297
3298static int
3299display_count_lines (from, limit, n, pos_ptr)
3300 int from, limit, n;
3301 int *pos_ptr;
3302{
3303 int oldbegv = BEGV;
3304 int oldzv = ZV;
3305 int shortage = 0;
3306
3307 if (limit < from)
3308 BEGV = limit;
3309 else
3310 ZV = limit;
3311
59b49f63 3312 *pos_ptr = display_scan_buffer (from, n, &shortage);
aa6d10fa
RS
3313
3314 ZV = oldzv;
3315 BEGV = oldbegv;
3316
3317 if (n < 0)
3318 /* When scanning backwards, scan_buffer stops *after* the last newline
3319 it finds, but does count it. Compensate for that. */
3320 return - n - shortage - (*pos_ptr != limit);
3321 return n - shortage;
3322}
a2889657
JB
3323\f
3324/* Display STRING on one line of window W, starting at HPOS.
3325 Display at position VPOS. Caller should have done get_display_line.
11e82b76 3326 If VPOS == -1, display it as the current frame's title.
90adcf20 3327 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
a2889657
JB
3328
3329 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3330
3331 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3332 MAXCOL is the last column ok to end at. Truncate here.
3333 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
44fa5b1e 3334 Both count from the left edge of the frame, as does HPOS.
a2889657
JB
3335 The right edge of W is an implicit maximum.
3336 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3337
278feba9
RS
3338 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3339 at the place where the current window ends in this line
3340 and not display anything beyond there. Otherwise, only MAXCOL
3341 controls where to stop output.
3342
3343 Returns ending hpos. */
a2889657
JB
3344
3345static int
278feba9
RS
3346display_string (w, vpos, string, length, hpos, truncate,
3347 obey_window_width, mincol, maxcol)
a2889657
JB
3348 struct window *w;
3349 unsigned char *string;
90adcf20 3350 int length;
a2889657
JB
3351 int vpos, hpos;
3352 GLYPH truncate;
278feba9 3353 int obey_window_width;
a2889657
JB
3354 int mincol, maxcol;
3355{
3356 register int c;
3357 register GLYPH *p1;
3358 int hscroll = XINT (w->hscroll);
253c7d2f 3359 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
a2889657
JB
3360 register GLYPH *start;
3361 register GLYPH *end;
b1d1124b
JB
3362 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3363 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
a2889657
JB
3364 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
3365 int window_width = XFASTINT (w->width);
3366
3367 /* Use the standard display table, not the window's display table.
3368 We don't want the mode line in rot13. */
3369 register struct Lisp_Vector *dp = 0;
efc63ef0 3370 int i;
a2889657
JB
3371
3372 if (XTYPE (Vstandard_display_table) == Lisp_Vector
3373 && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
3374 dp = XVECTOR (Vstandard_display_table);
3375
54ff581a 3376 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657
JB
3377
3378 p1 = p1start;
3379 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
a2889657 3380
278feba9 3381 if (obey_window_width)
b1d1124b 3382 {
278feba9
RS
3383 end = start + window_width - (truncate != 0);
3384
3385 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f))
b1d1124b 3386 {
278feba9
RS
3387 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3388 {
3389 int i;
b1d1124b 3390
5802e919 3391 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
278feba9
RS
3392 *end-- = ' ';
3393 }
3394 else
3395 *end-- = '|';
b1d1124b 3396 }
b1d1124b 3397 }
a2889657 3398
278feba9
RS
3399 if (! obey_window_width
3400 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
a2889657 3401 end = desired_glyphs->glyphs[vpos] + maxcol;
278feba9 3402
efc63ef0 3403 /* Store 0 in charstart for these columns. */
bd5dec8e 3404 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
efc63ef0
RS
3405 desired_glyphs->charstarts[vpos][i] = 0;
3406
a2889657
JB
3407 if (maxcol >= 0 && mincol > maxcol)
3408 mincol = maxcol;
3409
3410 while (p1 < end)
3411 {
90adcf20
RS
3412 if (length == 0)
3413 break;
a2889657 3414 c = *string++;
90adcf20
RS
3415 /* Specified length. */
3416 if (length >= 0)
3417 length--;
3418 /* Unspecified length (null-terminated string). */
3419 else if (c == 0)
3420 break;
3421
a2889657 3422 if (c >= 040 && c < 0177
c581d710 3423 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
a2889657
JB
3424 {
3425 if (p1 >= start)
3426 *p1 = c;
3427 p1++;
3428 }
3429 else if (c == '\t')
3430 {
3431 do
3432 {
3433 if (p1 >= start && p1 < end)
3434 *p1 = SPACEGLYPH;
3435 p1++;
3436 }
3437 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
3438 }
c581d710 3439 else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
278feba9
RS
3440 {
3441 p1 = copy_part_of_rope (f, p1, start,
3442 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
3443 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
3444 0);
3445 }
ded34426 3446 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
a2889657
JB
3447 {
3448 if (p1 >= start)
278feba9
RS
3449 *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
3450 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
3451 0);
a2889657 3452 p1++;
6e8290aa 3453 if (p1 >= start && p1 < end)
a2889657
JB
3454 *p1 = c ^ 0100;
3455 p1++;
3456 }
3457 else
3458 {
3459 if (p1 >= start)
278feba9
RS
3460 *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
3461 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
3462 0);
a2889657 3463 p1++;
6e8290aa 3464 if (p1 >= start && p1 < end)
a2889657
JB
3465 *p1 = (c >> 6) + '0';
3466 p1++;
6e8290aa 3467 if (p1 >= start && p1 < end)
a2889657
JB
3468 *p1 = (7 & (c >> 3)) + '0';
3469 p1++;
6e8290aa 3470 if (p1 >= start && p1 < end)
a2889657
JB
3471 *p1 = (7 & c) + '0';
3472 p1++;
3473 }
3474 }
3475
90adcf20 3476 if (c && length > 0)
a2889657
JB
3477 {
3478 p1 = end;
278feba9 3479 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
a2889657
JB
3480 }
3481 else if (mincol >= 0)
3482 {
3483 end = desired_glyphs->glyphs[vpos] + mincol;
3484 while (p1 < end)
3485 *p1++ = SPACEGLYPH;
3486 }
3487
3488 {
3489 register int len = p1 - desired_glyphs->glyphs[vpos];
3490
3491 if (len > desired_glyphs->used[vpos])
3492 desired_glyphs->used[vpos] = len;
3493 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3494
3495 return len;
3496 }
3497}
3498\f
3499void
3500syms_of_xdisp ()
3501{
cf074754
RS
3502 staticpro (&Qmenu_bar_update_hook);
3503 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
3504
a2889657
JB
3505 staticpro (&last_arrow_position);
3506 staticpro (&last_arrow_string);
3507 last_arrow_position = Qnil;
3508 last_arrow_string = Qnil;
3509
3510 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 3511 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
3512 Vglobal_mode_string = Qnil;
3513
3514 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
3515 "Marker for where to display an arrow on top of the buffer text.\n\
3516This must be the beginning of a line in order to work.\n\
3517See also `overlay-arrow-string'.");
3518 Voverlay_arrow_position = Qnil;
3519
3520 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
3521 "String to display as an arrow. See also `overlay-arrow-position'.");
3522 Voverlay_arrow_string = Qnil;
3523
3524 DEFVAR_INT ("scroll-step", &scroll_step,
3525 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
3526If that fails to bring point back on frame, point is centered instead.\n\
3527If this is zero, point is always centered after it moves off frame.");
a2889657
JB
3528
3529 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
3530
3531 DEFVAR_BOOL ("truncate-partial-width-windows",
3532 &truncate_partial_width_windows,
44fa5b1e 3533 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
3534 truncate_partial_width_windows = 1;
3535
3536 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
3537 "*Non-nil means use inverse video for the mode line.");
3538 mode_line_inverse_video = 1;
aa6d10fa
RS
3539
3540 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
3541 "*Maximum buffer size for which line number should be displayed.");
3542 line_number_display_limit = 1000000;
fba9ce76
RS
3543
3544 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
3545 "*Non-nil means highlight region even in nonselected windows.");
3546 highlight_nonselected_windows = 1;
d39b6696
KH
3547
3548 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3549 "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\
3550Not guaranteed to be accurate except while parsing frame-title-format.");
3551
3552 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
3553 "Template for displaying the titlebar of visible frames.\n\
3554\(Assuming the window manager supports this feature.)\n\
3555This variable has the same structure as `mode-line-format' (which see),\n\
3556and is used only on frames for which no explicit name has been set\n\
3557\(see `modify-frame-parameters').");
3558 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
3559 "Template for displaying the titlebar of an iconified frame.\n\
3560\(Assuming the window manager supports this feature.)\n\
3561This variable has the same structure as `mode-line-format' (which see),\n\
3562and is used only on frames for which no explicit name has been set\n\
3563\(see `modify-frame-parameters').");
3564 Vicon_title_format
3565 = Vframe_title_format
3566 = Fcons (intern ("multiple-frames"),
3567 Fcons (build_string ("%b"),
3568 Fcons (Fcons (build_string (""),
3569 Fcons (intern ("invocation-name"),
3570 Fcons (build_string ("@"),
3571 Fcons (intern ("system-name"),
3572 Qnil)))),
3573 Qnil)));
a2889657
JB
3574}
3575
3576/* initialize the window system */
3577init_xdisp ()
3578{
3579 Lisp_Object root_window;
3580#ifndef COMPILER_REGISTER_BUG
3581 register
3582#endif /* COMPILER_REGISTER_BUG */
3583 struct window *mini_w;
3584
3585 this_line_bufpos = 0;
3586
3587 mini_w = XWINDOW (minibuf_window);
11e82b76 3588 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657
JB
3589
3590 echo_area_glyphs = 0;
3591 previous_echo_glyphs = 0;
3592
3593 if (!noninteractive)
3594 {
44fa5b1e 3595 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
a2889657 3596 XFASTINT (XWINDOW (root_window)->top) = 0;
44fa5b1e
JB
3597 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
3598 XFASTINT (mini_w->top) = FRAME_HEIGHT (f) - 1;
a2889657
JB
3599 set_window_height (minibuf_window, 1, 0);
3600
44fa5b1e
JB
3601 XFASTINT (XWINDOW (root_window)->width) = FRAME_WIDTH (f);
3602 XFASTINT (mini_w->width) = FRAME_WIDTH (f);
a2889657
JB
3603 }
3604}