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