(etc): Delete *.orig and *.rej.
[emacs.git] / src / xdisp.c
bloba1b5a2ea88f9d36781e83227f558dcb04feb1c8c
1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include <config.h>
22 #include <stdio.h>
23 /*#include <ctype.h>*/
24 #undef NULL
25 #include "lisp.h"
26 #include "frame.h"
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"
35 #include "termhooks.h"
36 #include "intervals.h"
37 #include "keyboard.h"
39 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
40 extern void set_frame_menubar ();
41 #endif
43 extern int interrupt_input;
44 extern int command_loop_level;
46 extern Lisp_Object Qface;
48 extern Lisp_Object Voverriding_local_map;
49 extern Lisp_Object Voverriding_local_map_menu_flag;
51 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
52 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
53 Lisp_Object Qredisplay_end_trigger_functions;
55 /* Nonzero means print newline to stdout before next minibuffer message. */
57 int noninteractive_need_newline;
59 /* Nonzero means print newline to message log before next message. */
61 static int message_log_need_newline;
63 #define min(a, b) ((a) < (b) ? (a) : (b))
64 #define max(a, b) ((a) > (b) ? (a) : (b))
65 #define minmax(floor, val, ceil) \
66 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
68 /* The buffer position of the first character appearing
69 entirely or partially on the current frame line.
70 Or zero, which disables the optimization for the current frame line. */
71 static int this_line_bufpos;
73 /* Number of characters past the end of this line,
74 including the terminating newline */
75 static int this_line_endpos;
77 /* The vertical position of this frame line. */
78 static int this_line_vpos;
80 /* Hpos value for start of display on this frame line.
81 Usually zero, but negative if first character really began
82 on previous line */
83 static int this_line_start_hpos;
85 /* Buffer that this_line variables are describing. */
86 static struct buffer *this_line_buffer;
88 /* Value of echo_area_glyphs when it was last acted on.
89 If this is nonzero, there is a message on the frame
90 in the minibuffer and it should be erased as soon
91 as it is no longer requested to appear. */
92 char *previous_echo_glyphs;
94 /* Nonzero means truncate lines in all windows less wide than the frame */
95 int truncate_partial_width_windows;
97 /* Nonzero means we have more than one non-minibuffer-only frame.
98 Not guaranteed to be accurate except while parsing frame-title-format. */
99 int multiple_frames;
101 Lisp_Object Vglobal_mode_string;
103 /* Marker for where to display an arrow on top of the buffer text. */
104 Lisp_Object Voverlay_arrow_position;
106 /* String to display for the arrow. */
107 Lisp_Object Voverlay_arrow_string;
109 /* Like mode-line-format, but for the titlebar on a visible frame. */
110 Lisp_Object Vframe_title_format;
112 /* Like mode-line-format, but for the titlebar on an iconified frame. */
113 Lisp_Object Vicon_title_format;
115 /* List of functions to call when a window's size changes. These
116 functions get one arg, a frame on which one or more windows' sizes
117 have changed. */
118 static Lisp_Object Vwindow_size_change_functions;
120 /* Values of those variables at last redisplay. */
121 static Lisp_Object last_arrow_position, last_arrow_string;
123 Lisp_Object Qmenu_bar_update_hook;
125 /* Nonzero if overlay arrow has been displayed once in this window. */
126 static int overlay_arrow_seen;
128 /* Nonzero if visible end of buffer has already been displayed once
129 in this window. (We need this variable in case there are overlay
130 strings that get displayed there.) */
131 static int zv_strings_seen;
133 /* Nonzero means highlight the region even in nonselected windows. */
134 static int highlight_nonselected_windows;
136 /* If cursor motion alone moves point off frame,
137 Try scrolling this many lines up or down if that will bring it back. */
138 static int scroll_step;
140 /* Nonzero if try_window_id has made blank lines at window bottom
141 since the last redisplay that paused */
142 static int blank_end_of_window;
144 /* Number of windows showing the buffer of the selected window
145 (or another buffer with the same base buffer).
146 keyboard.c refers to this. */
147 int buffer_shared;
149 /* display_text_line sets these to the frame position (origin 0) of point,
150 whether the window is selected or not.
151 Set one to -1 first to determine whether point was found afterwards. */
153 static int cursor_vpos;
154 static int cursor_hpos;
156 static int debug_end_pos;
158 /* Nonzero means display mode line highlighted */
159 int mode_line_inverse_video;
161 static int message_log_check_duplicate ();
162 static void echo_area_display ();
163 void mark_window_display_accurate ();
164 static void redisplay_windows ();
165 static void redisplay_window ();
166 static void update_menu_bar ();
167 static void try_window ();
168 static int try_window_id ();
169 static struct position *display_text_line ();
170 static void display_mode_line ();
171 static int display_mode_element ();
172 static char *decode_mode_spec ();
173 static int display_string ();
174 static void display_menu_bar ();
175 static int display_count_lines ();
177 /* Prompt to display in front of the minibuffer contents */
178 Lisp_Object minibuf_prompt;
180 /* Width in columns of current minibuffer prompt. */
181 int minibuf_prompt_width;
183 /* Message to display instead of minibuffer contents
184 This is what the functions error and message make,
185 and command echoing uses it as well.
186 It overrides the minibuf_prompt as well as the buffer. */
187 char *echo_area_glyphs;
189 /* This is the length of the message in echo_area_glyphs. */
190 int echo_area_glyphs_length;
192 /* This is the window where the echo area message was displayed.
193 It is always a minibuffer window, but it may not be the
194 same window currently active as a minibuffer. */
195 Lisp_Object echo_area_window;
197 /* true iff we should redraw the mode lines on the next redisplay */
198 int update_mode_lines;
200 /* Smallest number of characters before the gap
201 at any time since last redisplay that finished.
202 Valid for current buffer when try_window_id can be called. */
203 int beg_unchanged;
205 /* Smallest number of characters after the gap
206 at any time since last redisplay that finished.
207 Valid for current buffer when try_window_id can be called. */
208 int end_unchanged;
210 /* MODIFF as of last redisplay that finished;
211 if it matches MODIFF, beg_unchanged and end_unchanged
212 contain no useful information */
213 int unchanged_modified;
215 /* Nonzero if window sizes or contents have changed
216 since last redisplay that finished */
217 int windows_or_buffers_changed;
219 /* Nonzero after display_mode_line if %l was used
220 and it displayed a line number. */
221 int line_number_displayed;
223 /* Maximum buffer size for which to display line numbers. */
224 static int line_number_display_limit;
226 /* Number of lines to keep in the message log buffer.
227 t means infinite. nil means don't log at all. */
228 Lisp_Object Vmessage_log_max;
230 void
231 message_log_maybe_newline ()
233 if (message_log_need_newline)
234 message_dolog ("", 0, 1);
238 /* Add a string to the message log, optionally terminated with a newline.
239 This function calls low-level routines in order to bypass text property
240 hooks, etc. which might not be safe to run. */
242 void
243 message_dolog (m, len, nlflag)
244 char *m;
245 int len, nlflag;
247 if (!NILP (Vmessage_log_max))
249 struct buffer *oldbuf;
250 int oldpoint, oldbegv, oldzv;
252 oldbuf = current_buffer;
253 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
254 current_buffer->undo_list = Qt;
255 oldpoint = PT;
256 oldbegv = BEGV;
257 oldzv = ZV;
258 BEGV = BEG;
259 ZV = Z;
260 if (oldpoint == Z)
261 oldpoint += len + nlflag;
262 if (oldzv == Z)
263 oldzv += len + nlflag;
264 TEMP_SET_PT (Z);
265 if (len)
266 insert_1 (m, len, 1, 0);
267 if (nlflag)
269 int this_bol, prev_bol, dup;
270 insert_1 ("\n", 1, 1, 0);
272 this_bol = scan_buffer ('\n', Z, 0, -2, 0, 0);
273 if (this_bol > BEG)
275 prev_bol = scan_buffer ('\n', this_bol, 0, -2, 0, 0);
276 dup = message_log_check_duplicate (prev_bol, this_bol);
277 if (dup)
279 if (oldpoint > prev_bol)
280 oldpoint -= min (this_bol, oldpoint) - prev_bol;
281 if (oldbegv > prev_bol)
282 oldbegv -= min (this_bol, oldbegv) - prev_bol;
283 if (oldzv > prev_bol)
284 oldzv -= min (this_bol, oldzv) - prev_bol;
285 del_range_1 (prev_bol, this_bol, 0);
286 if (dup > 1)
288 char dupstr[40];
289 int duplen;
291 /* If you change this format, don't forget to also
292 change message_log_check_duplicate. */
293 sprintf (dupstr, " [%d times]", dup);
294 duplen = strlen (dupstr);
295 TEMP_SET_PT (Z-1);
296 if (oldpoint == Z)
297 oldpoint += duplen;
298 if (oldzv == Z)
299 oldzv += duplen;
300 insert_1 (dupstr, duplen, 1, 0);
305 if (NATNUMP (Vmessage_log_max))
307 int pos = scan_buffer ('\n', Z, 0,
308 -XFASTINT (Vmessage_log_max) - 1, 0, 0);
309 oldpoint -= min (pos, oldpoint) - BEG;
310 oldbegv -= min (pos, oldbegv) - BEG;
311 oldzv -= min (pos, oldzv) - BEG;
312 del_range_1 (BEG, pos, 0);
315 BEGV = oldbegv;
316 ZV = oldzv;
317 TEMP_SET_PT (oldpoint);
318 set_buffer_internal (oldbuf);
319 message_log_need_newline = !nlflag;
324 /* We are at the end of the buffer after just having inserted a newline.
325 (Note: We depend on the fact we won't be crossing the gap.)
326 Check to see if the most recent message looks a lot like the previous one.
327 Return 0 if different, 1 if the new one should just replace it, or a
328 value N > 1 if we should also append " [N times]". */
330 static int
331 message_log_check_duplicate (prev_bol, this_bol)
332 int prev_bol, this_bol;
334 int i;
335 int len = Z - 1 - this_bol;
336 int seen_dots = 0;
337 unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
338 unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
340 for (i = 0; i < len; i++)
342 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
343 && p1[i] != '\n')
344 seen_dots = 1;
345 if (p1[i] != p2[i])
346 return seen_dots;
348 p1 += len;
349 if (*p1 == '\n')
350 return 2;
351 if (*p1++ == ' ' && *p1++ == '[')
353 int n = 0;
354 while (*p1 >= '0' && *p1 <= '9')
355 n = n * 10 + *p1++ - '0';
356 if (strncmp (p1, " times]\n", 8) == 0)
357 return n+1;
359 return 0;
362 /* Display an echo area message M with a specified length of LEN chars.
363 The string may include null characters. If m is 0, clear out any
364 existing message, and let the minibuffer text show through.
365 Do not pass text that is stored in a Lisp string. */
367 void
368 message2 (m, len)
369 char *m;
370 int len;
372 /* First flush out any partial line written with print. */
373 message_log_maybe_newline ();
374 if (m)
375 message_dolog (m, len, 1);
376 message2_nolog (m, len);
380 /* The non-logging part of that function. */
382 void
383 message2_nolog (m, len)
384 char *m;
385 int len;
387 if (noninteractive)
389 if (noninteractive_need_newline)
390 putc ('\n', stderr);
391 noninteractive_need_newline = 0;
392 fwrite (m, len, 1, stderr);
393 if (cursor_in_echo_area == 0)
394 fprintf (stderr, "\n");
395 fflush (stderr);
397 /* A null message buffer means that the frame hasn't really been
398 initialized yet. Error messages get reported properly by
399 cmd_error, so this must be just an informative message; toss it. */
400 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
402 Lisp_Object mini_window;
403 FRAME_PTR f;
405 /* Get the frame containing the minibuffer
406 that the selected frame is using. */
407 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
408 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
410 #ifdef MULTI_FRAME
411 FRAME_SAMPLE_VISIBILITY (f);
412 if (FRAME_VISIBLE_P (selected_frame)
413 && ! FRAME_VISIBLE_P (f))
414 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
415 #endif
417 if (m)
419 echo_area_glyphs = m;
420 echo_area_glyphs_length = len;
422 else
423 echo_area_glyphs = previous_echo_glyphs = 0;
425 do_pending_window_change ();
426 echo_area_display ();
427 update_frame (f, 1, 1);
428 do_pending_window_change ();
429 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
430 (*frame_up_to_date_hook) (f);
434 void
435 message1 (m)
436 char *m;
438 message2 (m, (m ? strlen (m) : 0));
441 void
442 message1_nolog (m)
443 char *m;
445 message2_nolog (m, (m ? strlen (m) : 0));
448 /* Truncate what will be displayed in the echo area
449 the next time we display it--but don't redisplay it now. */
451 void
452 truncate_echo_area (len)
453 int len;
455 /* A null message buffer means that the frame hasn't really been
456 initialized yet. Error messages get reported properly by
457 cmd_error, so this must be just an informative message; toss it. */
458 if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
459 echo_area_glyphs_length = len;
462 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
463 zero if being used by message. */
464 int message_buf_print;
466 /* Dump an informative message to the minibuf. If m is 0, clear out
467 any existing message, and let the minibuffer text show through. */
468 /* VARARGS 1 */
469 void
470 message (m, a1, a2, a3)
471 char *m;
472 EMACS_INT a1, a2, a3;
474 if (noninteractive)
476 if (m)
478 if (noninteractive_need_newline)
479 putc ('\n', stderr);
480 noninteractive_need_newline = 0;
481 fprintf (stderr, m, a1, a2, a3);
482 if (cursor_in_echo_area == 0)
483 fprintf (stderr, "\n");
484 fflush (stderr);
487 else if (INTERACTIVE)
489 /* The frame whose minibuffer we're going to display the message on.
490 It may be larger than the selected frame, so we need
491 to use its buffer, not the selected frame's buffer. */
492 Lisp_Object mini_window;
493 FRAME_PTR f;
495 /* Get the frame containing the minibuffer
496 that the selected frame is using. */
497 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
498 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
500 /* A null message buffer means that the frame hasn't really been
501 initialized yet. Error messages get reported properly by
502 cmd_error, so this must be just an informative message; toss it. */
503 if (FRAME_MESSAGE_BUF (f))
505 if (m)
507 int len;
508 #ifdef NO_ARG_ARRAY
509 EMACS_INT a[3];
510 a[0] = a1;
511 a[1] = a2;
512 a[2] = a3;
514 len = doprnt (FRAME_MESSAGE_BUF (f),
515 FRAME_WIDTH (f), m, (char *)0, 3, a);
516 #else
517 len = doprnt (FRAME_MESSAGE_BUF (f),
518 FRAME_WIDTH (f), m, (char *)0, 3, &a1);
519 #endif /* NO_ARG_ARRAY */
521 message2 (FRAME_MESSAGE_BUF (f), len);
523 else
524 message1 (0);
526 /* Print should start at the beginning of the message
527 buffer next time. */
528 message_buf_print = 0;
533 /* The non-logging version of that function. */
534 void
535 message_nolog (m, a1, a2, a3)
536 char *m;
537 EMACS_INT a1, a2, a3;
539 Lisp_Object old_log_max;
540 old_log_max = Vmessage_log_max;
541 Vmessage_log_max = Qnil;
542 message (m, a1, a2, a3);
543 Vmessage_log_max = old_log_max;
546 void
547 update_echo_area ()
549 message2 (echo_area_glyphs, echo_area_glyphs_length);
552 static void
553 echo_area_display ()
555 register int vpos;
556 FRAME_PTR f;
557 Lisp_Object mini_window;
559 /* Choose the minibuffer window for this display.
560 It is the minibuffer window used by the selected frame. */
561 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
562 /* This is the frame that window is in. */
563 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
565 if (! FRAME_VISIBLE_P (f))
566 return;
568 if (frame_garbaged)
570 redraw_garbaged_frames ();
571 frame_garbaged = 0;
574 if (echo_area_glyphs || minibuf_level == 0)
576 echo_area_window = mini_window;
578 vpos = XFASTINT (XWINDOW (mini_window)->top);
579 get_display_line (f, vpos, 0);
580 display_string (XWINDOW (mini_window), vpos,
581 echo_area_glyphs ? echo_area_glyphs : "",
582 echo_area_glyphs ? echo_area_glyphs_length : -1,
583 0, 0, 0, 0, FRAME_WIDTH (f));
585 #if 0 /* This just gets in the way. update_frame does the job. */
586 /* If desired cursor location is on this line, put it at end of text */
587 if (cursor_in_echo_area)
588 FRAME_CURSOR_Y (f) = vpos;
589 if (FRAME_CURSOR_Y (f) == vpos)
590 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
591 #endif
593 /* Fill the rest of the minibuffer window with blank lines. */
595 int i;
597 for (i = vpos + 1;
598 i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
600 get_display_line (f, i, 0);
601 display_string (XWINDOW (mini_window), vpos,
602 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f));
606 else if (!EQ (mini_window, selected_window))
607 windows_or_buffers_changed++;
609 if (EQ (mini_window, selected_window))
610 this_line_bufpos = 0;
612 previous_echo_glyphs = echo_area_glyphs;
615 #ifdef HAVE_WINDOW_SYSTEM
616 static char frame_title_buf[512];
617 static char *frame_title_ptr;
619 static int
620 store_frame_title (str, mincol, maxcol)
621 char *str;
622 int mincol, maxcol;
624 char *limit;
625 if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
626 maxcol = sizeof (frame_title_buf);
627 limit = &frame_title_buf[maxcol];
628 while (*str != '\0' && frame_title_ptr < limit)
629 *frame_title_ptr++ = *str++;
630 while (frame_title_ptr < &frame_title_buf[mincol])
631 *frame_title_ptr++ = ' ';
632 return frame_title_ptr - frame_title_buf;
635 static void
636 x_consider_frame_title (frame)
637 Lisp_Object frame;
639 Lisp_Object fmt;
640 struct buffer *obuf;
641 int len;
642 FRAME_PTR f = XFRAME (frame);
644 if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
645 return;
647 /* Do we have more than one visible frame on this X display? */
649 Lisp_Object tail;
651 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
653 FRAME_PTR tf = XFRAME (XCONS (tail)->car);
655 if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
656 && !FRAME_MINIBUF_ONLY_P (tf)
657 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
658 break;
661 multiple_frames = CONSP (tail);
664 obuf = current_buffer;
665 Fset_buffer (XWINDOW (f->selected_window)->buffer);
666 fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
667 frame_title_ptr = frame_title_buf;
668 len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
669 0, sizeof (frame_title_buf), fmt);
670 frame_title_ptr = 0;
671 set_buffer_internal (obuf);
672 /* Set the name only if it's changed. This avoids consing
673 in the common case where it hasn't. (If it turns out that we've
674 already wasted too much time by walking through the list with
675 display_mode_element, then we might need to optimize at a higher
676 level than this.) */
677 if (! STRINGP (f->name) || XSTRING (f->name)->size != len
678 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
679 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
681 #else
682 #define frame_title_ptr ((char *)0)
683 #define store_frame_title(str, mincol, maxcol) 0
684 #endif
686 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
687 This can call eval. */
689 void
690 prepare_menu_bars ()
692 register struct window *w = XWINDOW (selected_window);
693 int all_windows;
694 struct gcpro gcpro1, gcpro2;
696 all_windows = (update_mode_lines || buffer_shared > 1
697 || windows_or_buffers_changed);
699 /* Update all frame titles based on their buffer names, etc.
700 We do this before the menu bars so that the buffer-menu
701 will show the up-to-date frame titles.
703 This used to be done after the menu bars, for a reason that
704 was stated as follows but which I do not understand:
705 "We do this after the menu bars so that the frame will first
706 create its menu bar using the name `emacs' if no other name
707 has yet been specified."
708 I think that is no longer a concern. */
709 #ifdef HAVE_WINDOW_SYSTEM
710 if (windows_or_buffers_changed)
712 Lisp_Object tail, frame;
714 FOR_EACH_FRAME (tail, frame)
715 if (FRAME_VISIBLE_P (XFRAME (frame))
716 || FRAME_ICONIFIED_P (XFRAME (frame)))
717 x_consider_frame_title (frame);
719 #endif
721 /* Update the menu bar item lists, if appropriate.
722 This has to be done before any actual redisplay
723 or generation of display lines. */
724 if (all_windows)
726 Lisp_Object tail, frame;
727 int count = specpdl_ptr - specpdl;
729 record_unwind_protect (Fstore_match_data, Fmatch_data ());
731 FOR_EACH_FRAME (tail, frame)
733 /* If a window on this frame changed size,
734 report that to the user and clear the size-change flag. */
735 if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
737 Lisp_Object functions;
738 /* Clear flag first in case we get error below. */
739 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
740 functions = Vwindow_size_change_functions;
741 GCPRO2 (tail, functions);
742 while (CONSP (functions))
744 call1 (XCONS (functions)->car, frame);
745 functions = XCONS (functions)->cdr;
747 UNGCPRO;
749 GCPRO1 (tail);
750 update_menu_bar (XFRAME (frame), 0);
751 UNGCPRO;
754 unbind_to (count, Qnil);
756 else
757 update_menu_bar (selected_frame, 1);
760 /* Do a frame update, taking possible shortcuts into account.
761 This is the main external entry point for redisplay.
763 If the last redisplay displayed an echo area message and that
764 message is no longer requested, we clear the echo area
765 or bring back the minibuffer if that is in use.
767 Do not call eval from within this function.
768 Calls to eval after the call to echo_area_display would confuse
769 the display_line mechanism and would cause a crash.
770 Calls to eval before that point will work most of the time,
771 but can still lose, because this function
772 can be called from signal handlers; with alarms set up;
773 or with synchronous processes running.
775 See Fcall_process; if you called it from here, it could be
776 entered recursively. */
778 static int do_verify_charstarts;
780 /* Counter is used to clear the face cache
781 no more than once ever 1000 redisplays. */
782 static int clear_face_cache_count;
784 /* Record the previous terminal frame we displayed. */
785 static FRAME_PTR previous_terminal_frame;
787 void
788 redisplay ()
790 register struct window *w = XWINDOW (selected_window);
791 register int pause;
792 int must_finish = 0;
793 int all_windows;
794 register int tlbufpos, tlendpos;
795 struct position pos;
797 if (noninteractive)
798 return;
800 #ifdef MULTI_FRAME
801 if (FRAME_TERMCAP_P (selected_frame)
802 && previous_terminal_frame != selected_frame)
804 /* Since frames on an ASCII terminal share the same display area,
805 displaying a different frame means redisplay the whole thing. */
806 windows_or_buffers_changed++;
807 SET_FRAME_GARBAGED (selected_frame);
808 XSETFRAME (Vterminal_frame, selected_frame);
810 previous_terminal_frame = selected_frame;
811 #endif
813 /* Set the visible flags for all frames.
814 Do this before checking for resized or garbaged frames; they want
815 to know if their frames are visible.
816 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
818 Lisp_Object tail, frame;
820 FOR_EACH_FRAME (tail, frame)
822 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
824 /* Clear out all the display lines in which we will generate the
825 glyphs to display. */
826 init_desired_glyphs (XFRAME (frame));
830 /* Notice any pending interrupt request to change frame size. */
831 do_pending_window_change ();
833 if (frame_garbaged)
835 redraw_garbaged_frames ();
836 frame_garbaged = 0;
839 prepare_menu_bars ();
841 if (windows_or_buffers_changed)
842 update_mode_lines++;
844 /* Detect case that we need to write a star in the mode line. */
845 if (XFASTINT (w->last_modified) < MODIFF
846 && XFASTINT (w->last_modified) <= SAVE_MODIFF)
848 w->update_mode_line = Qt;
849 if (buffer_shared > 1)
850 update_mode_lines++;
853 /* If %c is in use, update it if needed. */
854 if (!NILP (w->column_number_displayed)
855 /* This alternative quickly identifies a common case
856 where no change is needed. */
857 && !(PT == XFASTINT (w->last_point)
858 && XFASTINT (w->last_modified) >= MODIFF)
859 && XFASTINT (w->column_number_displayed) != current_column ())
860 w->update_mode_line = Qt;
862 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
864 all_windows = update_mode_lines || buffer_shared > 1;
866 /* If specs for an arrow have changed, do thorough redisplay
867 to ensure we remove any arrow that should no longer exist. */
868 if (! EQ (Voverlay_arrow_position, last_arrow_position)
869 || ! EQ (Voverlay_arrow_string, last_arrow_string))
870 all_windows = 1;
872 /* Normally the message* functions will have already displayed and
873 updated the echo area, but the frame may have been trashed, or
874 the update may have been preempted, so display the echo area
875 again here. */
876 if (echo_area_glyphs || previous_echo_glyphs)
878 echo_area_display ();
879 must_finish = 1;
882 /* If showing region, and mark has changed, must redisplay whole window. */
883 if (((!NILP (Vtransient_mark_mode)
884 && !NILP (XBUFFER (w->buffer)->mark_active))
885 != !NILP (w->region_showing))
886 || (!NILP (w->region_showing)
887 && !EQ (w->region_showing,
888 Fmarker_position (XBUFFER (w->buffer)->mark))))
889 this_line_bufpos = -1;
891 tlbufpos = this_line_bufpos;
892 tlendpos = this_line_endpos;
893 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
894 && !current_buffer->clip_changed
895 && FRAME_VISIBLE_P (XFRAME (w->frame))
896 /* Make sure recorded data applies to current buffer, etc */
897 && this_line_buffer == current_buffer
898 && current_buffer == XBUFFER (w->buffer)
899 && NILP (w->force_start)
900 /* Point must be on the line that we have info recorded about */
901 && PT >= tlbufpos
902 && PT <= Z - tlendpos
903 /* All text outside that line, including its final newline,
904 must be unchanged */
905 && (XFASTINT (w->last_modified) >= MODIFF
906 || (beg_unchanged >= tlbufpos - 1
907 && GPT >= tlbufpos
908 /* If selective display, can't optimize
909 if the changes start at the beginning of the line. */
910 && ((INTEGERP (current_buffer->selective_display)
911 && XINT (current_buffer->selective_display) > 0
912 ? (beg_unchanged >= tlbufpos
913 && GPT > tlbufpos)
914 : 1))
915 && end_unchanged >= tlendpos
916 && Z - GPT >= tlendpos)))
918 if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n'
919 && (tlbufpos == ZV
920 || FETCH_CHAR (tlbufpos) == '\n'))
921 /* Former continuation line has disappeared by becoming empty */
922 goto cancel;
923 else if (XFASTINT (w->last_modified) < MODIFF
924 || MINI_WINDOW_P (w))
926 cursor_vpos = -1;
927 overlay_arrow_seen = 0;
928 zv_strings_seen = 0;
929 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
930 pos_tab_offset (w, tlbufpos));
931 /* If line contains point, is not continued,
932 and ends at same distance from eob as before, we win */
933 if (cursor_vpos >= 0 && this_line_bufpos
934 && this_line_endpos == tlendpos)
936 /* If this is not the window's last line,
937 we must adjust the charstarts of the lines below. */
938 if (this_line_vpos + 1
939 < XFASTINT (w->top) + window_internal_height (w))
941 int left = XFASTINT (w->left);
942 int *charstart_next_line
943 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
944 int adjust;
946 if (Z - tlendpos == ZV)
947 /* This line ends at end of (accessible part of) buffer.
948 There is no newline to count. */
949 adjust = Z - tlendpos - charstart_next_line[left];
950 else
951 /* This line ends in a newline.
952 Must take account of the newline and the rest of the
953 text that follows. */
954 adjust = Z - tlendpos + 1 - charstart_next_line[left];
956 adjust_window_charstarts (w, this_line_vpos, adjust);
959 if (XFASTINT (w->width) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
960 preserve_other_columns (w);
961 goto update;
963 else
964 goto cancel;
966 else if (PT == XFASTINT (w->last_point)
967 /* Make sure the cursor was last displayed
968 in this window. Otherwise we have to reposition it. */
969 && XINT (w->top) <= FRAME_CURSOR_Y (selected_frame)
970 && (XINT (w->top) + XINT (w->height)
971 > FRAME_CURSOR_Y (selected_frame)))
973 if (!must_finish)
975 do_pending_window_change ();
976 return;
978 goto update;
980 /* If highlighting the region, or if the cursor is in the echo area,
981 then we can't just move the cursor. */
982 else if (! (!NILP (Vtransient_mark_mode)
983 && !NILP (current_buffer->mark_active))
984 && NILP (w->region_showing)
985 && !cursor_in_echo_area)
987 pos = *compute_motion (tlbufpos, 0,
988 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
990 PT, 2, - (1 << (BITS_PER_SHORT - 1)),
991 window_internal_width (w) - 1,
992 XINT (w->hscroll),
993 pos_tab_offset (w, tlbufpos), w);
994 if (pos.vpos < 1)
996 int width = window_internal_width (w) - 1;
997 FRAME_CURSOR_X (selected_frame)
998 = XFASTINT (w->left) + minmax (0, pos.hpos, width);
999 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
1000 goto update;
1002 else
1003 goto cancel;
1005 cancel:
1006 /* Text changed drastically or point moved off of line */
1007 cancel_line (this_line_vpos, selected_frame);
1010 this_line_bufpos = 0;
1011 all_windows |= buffer_shared > 1;
1013 clear_face_cache_count++;
1015 if (all_windows)
1017 Lisp_Object tail, frame;
1019 #ifdef HAVE_FACES
1020 /* Clear the face cache, only when we do a full redisplay
1021 and not too often either. */
1022 if (clear_face_cache_count > 1000)
1024 clear_face_cache ();
1025 clear_face_cache_count = 0;
1027 #endif
1029 /* Recompute # windows showing selected buffer.
1030 This will be incremented each time such a window is displayed. */
1031 buffer_shared = 0;
1033 FOR_EACH_FRAME (tail, frame)
1035 FRAME_PTR f = XFRAME (frame);
1036 if (! FRAME_TERMCAP_P (f) || f == selected_frame)
1039 /* Mark all the scroll bars to be removed; we'll redeem the ones
1040 we want when we redisplay their windows. */
1041 if (condemn_scroll_bars_hook)
1042 (*condemn_scroll_bars_hook) (f);
1044 if (FRAME_VISIBLE_P (f))
1045 redisplay_windows (FRAME_ROOT_WINDOW (f));
1047 /* Any scroll bars which redisplay_windows should have nuked
1048 should now go away. */
1049 if (judge_scroll_bars_hook)
1050 (*judge_scroll_bars_hook) (f);
1054 else if (FRAME_VISIBLE_P (selected_frame))
1056 redisplay_window (selected_window, 1);
1057 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
1058 preserve_other_columns (w);
1061 update:
1062 /* Prevent various kinds of signals during display update.
1063 stdio is not robust about handling signals,
1064 which can cause an apparent I/O error. */
1065 if (interrupt_input)
1066 unrequest_sigio ();
1067 stop_polling ();
1069 #ifdef MULTI_FRAME
1070 if (all_windows)
1072 Lisp_Object tail;
1074 pause = 0;
1076 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1078 FRAME_PTR f;
1080 if (!FRAMEP (XCONS (tail)->car))
1081 continue;
1083 f = XFRAME (XCONS (tail)->car);
1085 if ((! FRAME_TERMCAP_P (f) || f == selected_frame)
1086 && FRAME_VISIBLE_P (f))
1088 pause |= update_frame (f, 0, 0);
1089 if (!pause)
1091 mark_window_display_accurate (f->root_window, 1);
1092 if (frame_up_to_date_hook != 0)
1093 (*frame_up_to_date_hook) (f);
1098 else
1099 #endif /* MULTI_FRAME */
1101 if (FRAME_VISIBLE_P (selected_frame))
1102 pause = update_frame (selected_frame, 0, 0);
1103 else
1104 pause = 0;
1106 /* We may have called echo_area_display at the top of this
1107 function. If the echo area is on another frame, that may
1108 have put text on a frame other than the selected one, so the
1109 above call to update_frame would not have caught it. Catch
1110 it here. */
1112 Lisp_Object mini_window;
1113 FRAME_PTR mini_frame;
1115 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
1116 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
1118 if (mini_frame != selected_frame
1119 && ! FRAME_TERMCAP_P (mini_frame))
1120 pause |= update_frame (mini_frame, 0, 0);
1124 /* If frame does not match, prevent doing single-line-update next time.
1125 Also, don't forget to check every line to update the arrow. */
1126 if (pause)
1128 this_line_bufpos = 0;
1129 if (!NILP (last_arrow_position))
1131 last_arrow_position = Qt;
1132 last_arrow_string = Qt;
1134 /* If we pause after scrolling, some lines in current_frame
1135 may be null, so preserve_other_columns won't be able to
1136 preserve all the vertical-bar separators. So, avoid using it
1137 in that case. */
1138 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
1139 update_mode_lines = 1;
1142 /* Now text on frame agrees with windows, so
1143 put info into the windows for partial redisplay to follow */
1145 if (!pause)
1147 register struct buffer *b = XBUFFER (w->buffer);
1149 blank_end_of_window = 0;
1150 unchanged_modified = BUF_MODIFF (b);
1151 beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
1152 end_unchanged = BUF_Z (b) - BUF_GPT (b);
1154 XSETFASTINT (w->last_point, BUF_PT (b));
1155 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
1156 XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
1158 if (all_windows)
1159 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
1160 else
1162 b->clip_changed = 0;
1163 w->update_mode_line = Qnil;
1164 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
1165 w->window_end_valid = w->buffer;
1166 last_arrow_position = Voverlay_arrow_position;
1167 last_arrow_string = Voverlay_arrow_string;
1168 if (do_verify_charstarts)
1169 verify_charstarts (w);
1170 if (frame_up_to_date_hook != 0)
1171 (*frame_up_to_date_hook) (selected_frame);
1173 update_mode_lines = 0;
1174 windows_or_buffers_changed = 0;
1177 /* Start SIGIO interrupts coming again.
1178 Having them off during the code above
1179 makes it less likely one will discard output,
1180 but not impossible, since there might be stuff
1181 in the system buffer here.
1182 But it is much hairier to try to do anything about that. */
1184 if (interrupt_input)
1185 request_sigio ();
1186 start_polling ();
1188 /* Change frame size now if a change is pending. */
1189 do_pending_window_change ();
1191 /* If we just did a pending size change, redisplay again
1192 for the new size. */
1193 if (windows_or_buffers_changed && !pause)
1194 redisplay ();
1197 /* Redisplay, but leave alone any recent echo area message
1198 unless another message has been requested in its place.
1200 This is useful in situations where you need to redisplay but no
1201 user action has occurred, making it inappropriate for the message
1202 area to be cleared. See tracking_off and
1203 wait_reading_process_input for examples of these situations. */
1205 redisplay_preserve_echo_area ()
1207 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
1209 echo_area_glyphs = previous_echo_glyphs;
1210 redisplay ();
1211 echo_area_glyphs = 0;
1213 else
1214 redisplay ();
1217 void
1218 mark_window_display_accurate (window, flag)
1219 Lisp_Object window;
1220 int flag;
1222 register struct window *w;
1224 for (;!NILP (window); window = w->next)
1226 if (!WINDOWP (window)) abort ();
1227 w = XWINDOW (window);
1229 if (!NILP (w->buffer))
1231 XSETFASTINT (w->last_modified,
1232 !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
1234 /* Record if we are showing a region, so can make sure to
1235 update it fully at next redisplay. */
1236 w->region_showing = (!NILP (Vtransient_mark_mode)
1237 && !NILP (XBUFFER (w->buffer)->mark_active)
1238 ? Fmarker_position (XBUFFER (w->buffer)->mark)
1239 : Qnil);
1242 w->window_end_valid = w->buffer;
1243 w->update_mode_line = Qnil;
1244 if (!NILP (w->buffer))
1245 XBUFFER (w->buffer)->clip_changed = 0;
1247 if (!NILP (w->vchild))
1248 mark_window_display_accurate (w->vchild, flag);
1249 if (!NILP (w->hchild))
1250 mark_window_display_accurate (w->hchild, flag);
1253 if (flag)
1255 last_arrow_position = Voverlay_arrow_position;
1256 last_arrow_string = Voverlay_arrow_string;
1258 else
1260 /* t is unequal to any useful value of Voverlay_arrow_... */
1261 last_arrow_position = Qt;
1262 last_arrow_string = Qt;
1266 /* Update the menu bar item list for frame F.
1267 This has to be done before we start to fill in any display lines,
1268 because it can call eval.
1270 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1272 static void
1273 update_menu_bar (f, save_match_data)
1274 FRAME_PTR f;
1275 int save_match_data;
1277 struct buffer *old = current_buffer;
1278 Lisp_Object window;
1279 register struct window *w;
1281 window = FRAME_SELECTED_WINDOW (f);
1282 w = XWINDOW (window);
1284 if (update_mode_lines)
1285 w->update_mode_line = Qt;
1287 if (FRAME_X_P (f)
1289 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1290 FRAME_EXTERNAL_MENU_BAR (f)
1291 #else
1292 FRAME_MENU_BAR_LINES (f) > 0
1293 #endif
1294 : FRAME_MENU_BAR_LINES (f) > 0)
1296 /* If the user has switched buffers or windows, we need to
1297 recompute to reflect the new bindings. But we'll
1298 recompute when update_mode_lines is set too; that means
1299 that people can use force-mode-line-update to request
1300 that the menu bar be recomputed. The adverse effect on
1301 the rest of the redisplay algorithm is about the same as
1302 windows_or_buffers_changed anyway. */
1303 if (windows_or_buffers_changed
1304 || !NILP (w->update_mode_line)
1305 || (XFASTINT (w->last_modified) < MODIFF
1306 && (XFASTINT (w->last_modified)
1307 <= BUF_SAVE_MODIFF (XBUFFER (w->buffer))))
1308 || ((!NILP (Vtransient_mark_mode)
1309 && !NILP (XBUFFER (w->buffer)->mark_active))
1310 != !NILP (w->region_showing)))
1312 struct buffer *prev = current_buffer;
1313 int count = specpdl_ptr - specpdl;
1315 set_buffer_internal_1 (XBUFFER (w->buffer));
1316 if (save_match_data)
1317 record_unwind_protect (Fstore_match_data, Fmatch_data ());
1318 if (NILP (Voverriding_local_map_menu_flag))
1320 specbind (Qoverriding_terminal_local_map, Qnil);
1321 specbind (Qoverriding_local_map, Qnil);
1324 /* Run the Lucid hook. */
1325 call1 (Vrun_hooks, Qactivate_menubar_hook);
1326 /* If it has changed current-menubar from previous value,
1327 really recompute the menubar from the value. */
1328 if (! NILP (Vlucid_menu_bar_dirty_flag))
1329 call0 (Qrecompute_lucid_menubar);
1330 call1 (Vrun_hooks, Qmenu_bar_update_hook);
1331 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1332 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1333 if (FRAME_X_P (f))
1334 set_frame_menubar (f, 0, 0);
1335 #endif /* USE_X_TOOLKIT || HAVE_NTGUI */
1337 unbind_to (count, Qnil);
1338 set_buffer_internal_1 (prev);
1343 int do_id = 1;
1345 /* Redisplay WINDOW and its subwindows and siblings. */
1347 static void
1348 redisplay_windows (window)
1349 Lisp_Object window;
1351 for (; !NILP (window); window = XWINDOW (window)->next)
1352 redisplay_window (window, 0);
1355 /* Redisplay window WINDOW and its subwindows. */
1357 static void
1358 redisplay_window (window, just_this_one)
1359 Lisp_Object window;
1360 int just_this_one;
1362 register struct window *w = XWINDOW (window);
1363 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1364 int height;
1365 register int lpoint = PT;
1366 struct buffer *old = current_buffer;
1367 register int width = window_internal_width (w) - 1;
1368 register int startp;
1369 register int hscroll = XINT (w->hscroll);
1370 struct position pos;
1371 int opoint = PT;
1372 int tem;
1373 int update_mode_line;
1374 struct Lisp_Char_Table *dp = window_display_table (w);
1376 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1378 /* If this is a combination window, do its children; that's all. */
1380 if (!NILP (w->vchild))
1382 redisplay_windows (w->vchild);
1383 return;
1385 if (!NILP (w->hchild))
1387 redisplay_windows (w->hchild);
1388 return;
1390 if (NILP (w->buffer))
1391 abort ();
1393 height = window_internal_height (w);
1394 update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
1395 if (XBUFFER (w->buffer)->clip_changed)
1396 update_mode_line = 1;
1398 if (MINI_WINDOW_P (w))
1400 if (w == XWINDOW (echo_area_window) && echo_area_glyphs)
1401 /* We've already displayed the echo area glyphs in this window. */
1402 goto finish_scroll_bars;
1403 else if (w != XWINDOW (minibuf_window))
1405 /* This is a minibuffer, but it's not the currently active one,
1406 so clear it. */
1407 int vpos = XFASTINT (w->top);
1408 int i;
1410 for (i = 0; i < height; i++)
1412 get_display_line (f, vpos + i, 0);
1413 display_string (w, vpos + i, "", 0, 0, 0, 1, 0, width);
1416 goto finish_scroll_bars;
1420 /* Otherwise set up data on this window; select its buffer and point value */
1422 if (update_mode_line)
1423 set_buffer_internal_1 (XBUFFER (w->buffer));
1424 else
1425 set_buffer_temp (XBUFFER (w->buffer));
1427 opoint = PT;
1429 /* If %c is in mode line, update it if needed. */
1430 if (!NILP (w->column_number_displayed)
1431 /* This alternative quickly identifies a common case
1432 where no change is needed. */
1433 && !(PT == XFASTINT (w->last_point)
1434 && XFASTINT (w->last_modified) >= MODIFF)
1435 && XFASTINT (w->column_number_displayed) != current_column ())
1436 update_mode_line = 1;
1438 /* Count number of windows showing the selected buffer.
1439 An indirect buffer counts as its base buffer. */
1441 if (!just_this_one)
1443 struct buffer *current_base, *window_base;
1444 current_base = current_buffer;
1445 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
1446 if (current_base->base_buffer)
1447 current_base = current_base->base_buffer;
1448 if (window_base->base_buffer)
1449 window_base = window_base->base_buffer;
1450 if (current_base == window_base)
1451 buffer_shared++;
1454 /* POINT refers normally to the selected window.
1455 For any other window, set up appropriate value. */
1457 if (!EQ (window, selected_window))
1459 int new_pt = marker_position (w->pointm);
1460 if (new_pt < BEGV)
1462 new_pt = BEGV;
1463 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1465 else if (new_pt > (ZV - 1))
1467 new_pt = ZV;
1468 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1470 /* We don't use SET_PT so that the point-motion hooks don't run. */
1471 BUF_PT (current_buffer) = new_pt;
1474 /* If any of the character widths specified in the display table
1475 have changed, invalidate the width run cache. It's true that this
1476 may be a bit late to catch such changes, but the rest of
1477 redisplay goes (non-fatally) haywire when the display table is
1478 changed, so why should we worry about doing any better? */
1479 if (current_buffer->width_run_cache)
1481 struct Lisp_Char_Table *disptab = buffer_display_table ();
1483 if (! disptab_matches_widthtab (disptab,
1484 XVECTOR (current_buffer->width_table)))
1486 invalidate_region_cache (current_buffer,
1487 current_buffer->width_run_cache,
1488 BEG, Z);
1489 recompute_width_table (current_buffer, disptab);
1493 /* If window-start is screwed up, choose a new one. */
1494 if (XMARKER (w->start)->buffer != current_buffer)
1495 goto recenter;
1497 startp = marker_position (w->start);
1499 /* Handle case where place to start displaying has been specified,
1500 unless the specified location is outside the accessible range. */
1501 if (!NILP (w->force_start))
1503 /* Forget any recorded base line for line number display. */
1504 w->base_line_number = Qnil;
1505 /* Redisplay the mode line. Select the buffer properly for that.
1506 Also, run the hook window-scroll-functions
1507 because we have scrolled. */
1508 if (!update_mode_line
1509 || ! NILP (Vwindow_scroll_functions))
1511 Lisp_Object temp[3];
1513 set_buffer_temp (old);
1514 set_buffer_internal_1 (XBUFFER (w->buffer));
1515 update_mode_line = 1;
1516 w->update_mode_line = Qt;
1517 if (! NILP (Vwindow_scroll_functions))
1518 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1519 make_number (startp));
1521 w->force_start = Qnil;
1522 XSETFASTINT (w->last_modified, 0);
1523 if (startp < BEGV) startp = BEGV;
1524 if (startp > ZV) startp = ZV;
1525 try_window (window, startp);
1526 if (cursor_vpos < 0)
1528 /* If point does not appear, move point so it does appear */
1529 pos = *compute_motion (startp, 0,
1530 (((EQ (window, minibuf_window)
1531 && startp == BEG)
1532 ? minibuf_prompt_width : 0)
1533 + (hscroll ? 1 - hscroll : 0)),
1535 ZV, height / 2,
1536 - (1 << (BITS_PER_SHORT - 1)),
1537 width, hscroll, pos_tab_offset (w, startp), w);
1538 BUF_PT (current_buffer) = pos.bufpos;
1539 if (w != XWINDOW (selected_window))
1540 Fset_marker (w->pointm, make_number (PT), Qnil);
1541 else
1543 if (current_buffer == old)
1544 lpoint = PT;
1545 FRAME_CURSOR_X (f) = (XFASTINT (w->left)
1546 + minmax (0, pos.hpos, width));
1547 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1549 /* If we are highlighting the region,
1550 then we just changed the region, so redisplay to show it. */
1551 if (!NILP (Vtransient_mark_mode)
1552 && !NILP (current_buffer->mark_active))
1554 cancel_my_columns (XWINDOW (window));
1555 try_window (window, startp);
1558 goto done;
1561 /* Handle case where text has not changed, only point,
1562 and it has not moved off the frame */
1564 /* This code is not used for minibuffer for the sake of
1565 the case of redisplaying to replace an echo area message;
1566 since in that case the minibuffer contents per se are usually unchanged.
1567 This code is of no real use in the minibuffer since
1568 the handling of this_line_bufpos, etc.,
1569 in redisplay handles the same cases. */
1571 if (XFASTINT (w->last_modified) >= MODIFF
1572 && PT >= startp && !current_buffer->clip_changed
1573 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
1574 /* If force-mode-line-update was called, really redisplay;
1575 that's how redisplay is forced after e.g. changing
1576 buffer-invisibility-spec. */
1577 && NILP (w->update_mode_line)
1578 /* Can't use this case if highlighting a region. */
1579 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1580 && NILP (w->region_showing)
1581 /* If end pos is out of date, scroll bar and percentage will be wrong */
1582 && INTEGERP (w->window_end_vpos)
1583 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
1584 && !EQ (window, minibuf_window))
1586 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
1587 PT, height, 0, width, hscroll,
1588 pos_tab_offset (w, startp), w);
1590 if (pos.vpos < height)
1592 /* Ok, point is still on frame */
1593 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1595 /* These variables are supposed to be origin 1 */
1596 FRAME_CURSOR_X (f) = (XFASTINT (w->left)
1597 + minmax (0, pos.hpos, width));
1598 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1600 /* This doesn't do the trick, because if a window to the right of
1601 this one must be redisplayed, this does nothing because there
1602 is nothing in DesiredFrame yet, and then the other window is
1603 redisplayed, making likes that are empty in this window's columns.
1604 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1605 preserve_my_columns (w);
1607 goto done;
1609 /* Don't bother trying redisplay with same start;
1610 we already know it will lose */
1612 /* If current starting point was originally the beginning of a line
1613 but no longer is, find a new starting point. */
1614 else if (!NILP (w->start_at_line_beg)
1615 && !(startp <= BEGV
1616 || FETCH_CHAR (startp - 1) == '\n'))
1618 goto recenter;
1620 else if (just_this_one && !MINI_WINDOW_P (w)
1621 && PT >= startp
1622 && XFASTINT (w->last_modified)
1623 /* or else vmotion on first line won't work. */
1624 && ! NILP (w->start_at_line_beg)
1625 && ! EQ (w->window_end_valid, Qnil)
1626 && do_id && !current_buffer->clip_changed
1627 && !blank_end_of_window
1628 && XFASTINT (w->width) == FRAME_WIDTH (f)
1629 /* Can't use this case if highlighting a region. */
1630 && !(!NILP (Vtransient_mark_mode)
1631 && !NILP (current_buffer->mark_active))
1632 /* Don't use try_window_id if newline
1633 doesn't display as the end of a line. */
1634 && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
1635 && NILP (w->region_showing)
1636 && EQ (last_arrow_position, Voverlay_arrow_position)
1637 && EQ (last_arrow_string, Voverlay_arrow_string)
1638 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
1639 && tem != -2)
1641 /* tem > 0 means success. tem == -1 means choose new start.
1642 tem == -2 means try again with same start,
1643 and nothing but whitespace follows the changed stuff.
1644 tem == 0 means try again with same start. */
1645 if (tem > 0)
1646 goto done;
1648 else if (startp >= BEGV && startp <= ZV
1649 /* Avoid starting display at end of buffer! */
1650 && (startp < ZV || startp == BEGV
1651 || (XFASTINT (w->last_modified) >= MODIFF)))
1653 /* Try to redisplay starting at same place as before */
1654 /* If point has not moved off frame, accept the results */
1655 try_window (window, startp);
1656 if (cursor_vpos >= 0)
1658 if (!just_this_one || current_buffer->clip_changed
1659 || beg_unchanged < startp)
1660 /* Forget any recorded base line for line number display. */
1661 w->base_line_number = Qnil;
1662 goto done;
1664 else
1665 cancel_my_columns (w);
1668 XSETFASTINT (w->last_modified, 0);
1669 /* Redisplay the mode line. Select the buffer properly for that. */
1670 if (!update_mode_line)
1672 set_buffer_temp (old);
1673 set_buffer_internal_1 (XBUFFER (w->buffer));
1674 update_mode_line = 1;
1675 w->update_mode_line = Qt;
1678 /* Try to scroll by specified few lines */
1680 if (scroll_step && !current_buffer->clip_changed)
1682 if (PT > startp)
1684 pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
1685 if (pos.vpos >= height)
1686 goto scroll_fail;
1689 pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
1691 if (PT >= pos.bufpos)
1693 if (! NILP (Vwindow_scroll_functions))
1694 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1695 make_number (pos.bufpos));
1696 try_window (window, pos.bufpos);
1697 if (cursor_vpos >= 0)
1699 if (!just_this_one || current_buffer->clip_changed
1700 || beg_unchanged < startp)
1701 /* Forget any recorded base line for line number display. */
1702 w->base_line_number = Qnil;
1703 goto done;
1705 else
1706 cancel_my_columns (w);
1708 scroll_fail: ;
1711 /* Finally, just choose place to start which centers point */
1713 recenter:
1714 /* Forget any previously recorded base line for line number display. */
1715 w->base_line_number = Qnil;
1717 pos = *vmotion (PT, - (height / 2), w);
1718 if (! NILP (Vwindow_scroll_functions))
1719 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1720 make_number (pos.bufpos));
1721 try_window (window, pos.bufpos);
1723 startp = marker_position (w->start);
1724 w->start_at_line_beg
1725 = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
1727 done:
1728 if ((update_mode_line
1729 /* If window not full width, must redo its mode line
1730 if the window to its side is being redone */
1731 || (!just_this_one && width < FRAME_WIDTH (f) - 1)
1732 || INTEGERP (w->base_line_pos)
1733 || (!NILP (w->column_number_displayed)
1734 && XFASTINT (w->column_number_displayed) != current_column ()))
1735 && height != XFASTINT (w->height))
1736 display_mode_line (w);
1737 if (! line_number_displayed
1738 && ! BUFFERP (w->base_line_pos))
1740 w->base_line_pos = Qnil;
1741 w->base_line_number = Qnil;
1744 /* When we reach a frame's selected window, redo the frame's menu bar. */
1745 if (update_mode_line
1746 && (FRAME_X_P (f)
1748 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1749 FRAME_EXTERNAL_MENU_BAR (f)
1750 #else
1751 FRAME_MENU_BAR_LINES (f) > 0
1752 #endif
1753 : FRAME_MENU_BAR_LINES (f) > 0)
1754 && EQ (FRAME_SELECTED_WINDOW (f), window))
1755 display_menu_bar (w);
1757 finish_scroll_bars:
1758 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1760 int start, end, whole;
1762 /* Calculate the start and end positions for the current window.
1763 At some point, it would be nice to choose between scrollbars
1764 which reflect the whole buffer size, with special markers
1765 indicating narrowing, and scrollbars which reflect only the
1766 visible region.
1768 Note that minibuffers sometimes aren't displaying any text. */
1769 if (! MINI_WINDOW_P (w)
1770 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
1772 whole = ZV - BEGV;
1773 start = marker_position (w->start) - BEGV;
1774 /* I don't think this is guaranteed to be right. For the
1775 moment, we'll pretend it is. */
1776 end = (Z - XINT (w->window_end_pos)) - BEGV;
1778 if (end < start) end = start;
1779 if (whole < (end - start)) whole = end - start;
1781 else
1782 start = end = whole = 0;
1784 /* Indicate what this scroll bar ought to be displaying now. */
1785 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
1787 /* Note that we actually used the scroll bar attached to this window,
1788 so it shouldn't be deleted at the end of redisplay. */
1789 (*redeem_scroll_bar_hook) (w);
1792 BUF_PT (current_buffer) = opoint;
1793 if (update_mode_line)
1794 set_buffer_internal_1 (old);
1795 else
1796 set_buffer_temp (old);
1797 BUF_PT (current_buffer) = lpoint;
1800 /* Do full redisplay on one window, starting at position `pos'. */
1802 static void
1803 try_window (window, pos)
1804 Lisp_Object window;
1805 register int pos;
1807 register struct window *w = XWINDOW (window);
1808 register int height = window_internal_height (w);
1809 register int vpos = XFASTINT (w->top);
1810 register int last_text_vpos = vpos;
1811 int tab_offset = pos_tab_offset (w, pos);
1812 FRAME_PTR f = XFRAME (w->frame);
1813 int width = window_internal_width (w) - 1;
1814 struct position val;
1816 Fset_marker (w->start, make_number (pos), Qnil);
1817 cursor_vpos = -1;
1818 overlay_arrow_seen = 0;
1819 zv_strings_seen = 0;
1820 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
1822 while (--height >= 0)
1824 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
1825 tab_offset += width;
1826 /* For the first line displayed, display_text_line
1827 subtracts the prompt width from the tab offset.
1828 But it does not affect the value of our variable tab_offset.
1829 So we do the subtraction again,
1830 for the sake of continuation lines of that first line. */
1831 if (MINI_WINDOW_P (w) && vpos == XFASTINT (w->top))
1832 tab_offset -= minibuf_prompt_width;
1834 if (val.vpos) tab_offset = 0;
1835 vpos++;
1836 if (pos != val.bufpos)
1838 int invis = 0;
1839 #ifdef USE_TEXT_PROPERTIES
1840 Lisp_Object invis_prop;
1841 invis_prop = Fget_char_property (val.bufpos-1, Qinvisible, window);
1842 invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
1843 #endif
1845 last_text_vpos
1846 /* Next line, unless prev line ended in end of buffer with no cr */
1847 = vpos - (val.vpos
1848 && (FETCH_CHAR (val.bufpos - 1) != '\n' || invis));
1850 pos = val.bufpos;
1853 /* If last line is continued in middle of character,
1854 include the split character in the text considered on the frame */
1855 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
1856 pos++;
1858 /* If bottom just moved off end of frame, change mode line percentage. */
1859 if (XFASTINT (w->window_end_pos) == 0
1860 && Z != pos)
1861 w->update_mode_line = Qt;
1863 /* Say where last char on frame will be, once redisplay is finished. */
1864 XSETFASTINT (w->window_end_pos, Z - pos);
1865 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
1866 /* But that is not valid info until redisplay finishes. */
1867 w->window_end_valid = Qnil;
1870 /* Try to redisplay when buffer is modified locally,
1871 computing insert/delete line to preserve text outside
1872 the bounds of the changes.
1873 Return 1 if successful, 0 if if cannot tell what to do,
1874 or -1 to tell caller to find a new window start,
1875 or -2 to tell caller to do normal redisplay with same window start. */
1877 static int
1878 try_window_id (window)
1879 Lisp_Object window;
1881 int pos;
1882 register struct window *w = XWINDOW (window);
1883 register int height = window_internal_height (w);
1884 FRAME_PTR f = XFRAME (w->frame);
1885 int top = XFASTINT (w->top);
1886 int start = marker_position (w->start);
1887 int width = window_internal_width (w) - 1;
1888 int hscroll = XINT (w->hscroll);
1889 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1890 int did_motion;
1891 register int vpos;
1892 register int i, tem;
1893 int last_text_vpos = 0;
1894 int stop_vpos;
1895 int selective = (INTEGERP (current_buffer->selective_display)
1896 ? XINT (current_buffer->selective_display)
1897 : !NILP (current_buffer->selective_display) ? -1 : 0);
1899 struct position val, bp, ep, xp, pp;
1900 int scroll_amount = 0;
1901 int delta;
1902 int tab_offset, epto, old_tick;
1904 if (GPT - BEG < beg_unchanged)
1905 beg_unchanged = GPT - BEG;
1906 if (Z - GPT < end_unchanged)
1907 end_unchanged = Z - GPT;
1909 if (beg_unchanged + BEG < start)
1910 return 0; /* Give up if changes go above top of window */
1912 /* Find position before which nothing is changed. */
1913 bp = *compute_motion (start, 0, lmargin, 0,
1914 min (ZV, beg_unchanged + BEG), height, 0,
1915 width, hscroll, pos_tab_offset (w, start), w);
1916 if (bp.vpos >= height)
1918 if (PT < bp.bufpos)
1920 /* All changes are beyond the window end, and point is on the screen.
1921 We don't need to change the text at all.
1922 But we need to update window_end_pos to account for
1923 any change in buffer size. */
1924 bp = *compute_motion (start, 0, lmargin, 0,
1925 ZV, height, 0,
1926 width, hscroll, pos_tab_offset (w, start), w);
1927 XSETFASTINT (w->window_end_vpos, height);
1928 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
1929 goto findpoint;
1931 return 0;
1934 vpos = bp.vpos;
1936 /* Find beginning of that frame line. Must display from there. */
1937 bp = *vmotion (bp.bufpos, 0, w);
1939 pos = bp.bufpos;
1940 val.hpos = lmargin;
1941 if (pos < start)
1942 return -1;
1944 did_motion = 0;
1945 /* If about to start displaying at the beginning of a continuation line,
1946 really start with previous frame line, in case it was not
1947 continued when last redisplayed */
1948 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
1950 /* Likewise if we have to worry about selective display. */
1951 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
1953 bp = *vmotion (bp.bufpos, -1, w);
1954 --vpos;
1955 pos = bp.bufpos;
1958 if (bp.contin && bp.hpos != lmargin)
1960 val.hpos = bp.prevhpos - width + lmargin;
1961 did_motion = 1;
1962 pos--;
1965 bp.vpos = vpos;
1967 /* Find first visible newline after which no more is changed. */
1968 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
1969 if (selective > 0)
1970 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
1971 tem = find_next_newline (tem, 1);
1973 /* Compute the cursor position after that newline. */
1974 ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
1975 height, - (1 << (BITS_PER_SHORT - 1)),
1976 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
1978 /* If changes reach past the text available on the frame,
1979 just display rest of frame. */
1980 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
1981 stop_vpos = height;
1982 else
1983 stop_vpos = ep.vpos;
1985 /* If no newline before ep, the line ep is on includes some changes
1986 that must be displayed. Make sure we don't stop before it. */
1987 /* Also, if changes reach all the way until ep.bufpos,
1988 it is possible that something was deleted after the
1989 newline before it, so the following line must be redrawn. */
1990 if (stop_vpos == ep.vpos
1991 && (ep.bufpos == BEGV
1992 || FETCH_CHAR (ep.bufpos - 1) != '\n'
1993 || ep.bufpos == Z - end_unchanged))
1994 stop_vpos = ep.vpos + 1;
1996 cursor_vpos = -1;
1997 overlay_arrow_seen = 0;
1998 zv_strings_seen = 0;
2000 /* If changes do not reach to bottom of window,
2001 figure out how much to scroll the rest of the window */
2002 if (stop_vpos < height)
2004 /* Now determine how far up or down the rest of the window has moved */
2005 epto = pos_tab_offset (w, ep.bufpos);
2006 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
2007 Z - XFASTINT (w->window_end_pos),
2008 10000, 0, width, hscroll, epto, w);
2009 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
2011 /* Is everything on frame below the changes whitespace?
2012 If so, no scrolling is really necessary. */
2013 for (i = ep.bufpos; i < xp.bufpos; i++)
2015 tem = FETCH_CHAR (i);
2016 if (tem != ' ' && tem != '\n' && tem != '\t')
2017 break;
2019 if (i == xp.bufpos)
2020 return -2;
2022 XSETFASTINT (w->window_end_vpos,
2023 XFASTINT (w->window_end_vpos) + scroll_amount);
2025 /* Before doing any scrolling, verify that point will be on frame. */
2026 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
2028 if (PT <= xp.bufpos)
2030 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
2031 PT, height, - (1 << (BITS_PER_SHORT - 1)),
2032 width, hscroll, epto, w);
2034 else
2036 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
2037 PT, height, - (1 << (BITS_PER_SHORT - 1)),
2038 width, hscroll,
2039 pos_tab_offset (w, xp.bufpos), w);
2041 if (pp.bufpos < PT || pp.vpos == height)
2042 return 0;
2043 cursor_vpos = pp.vpos + top;
2044 cursor_hpos = XFASTINT (w->left) + minmax (0, pp.hpos, width);
2047 if (stop_vpos - scroll_amount >= height
2048 || ep.bufpos == xp.bufpos)
2050 if (scroll_amount < 0)
2051 stop_vpos -= scroll_amount;
2052 scroll_amount = 0;
2053 /* In this path, we have altered window_end_vpos
2054 and not left it negative.
2055 We must make sure that, in case display is preempted
2056 before the frame changes to reflect what we do here,
2057 further updates will not come to try_window_id
2058 and assume the frame and window_end_vpos match. */
2059 blank_end_of_window = 1;
2061 else if (!scroll_amount)
2063 /* Even if we don't need to scroll, we must adjust the
2064 charstarts of subsequent lines (that we won't redisplay)
2065 according to the amount of text inserted or deleted. */
2066 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2067 int adjust = ep.bufpos - oldpos;
2068 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
2070 else if (bp.bufpos == Z - end_unchanged)
2072 /* If reprinting everything is nearly as fast as scrolling,
2073 don't bother scrolling. Can happen if lines are short. */
2074 if (scroll_cost (f, bp.vpos + top - scroll_amount,
2075 top + height - max (0, scroll_amount),
2076 scroll_amount)
2077 > xp.bufpos - bp.bufpos - 20)
2078 /* Return "try normal display with same window-start."
2079 Too bad we can't prevent further scroll-thinking. */
2080 return -2;
2081 /* If pure deletion, scroll up as many lines as possible.
2082 In common case of killing a line, this can save the
2083 following line from being overwritten by scrolling
2084 and therefore having to be redrawn. */
2085 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
2086 top + height - max (0, scroll_amount),
2087 scroll_amount, bp.bufpos);
2088 if (!tem)
2089 stop_vpos = height;
2090 else
2092 /* scroll_frame_lines did not properly adjust subsequent
2093 lines' charstarts in the case where the text of the
2094 screen line at bp.vpos has changed.
2095 (This can happen in a deletion that ends in mid-line.)
2096 To adjust properly, we need to make things constent at
2097 the position ep.
2098 So do a second adjust to make that happen.
2099 Note that stop_vpos >= ep.vpos, so it is sufficient
2100 to update the charstarts for lines at ep.vpos and below. */
2101 int oldstart
2102 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2103 adjust_window_charstarts (w, ep.vpos + top - 1,
2104 ep.bufpos - oldstart);
2107 else if (scroll_amount)
2109 /* If reprinting everything is nearly as fast as scrolling,
2110 don't bother scrolling. Can happen if lines are short. */
2111 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2112 overestimate of cost of reprinting, since xp.bufpos
2113 would end up below the bottom of the window. */
2114 if (scroll_cost (f, ep.vpos + top - scroll_amount,
2115 top + height - max (0, scroll_amount),
2116 scroll_amount)
2117 > xp.bufpos - ep.bufpos - 20)
2118 /* Return "try normal display with same window-start."
2119 Too bad we can't prevent further scroll-thinking. */
2120 return -2;
2121 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
2122 top + height - max (0, scroll_amount),
2123 scroll_amount, ep.bufpos);
2124 if (!tem) stop_vpos = height;
2128 /* In any case, do not display past bottom of window */
2129 if (stop_vpos >= height)
2131 stop_vpos = height;
2132 scroll_amount = 0;
2135 /* Handle case where pos is before w->start --
2136 can happen if part of line had been clipped and is not clipped now */
2137 if (vpos == 0 && pos < marker_position (w->start))
2138 Fset_marker (w->start, make_number (pos), Qnil);
2140 /* Redisplay the lines where the text was changed */
2141 last_text_vpos = vpos;
2142 tab_offset = pos_tab_offset (w, pos);
2143 /* If we are starting display in mid-character, correct tab_offset
2144 to account for passing the line that that character really starts in. */
2145 if (val.hpos < lmargin)
2146 tab_offset += width;
2147 old_tick = MODIFF;
2148 while (vpos < stop_vpos)
2150 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
2151 /* If display_text_line ran a hook and changed some text,
2152 redisplay all the way to bottom of buffer
2153 So that we show the changes. */
2154 if (old_tick != MODIFF)
2155 stop_vpos = height;
2156 tab_offset += width;
2157 if (val.vpos) tab_offset = 0;
2158 if (pos != val.bufpos)
2159 last_text_vpos
2160 /* Next line, unless prev line ended in end of buffer with no cr */
2161 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
2162 pos = val.bufpos;
2165 /* There are two cases:
2166 1) we have displayed down to the bottom of the window
2167 2) we have scrolled lines below stop_vpos by scroll_amount */
2169 if (vpos == height)
2171 /* If last line is continued in middle of character,
2172 include the split character in the text considered on the frame */
2173 if (val.hpos < lmargin)
2174 val.bufpos++;
2175 XSETFASTINT (w->window_end_vpos, last_text_vpos);
2176 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
2179 /* If scrolling made blank lines at window bottom,
2180 redisplay to fill those lines */
2181 if (scroll_amount < 0)
2183 /* Don't consider these lines for general-purpose scrolling.
2184 That will save time in the scrolling computation. */
2185 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
2186 vpos = xp.vpos;
2187 pos = xp.bufpos;
2188 val.hpos = lmargin;
2189 if (pos == ZV)
2190 vpos = height + scroll_amount;
2191 else if (xp.contin && xp.hpos != lmargin)
2193 val.hpos = xp.prevhpos - width + lmargin;
2194 pos--;
2197 blank_end_of_window = 1;
2198 tab_offset = pos_tab_offset (w, pos);
2199 /* If we are starting display in mid-character, correct tab_offset
2200 to account for passing the line that that character starts in. */
2201 if (val.hpos < lmargin)
2202 tab_offset += width;
2204 while (vpos < height)
2206 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
2207 tab_offset += width;
2208 if (val.vpos) tab_offset = 0;
2209 pos = val.bufpos;
2212 /* Here is a case where display_text_line sets cursor_vpos wrong.
2213 Make it be fixed up, below. */
2214 if (xp.bufpos == ZV
2215 && xp.bufpos == PT)
2216 cursor_vpos = -1;
2219 /* If bottom just moved off end of frame, change mode line percentage. */
2220 if (XFASTINT (w->window_end_pos) == 0
2221 && Z != val.bufpos)
2222 w->update_mode_line = Qt;
2224 /* Attempt to adjust end-of-text positions to new bottom line */
2225 if (scroll_amount)
2227 delta = height - xp.vpos;
2228 if (delta < 0
2229 || (delta > 0 && xp.bufpos <= ZV)
2230 || (delta == 0 && xp.hpos))
2232 val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
2233 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
2234 XSETFASTINT (w->window_end_vpos,
2235 XFASTINT (w->window_end_vpos) + val.vpos);
2239 w->window_end_valid = Qnil;
2241 /* If point was not in a line that was displayed, find it */
2242 if (cursor_vpos < 0)
2244 findpoint:
2245 val = *compute_motion (start, 0, lmargin, 0, PT, 10000, 10000,
2246 width, hscroll, pos_tab_offset (w, start), w);
2247 /* Admit failure if point is off frame now */
2248 if (val.vpos >= height)
2250 for (vpos = 0; vpos < height; vpos++)
2251 cancel_line (vpos + top, f);
2252 return 0;
2254 cursor_vpos = val.vpos + top;
2255 cursor_hpos = XFASTINT (w->left) + minmax (0, val.hpos, width);
2258 FRAME_CURSOR_X (f) = cursor_hpos;
2259 FRAME_CURSOR_Y (f) = cursor_vpos;
2261 if (debug_end_pos)
2263 val = *compute_motion (start, 0, lmargin, 0, ZV,
2264 height, - (1 << (BITS_PER_SHORT - 1)),
2265 width, hscroll, pos_tab_offset (w, start), w);
2266 if (val.vpos != XFASTINT (w->window_end_vpos))
2267 abort ();
2268 if (XFASTINT (w->window_end_pos)
2269 != Z - val.bufpos)
2270 abort ();
2273 return 1;
2276 /* Mark a section of BUF as modified, but only for the sake of redisplay.
2277 This is useful for recording changes to overlays.
2279 We increment the buffer's modification timestamp and set the
2280 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
2281 as if the region of text between START and END had been modified;
2282 the redisplay code will check this against the windows' timestamps,
2283 and redraw the appropriate area of the buffer.
2285 However, if the buffer is unmodified, we bump the last-save
2286 timestamp as well, so that incrementing the timestamp doesn't fool
2287 Emacs into thinking that the buffer's text has been modified.
2289 Tweaking the timestamps shouldn't hurt the first-modification
2290 timestamps recorded in the undo records; those values aren't
2291 written until just before a real text modification is made, so they
2292 will never catch the timestamp value just before this function gets
2293 called. */
2295 void
2296 redisplay_region (buf, start, end)
2297 struct buffer *buf;
2298 int start, end;
2300 if (start == end)
2301 return;
2303 if (start > end)
2305 int temp = start;
2306 start = end; end = temp;
2309 /* If this is a buffer not in the selected window,
2310 we must do other windows. */
2311 if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
2312 windows_or_buffers_changed = 1;
2313 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
2314 else if (buf != current_buffer)
2315 windows_or_buffers_changed = 1;
2316 /* If multiple windows show this buffer, we must do other windows. */
2317 else if (buffer_shared > 1)
2318 windows_or_buffers_changed = 1;
2319 else
2321 if (unchanged_modified == MODIFF)
2323 beg_unchanged = start - BEG;
2324 end_unchanged = Z - end;
2326 else
2328 if (Z - end < end_unchanged)
2329 end_unchanged = Z - end;
2330 if (start - BEG < beg_unchanged)
2331 beg_unchanged = start - BEG;
2335 /* Increment the buffer's time stamp, but also increment the save
2336 and autosave timestamps, so as not to screw up that timekeeping. */
2337 if (BUF_MODIFF (buf) == BUF_SAVE_MODIFF (buf))
2338 BUF_SAVE_MODIFF (buf)++;
2339 if (BUF_MODIFF (buf) == buf->auto_save_modified)
2340 buf->auto_save_modified++;
2342 BUF_MODIFF (buf) ++;
2346 /* Copy LEN glyphs starting address FROM to the rope TO.
2347 But don't actually copy the parts that would come in before S.
2348 Value is TO, advanced past the copied data.
2349 F is the frame we are displaying in. */
2351 static GLYPH *
2352 copy_part_of_rope (f, to, s, from, len, face)
2353 FRAME_PTR f;
2354 register GLYPH *to; /* Copy to here. */
2355 register GLYPH *s; /* Starting point. */
2356 Lisp_Object *from; /* Data to copy. */
2357 int len;
2358 int face; /* Face to apply to glyphs which don't specify one. */
2360 int n = len;
2361 register Lisp_Object *fp = from;
2362 /* These cache the results of the last call to compute_glyph_face. */
2363 int last_code = -1;
2364 int last_merged = 0;
2366 #ifdef HAVE_FACES
2367 if (! FRAME_TERMCAP_P (f))
2368 while (n--)
2370 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2371 int facecode;
2373 if (FAST_GLYPH_FACE (glyph) == 0)
2374 /* If GLYPH has no face code, use FACE. */
2375 facecode = face;
2376 else if (FAST_GLYPH_FACE (glyph) == last_code)
2377 /* If it's same as previous glyph, use same result. */
2378 facecode = last_merged;
2379 else
2381 /* Merge this glyph's face and remember the result. */
2382 last_code = FAST_GLYPH_FACE (glyph);
2383 last_merged = facecode = compute_glyph_face (f, last_code, face);
2386 if (to >= s)
2387 *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
2388 ++to;
2389 ++fp;
2391 else
2392 #endif
2393 while (n--)
2395 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2396 ++to;
2397 ++fp;
2399 return to;
2402 /* Correct a glyph by replacing its specified user-level face code
2403 with a displayable computed face code. */
2405 static GLYPH
2406 fix_glyph (f, glyph, cface)
2407 FRAME_PTR f;
2408 GLYPH glyph;
2409 int cface;
2411 #ifdef HAVE_FACES
2412 if (! FRAME_TERMCAP_P (f))
2414 if (FAST_GLYPH_FACE (glyph) != 0)
2415 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
2416 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
2418 #endif
2419 return glyph;
2422 /* Display one line of window W, starting at position START in W's buffer.
2424 Display starting at horizontal position HPOS, expressed relative to
2425 W's left edge. In situations where the text at START shouldn't
2426 start at the left margin (i.e. when the window is hscrolled, or
2427 we're continuing a line which left off in the midst of a
2428 multi-column character), HPOS should be negative; we throw away
2429 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2430 account.
2432 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2434 Display on position VPOS on the frame. It is origin 0, relative to
2435 the top of the frame, not W.
2437 Returns a STRUCT POSITION giving character to start next line with
2438 and where to display it, including a zero or negative hpos.
2439 The vpos field is not really a vpos; it is 1 unless the line is continued */
2441 struct position val_display_text_line;
2443 static struct position *
2444 display_text_line (w, start, vpos, hpos, taboffset)
2445 struct window *w;
2446 int start;
2447 int vpos;
2448 int hpos;
2449 int taboffset;
2451 register int pos = start;
2452 register int c;
2453 register GLYPH *p1;
2454 register int pause;
2455 register unsigned char *p;
2456 GLYPH *endp;
2457 register GLYPH *leftmargin;
2458 register GLYPH *p1prev;
2459 register GLYPH *p1start;
2460 int prevpos;
2461 int *charstart;
2462 FRAME_PTR f = XFRAME (w->frame);
2463 int tab_width = XINT (current_buffer->tab_width);
2464 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
2465 int width = window_internal_width (w) - 1;
2466 struct position val;
2467 int lastpos;
2468 int invis;
2469 int last_invis_skip = 0;
2470 Lisp_Object last_invis_prop;
2471 int hscroll = XINT (w->hscroll);
2472 int truncate = (hscroll
2473 || (truncate_partial_width_windows
2474 && XFASTINT (w->width) < FRAME_WIDTH (f))
2475 || !NILP (current_buffer->truncate_lines));
2477 /* 1 if we should highlight the region. */
2478 int highlight_region
2479 = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
2480 int region_beg, region_end;
2482 int selective = (INTEGERP (current_buffer->selective_display)
2483 ? XINT (current_buffer->selective_display)
2484 : !NILP (current_buffer->selective_display) ? -1 : 0);
2485 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
2486 register struct Lisp_Char_Table *dp = window_display_table (w);
2488 Lisp_Object default_invis_vector[3];
2489 /* Number of characters of ellipsis to display after an invisible line
2490 if it calls for an ellipsis.
2491 Note that this value can be nonzero regardless of whether
2492 selective display is enabled--you must check that separately. */
2493 int selective_rlen
2494 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2495 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
2496 : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
2497 /* This is the sequence of Lisp objects to display
2498 when there are invisible lines. */
2499 Lisp_Object *invis_vector_contents
2500 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2501 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2502 : default_invis_vector);
2504 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
2505 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
2506 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
2507 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
2509 /* The next buffer location at which the face should change, due
2510 to overlays or text property changes. */
2511 int next_face_change;
2513 /* The next location where the `invisible' property changes, or an
2514 overlay starts or ends. */
2515 int next_boundary;
2517 /* The face we're currently using. */
2518 int current_face = 0;
2519 int i;
2521 XSETFASTINT (default_invis_vector[2], '.');
2522 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2524 hpos += XFASTINT (w->left);
2525 get_display_line (f, vpos, XFASTINT (w->left));
2526 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
2528 /* Show where to highlight the region. */
2529 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
2530 /* Maybe highlight only in selected window. */
2531 && (highlight_nonselected_windows
2532 || w == XWINDOW (selected_window)))
2534 region_beg = marker_position (current_buffer->mark);
2535 if (PT < region_beg)
2537 region_end = region_beg;
2538 region_beg = PT;
2540 else
2541 region_end = PT;
2542 w->region_showing = Qt;
2544 else
2545 region_beg = region_end = -1;
2547 if (MINI_WINDOW_P (w)
2548 && start == BEG
2549 && vpos == XFASTINT (w->top))
2551 if (! NILP (minibuf_prompt))
2553 minibuf_prompt_width
2554 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2555 XSTRING (minibuf_prompt)->size, hpos,
2556 /* Display a space if we truncate. */
2557 ' ',
2558 1, -1,
2559 /* Truncate the prompt a little before the
2560 margin, so user input can at least start
2561 on the first line. */
2562 w->width > 10 ? w->width - 4 : -1)
2563 - hpos);
2564 hpos += minibuf_prompt_width;
2565 taboffset -= minibuf_prompt_width;
2567 else
2568 minibuf_prompt_width = 0;
2571 /* If we're hscrolled at all, use compute_motion to skip over any
2572 text off the left edge of the window. compute_motion may know
2573 tricks to do this faster than we can. */
2574 if (hpos < 0)
2576 struct position *left_edge
2577 = compute_motion (pos, vpos, hpos, 0,
2578 ZV, vpos, 0,
2579 width, hscroll, taboffset, w);
2581 /* Retrieve the buffer position and column provided by
2582 compute_motion. We can't assume that the column will be
2583 zero, because you may have multi-column characters crossing
2584 the left margin.
2586 compute_motion may have moved us past the screen position we
2587 requested, if we hit a multi-column character, or the end of
2588 the line. If so, back up. */
2589 if (left_edge->vpos > vpos
2590 || left_edge->hpos > 0)
2592 pos = left_edge->bufpos - 1;
2593 hpos = left_edge->prevhpos;
2595 else
2597 pos = left_edge->bufpos;
2598 hpos = left_edge->hpos;
2602 desired_glyphs->bufp[vpos] = start;
2603 p1 = desired_glyphs->glyphs[vpos] + hpos;
2604 p1start = p1;
2605 charstart = desired_glyphs->charstarts[vpos] + hpos;
2606 /* In case we don't ever write anything into it... */
2607 desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
2608 leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
2609 endp = leftmargin + width;
2611 /* Arrange the overlays nicely for our purposes. Usually, we call
2612 display_text_line on only one line at a time, in which case this
2613 can't really hurt too much, or we call it on lines which appear
2614 one after another in the buffer, in which case all calls to
2615 recenter_overlay_lists but the first will be pretty cheap. */
2616 recenter_overlay_lists (current_buffer, pos);
2618 /* Loop generating characters.
2619 Stop at end of buffer, before newline,
2620 if reach or pass continuation column,
2621 or at face change. */
2622 pause = pos;
2623 next_face_change = pos;
2624 next_boundary = pos;
2625 p1prev = p1;
2626 prevpos = pos;
2627 while (1)
2629 if (pos >= pause)
2631 int e_t_h;
2633 while (pos == next_boundary)
2635 Lisp_Object position, limit, prop, ww;
2637 /* Display the overlay strings here, unless we're at ZV
2638 and have already displayed the appropriate strings
2639 on an earlier line. */
2640 if (pos < ZV || !zv_strings_seen++)
2642 int ovlen;
2643 char *ovstr;
2644 ovlen = overlay_strings (pos, w, &ovstr);
2645 for (; ovlen; ovlen--, ovstr++)
2647 if (p1 >= leftmargin && p1 < endp)
2648 *p1 = MAKE_GLYPH (f, *ovstr, current_face);
2649 p1++;
2653 /* Did we reach point? Record the cursor location. */
2654 if (pos == PT && cursor_vpos < 0)
2656 cursor_vpos = vpos;
2657 cursor_hpos = p1 - leftmargin;
2660 if (pos >= ZV)
2661 break;
2663 XSETFASTINT (position, pos);
2664 limit = Fnext_overlay_change (position);
2665 #ifdef USE_TEXT_PROPERTIES
2666 /* This is just an estimate to give reasonable
2667 performance; nothing should go wrong if it is too small. */
2668 if (XFASTINT (limit) > pos + 50)
2669 XSETFASTINT (limit, pos + 50);
2670 limit = Fnext_single_property_change (position, Qinvisible,
2671 Fcurrent_buffer (), limit);
2672 #endif
2673 next_boundary = XFASTINT (limit);
2674 /* if the `invisible' property is set, we can skip to
2675 the next property change. */
2676 XSETWINDOW (ww, w);
2677 prop = Fget_char_property (position, Qinvisible, ww);
2678 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2680 if (pos < PT && next_boundary >= PT)
2682 cursor_vpos = vpos;
2683 cursor_hpos = p1 - leftmargin;
2685 pos = next_boundary;
2686 last_invis_skip = pos;
2687 last_invis_prop = prop;
2691 /* Did we reach point? Record the cursor location. */
2692 if (pos == PT && cursor_vpos < 0)
2694 cursor_vpos = vpos;
2695 cursor_hpos = p1 - leftmargin;
2698 /* Did we hit the end of the visible region of the buffer?
2699 Stop here. */
2700 if (pos >= ZV)
2702 /* Update charstarts for the end of this line. */
2703 /* Do nothing if off the left edge or at the right edge. */
2704 if (p1 >= leftmargin && p1 + 1 != endp)
2706 int *p2x = &charstart[(p1 < leftmargin
2707 ? leftmargin : p1)
2708 - p1start];
2709 *p2x++ = pos;
2711 break;
2714 /* Figure out where (if at all) the
2715 redisplay_end_trigger-hook should run. */
2716 if (MARKERP (w->redisplay_end_trigger)
2717 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
2718 e_t_h = marker_position (w->redisplay_end_trigger);
2719 else if (INTEGERP (w->redisplay_end_trigger))
2720 e_t_h = XINT (w->redisplay_end_trigger);
2721 else
2722 e_t_h = ZV;
2724 /* If we've gone past the place to run a hook,
2725 run the hook. */
2726 if (pos >= e_t_h && e_t_h != ZV)
2728 Lisp_Object args[3];
2730 args[0] = Qredisplay_end_trigger_functions;
2731 XSETWINDOW (args[1], w);
2732 XSETINT (args[2], e_t_h);
2733 Frun_hook_with_args (3, args);
2735 w->redisplay_end_trigger = Qnil;
2736 e_t_h = ZV;
2737 /* Notice if it changed the face of this character. */
2738 next_face_change = pos;
2741 #ifdef HAVE_FACES
2742 /* Did we hit a face change? Figure out what face we should
2743 use now. We also hit this the first time through the
2744 loop, to see what face we should start with. */
2745 if (pos >= next_face_change && (FRAME_WINDOW_P (f)))
2746 current_face = compute_char_face (f, w, pos,
2747 region_beg, region_end,
2748 &next_face_change, pos + 50, 0);
2749 #endif
2751 /* Compute the next place we need to stop
2752 and do something special; set PAUSE. */
2754 pause = ZV;
2756 if (pos < next_boundary && next_boundary < pause)
2757 pause = next_boundary;
2758 if (pos < next_face_change && next_face_change < pause)
2759 pause = next_face_change;
2761 if (e_t_h < pause)
2762 pause = e_t_h;
2764 /* Wouldn't you hate to read the next line to someone over
2765 the phone? */
2766 if (pos < PT && PT < pause)
2767 pause = PT;
2768 if (pos < GPT && GPT < pause)
2769 pause = GPT;
2771 p = &FETCH_CHAR (pos);
2774 if (p1 >= endp)
2775 break;
2777 p1prev = p1;
2779 c = *p++;
2780 /* Let a display table override all standard display methods. */
2781 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
2783 p1 = copy_part_of_rope (f, p1, leftmargin,
2784 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
2785 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
2786 current_face);
2788 else if (c >= 040 && c < 0177)
2790 if (p1 >= leftmargin)
2791 *p1 = MAKE_GLYPH (f, c, current_face);
2792 p1++;
2794 else if (c == '\n')
2796 invis = 0;
2797 if (last_invis_skip == pos
2798 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
2799 invis = 1;
2800 while (pos + 1 < ZV
2801 && selective > 0
2802 && indented_beyond_p (pos + 1, selective))
2804 invis = 1;
2805 pos = find_next_newline (pos + 1, 1);
2806 if (FETCH_CHAR (pos - 1) == '\n')
2807 pos--;
2809 if (invis && selective_rlen > 0 && p1 >= leftmargin)
2811 p1 += selective_rlen;
2812 if (p1 - leftmargin > width)
2813 p1 = endp;
2814 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2815 (p1 - p1prev), current_face);
2817 #ifdef HAVE_FACES
2818 /* Draw the face of the newline character as extending all the
2819 way to the end of the frame line. */
2820 if (current_face)
2822 if (p1 < leftmargin)
2823 p1 = leftmargin;
2824 while (p1 < endp)
2825 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2827 #endif
2829 /* Update charstarts for the newline that ended this line. */
2830 /* Do nothing here for a char that's entirely off the left edge
2831 or if it starts at the right edge. */
2832 if (p1 >= leftmargin && p1prev != endp)
2834 /* Store the newline's position into charstarts
2835 for the column where the newline starts.
2836 Store -1 for the rest of the glyphs it occupies. */
2837 int *p2x = &charstart[(p1prev < leftmargin
2838 ? leftmargin : p1prev)
2839 - p1start];
2840 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2842 *p2x++ = pos;
2843 while (p2x < p2)
2844 *p2x++ = -1;
2847 break;
2849 else if (c == '\t')
2853 if (p1 >= leftmargin && p1 < endp)
2854 *p1 = MAKE_GLYPH (f, ' ', current_face);
2855 p1++;
2857 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
2858 % tab_width);
2860 else if (c == Ctl ('M') && selective == -1)
2862 pos = find_next_newline (pos, 1);
2863 if (FETCH_CHAR (pos - 1) == '\n')
2864 pos--;
2865 if (selective_rlen > 0)
2867 p1 += selective_rlen;
2868 if (p1 - leftmargin > width)
2869 p1 = endp;
2870 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2871 (p1 - p1prev), current_face);
2873 #ifdef HAVE_FACES
2874 /* Draw the face of the newline character as extending all the
2875 way to the end of the frame line. */
2876 if (current_face)
2878 if (p1 < leftmargin)
2879 p1 = leftmargin;
2880 while (p1 < endp)
2881 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2883 #endif
2885 /* Update charstarts for the ^M that ended this line. */
2886 /* Do nothing here for a char that's entirely off the left edge
2887 or if it starts at the right edge. */
2888 if (p1 >= leftmargin && p1prev != endp)
2890 /* Store the newline's position into charstarts
2891 for the column where the newline starts.
2892 Store -1 for the rest of the glyphs it occupies. */
2893 int *p2x = &charstart[(p1prev < leftmargin
2894 ? leftmargin : p1prev)
2895 - p1start];
2896 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2898 *p2x++ = pos;
2899 while (p2x < p2)
2900 *p2x++ = -1;
2902 break;
2904 else if (c < 0200 && ctl_arrow)
2906 if (p1 >= leftmargin)
2907 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
2908 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
2909 current_face);
2910 p1++;
2911 if (p1 >= leftmargin && p1 < endp)
2912 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
2913 p1++;
2915 else
2917 if (p1 >= leftmargin)
2918 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
2919 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
2920 current_face);
2921 p1++;
2922 if (p1 >= leftmargin && p1 < endp)
2923 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
2924 p1++;
2925 if (p1 >= leftmargin && p1 < endp)
2926 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
2927 p1++;
2928 if (p1 >= leftmargin && p1 < endp)
2929 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
2930 p1++;
2933 prevpos = pos;
2934 pos++;
2936 /* Update charstarts for the character just output. */
2938 /* Do nothing here for a char that's entirely off the left edge. */
2939 if (p1 >= leftmargin)
2941 /* Store the char's position into charstarts
2942 for the first glyph occupied by this char.
2943 Store -1 for the rest of the glyphs it occupies. */
2944 if (p1 != p1prev)
2946 int *p2x = &charstart[(p1prev < leftmargin
2947 ? leftmargin : p1prev)
2948 - p1start];
2949 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2951 if (p2x < p2)
2952 *p2x++ = prevpos;
2953 while (p2x < p2)
2954 *p2x++ = -1;
2959 val.hpos = - XINT (w->hscroll);
2960 if (val.hpos)
2961 val.hpos++;
2963 val.vpos = 1;
2965 lastpos = pos;
2967 /* Store 0 in this charstart line for the positions where
2968 there is no character. But do leave what was recorded
2969 for the character that ended the line. */
2970 /* Add 1 in the endtest to compensate for the fact that ENDP was
2971 made from WIDTH, which is 1 less than the window's actual
2972 internal width. */
2973 i = p1 - p1start + 1;
2974 if (p1 < leftmargin)
2975 i += leftmargin - p1;
2976 for (; i < endp - p1start + 1; i++)
2977 charstart[i] = 0;
2979 /* Handle continuation in middle of a character */
2980 /* by backing up over it */
2981 if (p1 > endp)
2983 /* Don't back up if we never actually displayed any text.
2984 This occurs when the minibuffer prompt takes up the whole line. */
2985 if (p1prev)
2987 /* Start the next line with that same character */
2988 pos--;
2989 /* but at negative hpos, to skip the columns output on this line. */
2990 val.hpos += p1prev - endp;
2993 /* Keep in this line everything up to the continuation column. */
2994 p1 = endp;
2997 /* Finish deciding which character to start the next line on,
2998 and what hpos to start it at.
2999 Also set `lastpos' to the last position which counts as "on this line"
3000 for cursor-positioning. */
3002 if (pos < ZV)
3004 if (FETCH_CHAR (pos) == '\n')
3006 /* If stopped due to a newline, start next line after it */
3007 pos++;
3008 /* Check again for hidden lines, in case the newline occurred exactly
3009 at the right margin. */
3010 while (pos < ZV && selective > 0
3011 && indented_beyond_p (pos, selective))
3012 pos = find_next_newline (pos, 1);
3014 else
3015 /* Stopped due to right margin of window */
3017 if (truncate)
3019 *p1++ = fix_glyph (f, truncator, 0);
3020 /* Truncating => start next line after next newline,
3021 and point is on this line if it is before the newline,
3022 and skip none of first char of next line */
3024 pos = find_next_newline (pos, 1);
3025 while (pos < ZV && selective > 0
3026 && indented_beyond_p (pos, selective));
3027 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
3029 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
3031 else
3033 *p1++ = fix_glyph (f, continuer, 0);
3034 val.vpos = 0;
3035 lastpos--;
3040 /* If point is at eol or in invisible text at eol,
3041 record its frame location now. */
3043 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
3045 cursor_vpos = vpos;
3046 cursor_hpos = p1 - leftmargin;
3049 if (cursor_vpos == vpos)
3051 if (cursor_hpos < 0) cursor_hpos = 0;
3052 if (cursor_hpos > width) cursor_hpos = width;
3053 cursor_hpos += XFASTINT (w->left);
3054 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
3056 if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
3057 && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
3059 FRAME_CURSOR_Y (f) = cursor_vpos;
3060 FRAME_CURSOR_X (f) = cursor_hpos;
3063 if (w == XWINDOW (selected_window))
3065 /* Line is not continued and did not start
3066 in middle of character */
3067 if ((hpos - XFASTINT (w->left)
3068 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
3069 && val.vpos)
3071 this_line_bufpos = start;
3072 this_line_buffer = current_buffer;
3073 this_line_vpos = cursor_vpos;
3074 this_line_start_hpos = hpos;
3075 this_line_endpos = Z - lastpos;
3077 else
3078 this_line_bufpos = 0;
3083 /* If hscroll and line not empty, insert truncation-at-left marker */
3084 if (hscroll && lastpos != start)
3086 *leftmargin = fix_glyph (f, truncator, 0);
3087 if (p1 <= leftmargin)
3088 p1 = leftmargin + 1;
3091 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f))
3093 endp++;
3094 if (p1 < leftmargin) p1 = leftmargin;
3095 while (p1 < endp) *p1++ = SPACEGLYPH;
3097 /* Don't draw vertical bars if we're using scroll bars. They're
3098 covered up by the scroll bars, and it's distracting to see
3099 them when the scroll bar windows are flickering around to be
3100 reconfigured. */
3101 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3103 int i;
3104 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
3105 *p1++ = SPACEGLYPH;
3107 else
3108 *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
3109 ? DISP_BORDER_GLYPH (dp)
3110 : '|');
3112 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
3113 p1 - desired_glyphs->glyphs[vpos]);
3114 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3116 /* If the start of this line is the overlay arrow-position,
3117 then put the arrow string into the display-line. */
3119 if (MARKERP (Voverlay_arrow_position)
3120 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
3121 && start == marker_position (Voverlay_arrow_position)
3122 && STRINGP (Voverlay_arrow_string)
3123 && ! overlay_arrow_seen)
3125 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
3126 int i;
3127 int len = XSTRING (Voverlay_arrow_string)->size;
3128 int arrow_end;
3130 if (len > width)
3131 len = width;
3132 #ifdef HAVE_FACES
3133 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
3135 /* If the arrow string has text props, obey them when displaying. */
3136 for (i = 0; i < len; i++)
3138 int c = p[i];
3139 Lisp_Object face, ilisp;
3140 int newface;
3142 XSETFASTINT (ilisp, i);
3143 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
3144 newface = compute_glyph_face_1 (f, face, 0);
3145 leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
3148 else
3149 #endif /* HAVE_FACES */
3151 for (i = 0; i < len; i++)
3152 leftmargin[i] = p[i];
3155 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
3156 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
3157 if (desired_glyphs->used[vpos] < arrow_end)
3158 desired_glyphs->used[vpos] = arrow_end;
3160 overlay_arrow_seen = 1;
3163 val.bufpos = pos;
3164 val_display_text_line = val;
3165 return &val_display_text_line;
3168 /* Redisplay the menu bar in the frame for window W. */
3170 static void
3171 display_menu_bar (w)
3172 struct window *w;
3174 Lisp_Object items, tail;
3175 register int vpos = 0;
3176 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3177 int maxendcol = FRAME_WIDTH (f);
3178 int hpos = 0;
3179 int i;
3181 #ifdef HAVE_NTGUI
3182 return;
3183 #endif
3185 #ifdef USE_X_TOOLKIT
3186 if (FRAME_X_P (f))
3187 return;
3188 #endif /* USE_X_TOOLKIT */
3190 get_display_line (f, vpos, 0);
3192 items = FRAME_MENU_BAR_ITEMS (f);
3193 for (i = 0; i < XVECTOR (items)->size; i += 3)
3195 Lisp_Object pos, string;
3196 string = XVECTOR (items)->contents[i + 1];
3197 if (NILP (string))
3198 break;
3200 XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos);
3202 if (hpos < maxendcol)
3203 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
3204 XSTRING (string)->data,
3205 XSTRING (string)->size,
3206 hpos, 0, 0, hpos, maxendcol);
3207 /* Put a space between items. */
3208 if (hpos < maxendcol)
3210 int hpos1 = hpos + 1;
3211 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
3212 min (hpos1, maxendcol), maxendcol);
3216 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3217 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
3219 /* Fill out the line with spaces. */
3220 if (maxendcol > hpos)
3221 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
3223 /* Clear the rest of the lines allocated to the menu bar. */
3224 vpos++;
3225 while (vpos < FRAME_MENU_BAR_LINES (f))
3226 get_display_line (f, vpos++, 0);
3229 /* Display the mode line for window w */
3231 static void
3232 display_mode_line (w)
3233 struct window *w;
3235 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
3236 register int left = XFASTINT (w->left);
3237 register int right = XFASTINT (w->width) + left;
3238 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3240 line_number_displayed = 0;
3241 w->column_number_displayed = Qnil;
3243 get_display_line (f, vpos, left);
3245 /* Temporarily make frame F's kboard the current kboard
3246 so that kboard-local variables in the mode_line_format
3247 will get the right values. */
3248 push_frame_kboard (f);
3250 display_mode_element (w, vpos, left, 0, right, right,
3251 current_buffer->mode_line_format);
3253 pop_frame_kboard ();
3255 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3257 /* Make the mode line inverse video if the entire line
3258 is made of mode lines.
3259 I.e. if this window is full width,
3260 or if it is the child of a full width window
3261 (which implies that that window is split side-by-side
3262 and the rest of this line is mode lines of the sibling windows). */
3263 if (XFASTINT (w->width) == FRAME_WIDTH (f)
3264 || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
3265 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
3266 #ifdef HAVE_FACES
3267 else if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
3269 /* For a partial width window, explicitly set face of each glyph. */
3270 int i;
3271 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
3272 for (i = left; i < right; ++i)
3273 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
3275 #endif
3278 /* Contribute ELT to the mode line for window W.
3279 How it translates into text depends on its data type.
3281 VPOS is the position of the mode line being displayed.
3283 HPOS is the position (absolute on frame) where this element's text
3284 should start. The output is truncated automatically at the right
3285 edge of window W.
3287 DEPTH is the depth in recursion. It is used to prevent
3288 infinite recursion here.
3290 MINENDCOL is the hpos before which the element may not end.
3291 The element is padded at the right with spaces if nec
3292 to reach this column.
3294 MAXENDCOL is the hpos past which this element may not extend.
3295 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3296 (This is necessary to make nested padding and truncation work.)
3298 Returns the hpos of the end of the text generated by ELT.
3299 The next element will receive that value as its HPOS arg,
3300 so as to concatenate the elements. */
3302 static int
3303 display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
3304 struct window *w;
3305 register int vpos, hpos;
3306 int depth;
3307 int minendcol;
3308 register int maxendcol;
3309 register Lisp_Object elt;
3311 tail_recurse:
3312 if (depth > 10)
3313 goto invalid;
3315 depth++;
3317 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
3319 case Lisp_String:
3321 /* A string: output it and check for %-constructs within it. */
3322 register unsigned char c;
3323 register unsigned char *this = XSTRING (elt)->data;
3325 while (hpos < maxendcol && *this)
3327 unsigned char *last = this;
3328 while ((c = *this++) != '\0' && c != '%')
3330 if (this - 1 != last)
3332 register int lim = --this - last + hpos;
3333 if (frame_title_ptr)
3334 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
3335 else
3336 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
3337 hpos, min (lim, maxendcol));
3339 else /* c == '%' */
3341 register int minendcol;
3342 register int spec_width = 0;
3344 /* We can't allow -ve args due to the "%-" construct */
3345 /* Argument specifies minwidth but not maxwidth
3346 (maxwidth can be specified by
3347 (<negative-number> . <stuff>) mode-line elements) */
3349 while ((c = *this++) >= '0' && c <= '9')
3351 spec_width = spec_width * 10 + (c - '0');
3354 minendcol = hpos + spec_width;
3355 if (minendcol > maxendcol)
3357 spec_width = maxendcol - hpos;
3358 minendcol = maxendcol;
3361 if (c == 'M')
3362 hpos = display_mode_element (w, vpos, hpos, depth,
3363 spec_width, maxendcol,
3364 Vglobal_mode_string);
3365 else if (c != 0)
3367 char *spec = decode_mode_spec (w, c, spec_width,
3368 maxendcol - hpos);
3369 if (frame_title_ptr)
3370 hpos = store_frame_title (spec, minendcol, maxendcol);
3371 else
3372 hpos = display_string (w, vpos, spec, -1,
3373 hpos, 0, 1,
3374 minendcol, maxendcol);
3379 break;
3381 case Lisp_Symbol:
3382 /* A symbol: process the value of the symbol recursively
3383 as if it appeared here directly. Avoid error if symbol void.
3384 Special case: if value of symbol is a string, output the string
3385 literally. */
3387 register Lisp_Object tem;
3388 tem = Fboundp (elt);
3389 if (!NILP (tem))
3391 tem = Fsymbol_value (elt);
3392 /* If value is a string, output that string literally:
3393 don't check for % within it. */
3394 if (STRINGP (tem))
3396 if (frame_title_ptr)
3397 hpos = store_frame_title (XSTRING (tem)->data,
3398 minendcol, maxendcol);
3399 else
3400 hpos = display_string (w, vpos, XSTRING (tem)->data,
3401 XSTRING (tem)->size,
3402 hpos, 0, 1, minendcol, maxendcol);
3404 /* Give up right away for nil or t. */
3405 else if (!EQ (tem, elt))
3406 { elt = tem; goto tail_recurse; }
3409 break;
3411 case Lisp_Cons:
3413 register Lisp_Object car, tem;
3415 /* A cons cell: three distinct cases.
3416 If first element is a string or a cons, process all the elements
3417 and effectively concatenate them.
3418 If first element is a negative number, truncate displaying cdr to
3419 at most that many characters. If positive, pad (with spaces)
3420 to at least that many characters.
3421 If first element is a symbol, process the cadr or caddr recursively
3422 according to whether the symbol's value is non-nil or nil. */
3423 car = XCONS (elt)->car;
3424 if (SYMBOLP (car))
3426 tem = Fboundp (car);
3427 elt = XCONS (elt)->cdr;
3428 if (!CONSP (elt))
3429 goto invalid;
3430 /* elt is now the cdr, and we know it is a cons cell.
3431 Use its car if CAR has a non-nil value. */
3432 if (!NILP (tem))
3434 tem = Fsymbol_value (car);
3435 if (!NILP (tem))
3436 { elt = XCONS (elt)->car; goto tail_recurse; }
3438 /* Symbol's value is nil (or symbol is unbound)
3439 Get the cddr of the original list
3440 and if possible find the caddr and use that. */
3441 elt = XCONS (elt)->cdr;
3442 if (NILP (elt))
3443 break;
3444 else if (!CONSP (elt))
3445 goto invalid;
3446 elt = XCONS (elt)->car;
3447 goto tail_recurse;
3449 else if (INTEGERP (car))
3451 register int lim = XINT (car);
3452 elt = XCONS (elt)->cdr;
3453 if (lim < 0)
3454 /* Negative int means reduce maximum width.
3455 DO NOT change MINENDCOL here!
3456 (20 -10 . foo) should truncate foo to 10 col
3457 and then pad to 20. */
3458 maxendcol = min (maxendcol, hpos - lim);
3459 else if (lim > 0)
3461 /* Padding specified. Don't let it be more than
3462 current maximum. */
3463 lim += hpos;
3464 if (lim > maxendcol)
3465 lim = maxendcol;
3466 /* If that's more padding than already wanted, queue it.
3467 But don't reduce padding already specified even if
3468 that is beyond the current truncation point. */
3469 if (lim > minendcol)
3470 minendcol = lim;
3472 goto tail_recurse;
3474 else if (STRINGP (car) || CONSP (car))
3476 register int limit = 50;
3477 /* LIMIT is to protect against circular lists. */
3478 while (CONSP (elt) && --limit > 0
3479 && hpos < maxendcol)
3481 hpos = display_mode_element (w, vpos, hpos, depth,
3482 hpos, maxendcol,
3483 XCONS (elt)->car);
3484 elt = XCONS (elt)->cdr;
3488 break;
3490 default:
3491 invalid:
3492 if (frame_title_ptr)
3493 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
3494 else
3495 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
3496 minendcol, maxendcol);
3497 return hpos;
3500 if (minendcol > hpos)
3501 if (frame_title_ptr)
3502 hpos = store_frame_title ("", minendcol, maxendcol);
3503 else
3504 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
3505 return hpos;
3508 /* Write a null-terminated, right justified decimal representation of
3509 the positive integer D to BUF using a minimal field width WIDTH. */
3511 static void
3512 pint2str (buf, width, d)
3513 register char *buf;
3514 register int width;
3515 register int d;
3517 register char *p = buf;
3519 if (d <= 0)
3520 *p++ = '0';
3521 else
3522 while (d > 0)
3524 *p++ = d % 10 + '0';
3525 d /= 10;
3527 for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
3528 *p-- = '\0';
3529 while (p > buf)
3531 d = *buf;
3532 *buf++ = *p;
3533 *p-- = d;
3537 /* Return a string for the output of a mode line %-spec for window W,
3538 generated by character C. SPEC_WIDTH is the field width when
3539 padding to the left (%c, %l). The value returned from this
3540 function will later be truncated to width MAXWIDTH. */
3542 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3544 static char *
3545 decode_mode_spec (w, c, spec_width, maxwidth)
3546 struct window *w;
3547 register char c;
3548 register int spec_width;
3549 register int maxwidth;
3551 Lisp_Object obj;
3552 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3553 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
3554 struct buffer *b = XBUFFER (w->buffer);
3556 obj = Qnil;
3557 if (maxwidth > FRAME_WIDTH (f))
3558 maxwidth = FRAME_WIDTH (f);
3560 switch (c)
3562 case '*':
3563 if (!NILP (b->read_only))
3564 return "%";
3565 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3566 return "*";
3567 return "-";
3569 case '+':
3570 /* This differs from %* only for a modified read-only buffer. */
3571 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3572 return "*";
3573 if (!NILP (b->read_only))
3574 return "%";
3575 return "-";
3577 case '&':
3578 /* This differs from %* in ignoring read-only-ness. */
3579 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3580 return "*";
3581 return "-";
3583 case '%':
3584 return "%";
3586 case '[':
3588 int i;
3589 char *p;
3591 if (command_loop_level > 5)
3592 return "[[[... ";
3593 p = decode_mode_spec_buf;
3594 for (i = 0; i < command_loop_level; i++)
3595 *p++ = '[';
3596 *p = 0;
3597 return decode_mode_spec_buf;
3600 case ']':
3602 int i;
3603 char *p;
3605 if (command_loop_level > 5)
3606 return " ...]]]";
3607 p = decode_mode_spec_buf;
3608 for (i = 0; i < command_loop_level; i++)
3609 *p++ = ']';
3610 *p = 0;
3611 return decode_mode_spec_buf;
3614 case '-':
3616 register char *p;
3617 register int i;
3619 if (maxwidth < sizeof (lots_of_dashes))
3620 return lots_of_dashes;
3621 else
3623 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
3624 *p++ = '-';
3625 *p = '\0';
3627 return decode_mode_spec_buf;
3630 case 'b':
3631 obj = b->name;
3632 #if 0
3633 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
3635 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
3636 decode_mode_spec_buf[maxwidth - 1] = '\\';
3637 decode_mode_spec_buf[maxwidth] = '\0';
3638 return decode_mode_spec_buf;
3640 #endif
3641 break;
3643 case 'c':
3645 int col = current_column ();
3646 XSETFASTINT (w->column_number_displayed, col);
3647 pint2str (decode_mode_spec_buf, spec_width, col);
3648 return decode_mode_spec_buf;
3651 case 'F':
3652 /* %F displays the frame name. */
3653 #ifdef MULTI_FRAME
3654 return (char *) XSTRING (selected_frame->name)->data;
3655 #else
3656 return "Emacs";
3657 #endif
3659 case 'f':
3660 obj = b->filename;
3661 #if 0
3662 if (NILP (obj))
3663 return "[none]";
3664 else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
3666 bcopy ("...", decode_mode_spec_buf, 3);
3667 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
3668 decode_mode_spec_buf + 3, maxwidth - 3);
3669 return decode_mode_spec_buf;
3671 #endif
3672 break;
3674 case 'l':
3676 int startpos = marker_position (w->start);
3677 int line, linepos, topline;
3678 int nlines, junk;
3679 Lisp_Object tem;
3680 int height = XFASTINT (w->height);
3682 /* If we decided that this buffer isn't suitable for line numbers,
3683 don't forget that too fast. */
3684 if (EQ (w->base_line_pos, w->buffer))
3685 goto no_value;
3687 /* If the buffer is very big, don't waste time. */
3688 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
3690 w->base_line_pos = Qnil;
3691 w->base_line_number = Qnil;
3692 goto no_value;
3695 if (!NILP (w->base_line_number)
3696 && !NILP (w->base_line_pos)
3697 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
3699 line = XFASTINT (w->base_line_number);
3700 linepos = XFASTINT (w->base_line_pos);
3702 else
3704 line = 1;
3705 linepos = BUF_BEGV (b);
3708 /* Count lines from base line to window start position. */
3709 nlines = display_count_lines (linepos, startpos, startpos, &junk);
3711 topline = nlines + line;
3713 /* Determine a new base line, if the old one is too close
3714 or too far away, or if we did not have one.
3715 "Too close" means it's plausible a scroll-down would
3716 go back past it. */
3717 if (startpos == BUF_BEGV (b))
3719 XSETFASTINT (w->base_line_number, topline);
3720 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
3722 else if (nlines < height + 25 || nlines > height * 3 + 50
3723 || linepos == BUF_BEGV (b))
3725 int limit = BUF_BEGV (b);
3726 int position;
3727 int distance = (height * 2 + 30) * 200;
3729 if (startpos - distance > limit)
3730 limit = startpos - distance;
3732 nlines = display_count_lines (startpos, limit,
3733 -(height * 2 + 30),
3734 &position);
3735 /* If we couldn't find the lines we wanted within
3736 200 chars per line,
3737 give up on line numbers for this window. */
3738 if (position == startpos - distance)
3740 w->base_line_pos = w->buffer;
3741 w->base_line_number = Qnil;
3742 goto no_value;
3745 XSETFASTINT (w->base_line_number, topline - nlines);
3746 XSETFASTINT (w->base_line_pos, position);
3749 /* Now count lines from the start pos to point. */
3750 nlines = display_count_lines (startpos, PT, PT, &junk);
3752 /* Record that we did display the line number. */
3753 line_number_displayed = 1;
3755 /* Make the string to show. */
3756 pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
3757 return decode_mode_spec_buf;
3758 no_value:
3760 char* p = decode_mode_spec_buf;
3761 for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
3762 strcpy (p, "??");
3763 return decode_mode_spec_buf;
3766 break;
3768 case 'm':
3769 obj = b->mode_name;
3770 break;
3772 case 'n':
3773 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
3774 return " Narrow";
3775 break;
3777 case 'p':
3779 int pos = marker_position (w->start);
3780 int total = BUF_ZV (b) - BUF_BEGV (b);
3782 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
3784 if (pos <= BUF_BEGV (b))
3785 return "All";
3786 else
3787 return "Bottom";
3789 else if (pos <= BUF_BEGV (b))
3790 return "Top";
3791 else
3793 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
3794 /* We can't normally display a 3-digit number,
3795 so get us a 2-digit number that is close. */
3796 if (total == 100)
3797 total = 99;
3798 sprintf (decode_mode_spec_buf, "%2d%%", total);
3799 return decode_mode_spec_buf;
3803 /* Display percentage of size above the bottom of the screen. */
3804 case 'P':
3806 int toppos = marker_position (w->start);
3807 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
3808 int total = BUF_ZV (b) - BUF_BEGV (b);
3810 if (botpos >= BUF_ZV (b))
3812 if (toppos <= BUF_BEGV (b))
3813 return "All";
3814 else
3815 return "Bottom";
3817 else
3819 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
3820 /* We can't normally display a 3-digit number,
3821 so get us a 2-digit number that is close. */
3822 if (total == 100)
3823 total = 99;
3824 if (toppos <= BUF_BEGV (b))
3825 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
3826 else
3827 sprintf (decode_mode_spec_buf, "%2d%%", total);
3828 return decode_mode_spec_buf;
3832 case 's':
3833 /* status of process */
3834 obj = Fget_buffer_process (w->buffer);
3835 if (NILP (obj))
3836 return "no process";
3837 #ifdef subprocesses
3838 obj = Fsymbol_name (Fprocess_status (obj));
3839 #endif
3840 break;
3842 case 't': /* indicate TEXT or BINARY */
3843 #ifdef MODE_LINE_BINARY_TEXT
3844 return MODE_LINE_BINARY_TEXT (b);
3845 #else
3846 return "T";
3847 #endif
3850 if (STRINGP (obj))
3851 return (char *) XSTRING (obj)->data;
3852 else
3853 return "";
3856 /* Search for COUNT instances of a line boundary, which means either a
3857 newline or (if selective display enabled) a carriage return.
3858 Start at START. If COUNT is negative, search backwards.
3860 If we find COUNT instances, set *SHORTAGE to zero, and return the
3861 position after the COUNTth match. Note that for reverse motion
3862 this is not the same as the usual convention for Emacs motion commands.
3864 If we don't find COUNT instances before reaching the end of the
3865 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3866 the number of line boundaries left unfound, and return the end of the
3867 buffer we bumped up against. */
3869 static int
3870 display_scan_buffer (start, count, shortage)
3871 int *shortage, start;
3872 register int count;
3874 int limit = ((count > 0) ? ZV - 1 : BEGV);
3875 int direction = ((count > 0) ? 1 : -1);
3877 register unsigned char *cursor;
3878 unsigned char *base;
3880 register int ceiling;
3881 register unsigned char *ceiling_addr;
3883 /* If we are not in selective display mode,
3884 check only for newlines. */
3885 if (! (!NILP (current_buffer->selective_display)
3886 && !INTEGERP (current_buffer->selective_display)))
3887 return scan_buffer ('\n', start, 0, count, shortage, 0);
3889 /* The code that follows is like scan_buffer
3890 but checks for either newline or carriage return. */
3892 if (shortage != 0)
3893 *shortage = 0;
3895 if (count > 0)
3896 while (start != limit + 1)
3898 ceiling = BUFFER_CEILING_OF (start);
3899 ceiling = min (limit, ceiling);
3900 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
3901 base = (cursor = &FETCH_CHAR (start));
3902 while (1)
3904 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
3906 if (cursor != ceiling_addr)
3908 if (--count == 0)
3910 immediate_quit = 0;
3911 return (start + cursor - base + 1);
3913 else
3914 if (++cursor == ceiling_addr)
3915 break;
3917 else
3918 break;
3920 start += cursor - base;
3922 else
3924 start--; /* first character we scan */
3925 while (start > limit - 1)
3926 { /* we WILL scan under start */
3927 ceiling = BUFFER_FLOOR_OF (start);
3928 ceiling = max (limit, ceiling);
3929 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
3930 base = (cursor = &FETCH_CHAR (start));
3931 cursor++;
3932 while (1)
3934 while (--cursor != ceiling_addr
3935 && *cursor != '\n' && *cursor != 015)
3937 if (cursor != ceiling_addr)
3939 if (++count == 0)
3941 immediate_quit = 0;
3942 return (start + cursor - base + 1);
3945 else
3946 break;
3948 start += cursor - base;
3952 if (shortage != 0)
3953 *shortage = count * direction;
3954 return (start + ((direction == 1 ? 0 : 1)));
3957 /* Count up to N lines starting from FROM.
3958 But don't go beyond LIMIT.
3959 Return the number of lines thus found (always positive).
3960 Store the position after what was found into *POS_PTR. */
3962 static int
3963 display_count_lines (from, limit, n, pos_ptr)
3964 int from, limit, n;
3965 int *pos_ptr;
3967 int oldbegv = BEGV;
3968 int oldzv = ZV;
3969 int shortage = 0;
3971 if (limit < from)
3972 BEGV = limit;
3973 else
3974 ZV = limit;
3976 *pos_ptr = display_scan_buffer (from, n, &shortage);
3978 ZV = oldzv;
3979 BEGV = oldbegv;
3981 if (n < 0)
3982 /* When scanning backwards, scan_buffer stops *after* the last newline
3983 it finds, but does count it. Compensate for that. */
3984 return - n - shortage - (*pos_ptr != limit);
3985 return n - shortage;
3988 /* Display STRING on one line of window W, starting at HPOS.
3989 Display at position VPOS. Caller should have done get_display_line.
3990 If VPOS == -1, display it as the current frame's title.
3991 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3993 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3995 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3996 MAXCOL is the last column ok to end at. Truncate here.
3997 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3998 Both count from the left edge of the frame, as does HPOS.
3999 The right edge of W is an implicit maximum.
4000 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
4002 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
4003 at the place where the current window ends in this line
4004 and not display anything beyond there. Otherwise, only MAXCOL
4005 controls where to stop output.
4007 Returns ending hpos. */
4009 static int
4010 display_string (w, vpos, string, length, hpos, truncate,
4011 obey_window_width, mincol, maxcol)
4012 struct window *w;
4013 unsigned char *string;
4014 int length;
4015 int vpos, hpos;
4016 GLYPH truncate;
4017 int obey_window_width;
4018 int mincol, maxcol;
4020 register int c;
4021 int truncated;
4022 register GLYPH *p1;
4023 int hscroll = XINT (w->hscroll);
4024 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
4025 register GLYPH *start;
4026 register GLYPH *end;
4027 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
4028 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
4029 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
4030 int window_width = XFASTINT (w->width);
4032 /* Use the standard display table, not the window's display table.
4033 We don't want the mode line in rot13. */
4034 register struct Lisp_Char_Table *dp = 0;
4035 int i;
4037 if (DISP_TABLE_P (Vstandard_display_table))
4038 dp = XCHAR_TABLE (Vstandard_display_table);
4040 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
4042 p1 = p1start;
4043 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
4045 if (obey_window_width)
4047 end = start + window_width - (truncate != 0);
4049 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f))
4051 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4053 int i;
4055 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
4056 *end-- = ' ';
4058 else
4059 *end-- = '|';
4063 if (! obey_window_width
4064 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
4065 end = desired_glyphs->glyphs[vpos] + maxcol;
4067 /* Store 0 in charstart for these columns. */
4068 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
4069 desired_glyphs->charstarts[vpos][i] = 0;
4071 if (maxcol >= 0 && mincol > maxcol)
4072 mincol = maxcol;
4074 /* We set truncated to 1 if we get stopped by trying to pass END
4075 (that is, trying to pass MAXCOL.) */
4076 truncated = 0;
4077 while (1)
4079 if (length == 0)
4080 break;
4081 c = *string++;
4082 /* Specified length. */
4083 if (length >= 0)
4084 length--;
4085 /* Unspecified length (null-terminated string). */
4086 else if (c == 0)
4087 break;
4089 if (p1 >= end)
4091 truncated = 1;
4092 break;
4095 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
4097 p1 = copy_part_of_rope (f, p1, start,
4098 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
4099 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
4102 else if (c >= 040 && c < 0177)
4104 if (p1 >= start)
4105 *p1 = c;
4106 p1++;
4108 else if (c == '\t')
4112 if (p1 >= start && p1 < end)
4113 *p1 = SPACEGLYPH;
4114 p1++;
4116 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
4118 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
4120 if (p1 >= start)
4121 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
4122 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
4124 p1++;
4125 if (p1 >= start && p1 < end)
4126 *p1 = c ^ 0100;
4127 p1++;
4129 else
4131 if (p1 >= start)
4132 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
4133 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
4135 p1++;
4136 if (p1 >= start && p1 < end)
4137 *p1 = (c >> 6) + '0';
4138 p1++;
4139 if (p1 >= start && p1 < end)
4140 *p1 = (7 & (c >> 3)) + '0';
4141 p1++;
4142 if (p1 >= start && p1 < end)
4143 *p1 = (7 & c) + '0';
4144 p1++;
4148 if (truncated)
4150 p1 = end;
4151 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
4153 else if (mincol >= 0)
4155 end = desired_glyphs->glyphs[vpos] + mincol;
4156 while (p1 < end)
4157 *p1++ = SPACEGLYPH;
4161 register int len = p1 - desired_glyphs->glyphs[vpos];
4163 if (len > desired_glyphs->used[vpos])
4164 desired_glyphs->used[vpos] = len;
4165 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
4167 return len;
4171 /* This is like a combination of memq and assq.
4172 Return 1 if PROPVAL appears as an element of LIST
4173 or as the car of an element of LIST.
4174 If PROPVAL is a list, compare each element against LIST
4175 in that way, and return 1 if any element of PROPVAL is found in LIST.
4176 Otherwise return 0.
4177 This function cannot quit. */
4180 invisible_p (propval, list)
4181 register Lisp_Object propval;
4182 Lisp_Object list;
4184 register Lisp_Object tail, proptail;
4185 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4187 register Lisp_Object tem;
4188 tem = XCONS (tail)->car;
4189 if (EQ (propval, tem))
4190 return 1;
4191 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4192 return 1;
4194 if (CONSP (propval))
4195 for (proptail = propval; CONSP (proptail);
4196 proptail = XCONS (proptail)->cdr)
4198 Lisp_Object propelt;
4199 propelt = XCONS (proptail)->car;
4200 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4202 register Lisp_Object tem;
4203 tem = XCONS (tail)->car;
4204 if (EQ (propelt, tem))
4205 return 1;
4206 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4207 return 1;
4210 return 0;
4213 /* Return 1 if PROPVAL appears as the car of an element of LIST
4214 and the cdr of that element is non-nil.
4215 If PROPVAL is a list, check each element of PROPVAL in that way,
4216 and the first time some element is found,
4217 return 1 if the cdr of that element is non-nil.
4218 Otherwise return 0.
4219 This function cannot quit. */
4222 invisible_ellipsis_p (propval, list)
4223 register Lisp_Object propval;
4224 Lisp_Object list;
4226 register Lisp_Object tail, proptail;
4227 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4229 register Lisp_Object tem;
4230 tem = XCONS (tail)->car;
4231 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4232 return ! NILP (XCONS (tem)->cdr);
4234 if (CONSP (propval))
4235 for (proptail = propval; CONSP (proptail);
4236 proptail = XCONS (proptail)->cdr)
4238 Lisp_Object propelt;
4239 propelt = XCONS (proptail)->car;
4240 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4242 register Lisp_Object tem;
4243 tem = XCONS (tail)->car;
4244 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4245 return ! NILP (XCONS (tem)->cdr);
4248 return 0;
4251 void
4252 syms_of_xdisp ()
4254 staticpro (&Qmenu_bar_update_hook);
4255 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
4257 staticpro (&Qoverriding_terminal_local_map);
4258 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
4260 staticpro (&Qoverriding_local_map);
4261 Qoverriding_local_map = intern ("overriding-local-map");
4263 staticpro (&Qwindow_scroll_functions);
4264 Qwindow_scroll_functions = intern ("window-scroll-functions");
4266 staticpro (&Qredisplay_end_trigger_functions);
4267 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
4269 staticpro (&last_arrow_position);
4270 staticpro (&last_arrow_string);
4271 last_arrow_position = Qnil;
4272 last_arrow_string = Qnil;
4274 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
4275 "String (or mode line construct) included (normally) in `mode-line-format'.");
4276 Vglobal_mode_string = Qnil;
4278 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
4279 "Marker for where to display an arrow on top of the buffer text.\n\
4280 This must be the beginning of a line in order to work.\n\
4281 See also `overlay-arrow-string'.");
4282 Voverlay_arrow_position = Qnil;
4284 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
4285 "String to display as an arrow. See also `overlay-arrow-position'.");
4286 Voverlay_arrow_string = Qnil;
4288 DEFVAR_INT ("scroll-step", &scroll_step,
4289 "*The number of lines to try scrolling a window by when point moves out.\n\
4290 If that fails to bring point back on frame, point is centered instead.\n\
4291 If this is zero, point is always centered after it moves off frame.");
4293 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
4295 DEFVAR_BOOL ("truncate-partial-width-windows",
4296 &truncate_partial_width_windows,
4297 "*Non-nil means truncate lines in all windows less than full frame wide.");
4298 truncate_partial_width_windows = 1;
4300 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
4301 "*Non-nil means use inverse video for the mode line.");
4302 mode_line_inverse_video = 1;
4304 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
4305 "*Maximum buffer size for which line number should be displayed.");
4306 line_number_display_limit = 1000000;
4308 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
4309 "*Non-nil means highlight region even in nonselected windows.");
4310 highlight_nonselected_windows = 1;
4312 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
4313 "Non-nil if more than one frame is visible on this display.\n\
4314 Minibuffer-only frames don't count, but iconified frames do.\n\
4315 This variable is not guaranteed to be accurate except while processing\n\
4316 `frame-title-format' and `icon-title-format'.");
4318 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
4319 "Template for displaying the titlebar of visible frames.\n\
4320 \(Assuming the window manager supports this feature.)\n\
4321 This variable has the same structure as `mode-line-format' (which see),\n\
4322 and is used only on frames for which no explicit name has been set\n\
4323 \(see `modify-frame-parameters').");
4324 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
4325 "Template for displaying the titlebar of an iconified frame.\n\
4326 \(Assuming the window manager supports this feature.)\n\
4327 This variable has the same structure as `mode-line-format' (which see),\n\
4328 and is used only on frames for which no explicit name has been set\n\
4329 \(see `modify-frame-parameters').");
4330 Vicon_title_format
4331 = Vframe_title_format
4332 = Fcons (intern ("multiple-frames"),
4333 Fcons (build_string ("%b"),
4334 Fcons (Fcons (build_string (""),
4335 Fcons (intern ("invocation-name"),
4336 Fcons (build_string ("@"),
4337 Fcons (intern ("system-name"),
4338 Qnil)))),
4339 Qnil)));
4341 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
4342 "Maximum number of lines to keep in the message log buffer.\n\
4343 If nil, disable message logging. If t, log messages but don't truncate\n\
4344 the buffer when it becomes large.");
4345 XSETFASTINT (Vmessage_log_max, 50);
4347 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
4348 "Functions called before redisplay, if window sizes have changed.\n\
4349 The value should be a list of functions that take one argument.\n\
4350 Just before redisplay, for each frame, if any of its windows have changed\n\
4351 size since the last redisplay, or have been split or deleted,\n\
4352 all the functions in the list are called, with the frame as argument.");
4353 Vwindow_size_change_functions = Qnil;
4355 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
4356 "List of Functions to call before redisplaying a window with scrolling.\n\
4357 Each function is called with two arguments, the window\n\
4358 and its new display-start position. Note that the value of `window-end'\n\
4359 is not valid when these functions are called.");
4360 Vwindow_scroll_functions = Qnil;
4363 /* initialize the window system */
4364 init_xdisp ()
4366 Lisp_Object root_window;
4367 #ifndef COMPILER_REGISTER_BUG
4368 register
4369 #endif /* COMPILER_REGISTER_BUG */
4370 struct window *mini_w;
4372 this_line_bufpos = 0;
4374 mini_w = XWINDOW (minibuf_window);
4375 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
4377 echo_area_glyphs = 0;
4378 previous_echo_glyphs = 0;
4380 if (!noninteractive)
4382 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
4383 XSETFASTINT (XWINDOW (root_window)->top, 0);
4384 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
4385 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
4386 set_window_height (minibuf_window, 1, 0);
4388 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
4389 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));