Initial revision
[emacs.git] / src / xdisp.c
blob7000d8d6089705fc0f723c18945babf3cc2f23f6
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 #ifdef USE_X_TOOLKIT
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;
53 /* Nonzero means print newline to stdout before next minibuffer message. */
55 int noninteractive_need_newline;
57 /* Nonzero means print newline to message log before next message. */
59 static int message_log_need_newline;
61 #define min(a, b) ((a) < (b) ? (a) : (b))
62 #define max(a, b) ((a) > (b) ? (a) : (b))
63 #define minmax(floor, val, ceil) \
64 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
66 /* The buffer position of the first character appearing
67 entirely or partially on the current frame line.
68 Or zero, which disables the optimization for the current frame line. */
69 static int this_line_bufpos;
71 /* Number of characters past the end of this line,
72 including the terminating newline */
73 static int this_line_endpos;
75 /* The vertical position of this frame line. */
76 static int this_line_vpos;
78 /* Hpos value for start of display on this frame line.
79 Usually zero, but negative if first character really began
80 on previous line */
81 static int this_line_start_hpos;
83 /* Buffer that this_line variables are describing. */
84 static struct buffer *this_line_buffer;
86 /* Value of echo_area_glyphs when it was last acted on.
87 If this is nonzero, there is a message on the frame
88 in the minibuffer and it should be erased as soon
89 as it is no longer requested to appear. */
90 char *previous_echo_glyphs;
92 /* Nonzero means truncate lines in all windows less wide than the frame */
93 int truncate_partial_width_windows;
95 /* Nonzero means we have more than one non-minibuffer-only frame.
96 Not guaranteed to be accurate except while parsing frame-title-format. */
97 int multiple_frames;
99 Lisp_Object Vglobal_mode_string;
101 /* Marker for where to display an arrow on top of the buffer text. */
102 Lisp_Object Voverlay_arrow_position;
104 /* String to display for the arrow. */
105 Lisp_Object Voverlay_arrow_string;
107 /* Like mode-line-format, but for the titlebar on a visible frame. */
108 Lisp_Object Vframe_title_format;
110 /* Like mode-line-format, but for the titlebar on an iconified frame. */
111 Lisp_Object Vicon_title_format;
113 /* List of functions to call when a window's size changes. These
114 functions get one arg, a frame on which one or more windows' sizes
115 have changed. */
116 static Lisp_Object Vwindow_size_change_functions;
118 /* Values of those variables at last redisplay. */
119 static Lisp_Object last_arrow_position, last_arrow_string;
121 Lisp_Object Qmenu_bar_update_hook;
123 /* Nonzero if overlay arrow has been displayed once in this window. */
124 static int overlay_arrow_seen;
126 /* Nonzero if visible end of buffer has already been displayed once
127 in this window. (We need this variable in case there are overlay
128 strings that get displayed there.) */
129 static int zv_strings_seen;
131 /* Nonzero means highlight the region even in nonselected windows. */
132 static int highlight_nonselected_windows;
134 /* If cursor motion alone moves point off frame,
135 Try scrolling this many lines up or down if that will bring it back. */
136 static int scroll_step;
138 /* Nonzero if try_window_id has made blank lines at window bottom
139 since the last redisplay that paused */
140 static int blank_end_of_window;
142 /* Number of windows showing the buffer of the selected window
143 (or another buffer with the same base buffer).
144 keyboard.c refers to this. */
145 int buffer_shared;
147 /* display_text_line sets these to the frame position (origin 0) of point,
148 whether the window is selected or not.
149 Set one to -1 first to determine whether point was found afterwards. */
151 static int cursor_vpos;
152 static int cursor_hpos;
154 static int debug_end_pos;
156 /* Nonzero means display mode line highlighted */
157 int mode_line_inverse_video;
159 static int message_log_check_duplicate ();
160 static void echo_area_display ();
161 void mark_window_display_accurate ();
162 static void redisplay_windows ();
163 static void redisplay_window ();
164 static void update_menu_bar ();
165 static void try_window ();
166 static int try_window_id ();
167 static struct position *display_text_line ();
168 static void display_mode_line ();
169 static int display_mode_element ();
170 static char *decode_mode_spec ();
171 static int display_string ();
172 static void display_menu_bar ();
173 static int display_count_lines ();
175 /* Prompt to display in front of the minibuffer contents */
176 Lisp_Object minibuf_prompt;
178 /* Width in columns of current minibuffer prompt. */
179 int minibuf_prompt_width;
181 /* Message to display instead of minibuffer contents
182 This is what the functions error and message make,
183 and command echoing uses it as well.
184 It overrides the minibuf_prompt as well as the buffer. */
185 char *echo_area_glyphs;
187 /* This is the length of the message in echo_area_glyphs. */
188 int echo_area_glyphs_length;
190 /* This is the window where the echo area message was displayed.
191 It is always a minibuffer window, but it may not be the
192 same window currently active as a minibuffer. */
193 Lisp_Object echo_area_window;
195 /* true iff we should redraw the mode lines on the next redisplay */
196 int update_mode_lines;
198 /* Smallest number of characters before the gap
199 at any time since last redisplay that finished.
200 Valid for current buffer when try_window_id can be called. */
201 int beg_unchanged;
203 /* Smallest number of characters after the gap
204 at any time since last redisplay that finished.
205 Valid for current buffer when try_window_id can be called. */
206 int end_unchanged;
208 /* MODIFF as of last redisplay that finished;
209 if it matches MODIFF, beg_unchanged and end_unchanged
210 contain no useful information */
211 int unchanged_modified;
213 /* Nonzero if window sizes or contents have changed
214 since last redisplay that finished */
215 int windows_or_buffers_changed;
217 /* Nonzero after display_mode_line if %l was used
218 and it displayed a line number. */
219 int line_number_displayed;
221 /* Maximum buffer size for which to display line numbers. */
222 static int line_number_display_limit;
224 /* Number of lines to keep in the message log buffer.
225 t means infinite. nil means don't log at all. */
226 Lisp_Object Vmessage_log_max;
228 void
229 message_log_maybe_newline ()
231 if (message_log_need_newline)
232 message_dolog ("", 0, 1);
236 /* Add a string to the message log, optionally terminated with a newline.
237 This function calls low-level routines in order to bypass text property
238 hooks, etc. which might not be safe to run. */
240 void
241 message_dolog (m, len, nlflag)
242 char *m;
243 int len, nlflag;
245 if (!NILP (Vmessage_log_max))
247 struct buffer *oldbuf;
248 int oldpoint, oldbegv, oldzv;
250 oldbuf = current_buffer;
251 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
252 current_buffer->undo_list = Qt;
253 oldpoint = PT;
254 oldbegv = BEGV;
255 oldzv = ZV;
256 BEGV = BEG;
257 ZV = Z;
258 if (oldpoint == Z)
259 oldpoint += len + nlflag;
260 if (oldzv == Z)
261 oldzv += len + nlflag;
262 TEMP_SET_PT (Z);
263 if (len)
264 insert_1 (m, len, 1, 0);
265 if (nlflag)
267 int this_bol, prev_bol, dup;
268 insert_1 ("\n", 1, 1, 0);
270 this_bol = scan_buffer ('\n', Z, 0, -2, 0, 0);
271 if (this_bol > BEG)
273 prev_bol = scan_buffer ('\n', this_bol, 0, -2, 0, 0);
274 dup = message_log_check_duplicate (prev_bol, this_bol);
275 if (dup)
277 if (oldpoint > prev_bol)
278 oldpoint -= min (this_bol, oldpoint) - prev_bol;
279 if (oldbegv > prev_bol)
280 oldbegv -= min (this_bol, oldbegv) - prev_bol;
281 if (oldzv > prev_bol)
282 oldzv -= min (this_bol, oldzv) - prev_bol;
283 del_range_1 (prev_bol, this_bol, 0);
284 if (dup > 1)
286 char dupstr[40];
287 int duplen;
289 /* If you change this format, don't forget to also
290 change message_log_check_duplicate. */
291 sprintf (dupstr, " [%d times]", dup);
292 duplen = strlen (dupstr);
293 TEMP_SET_PT (Z-1);
294 if (oldpoint == Z)
295 oldpoint += duplen;
296 if (oldzv == Z)
297 oldzv += duplen;
298 insert_1 (dupstr, duplen, 1, 0);
303 if (NATNUMP (Vmessage_log_max))
305 int pos = scan_buffer ('\n', Z, 0,
306 -XFASTINT (Vmessage_log_max) - 1, 0, 0);
307 oldpoint -= min (pos, oldpoint) - BEG;
308 oldbegv -= min (pos, oldbegv) - BEG;
309 oldzv -= min (pos, oldzv) - BEG;
310 del_range_1 (BEG, pos, 0);
313 BEGV = oldbegv;
314 ZV = oldzv;
315 TEMP_SET_PT (oldpoint);
316 set_buffer_internal (oldbuf);
317 message_log_need_newline = !nlflag;
322 /* We are at the end of the buffer after just having inserted a newline.
323 (Note: We depend on the fact we won't be crossing the gap.)
324 Check to see if the most recent message looks a lot like the previous one.
325 Return 0 if different, 1 if the new one should just replace it, or a
326 value N > 1 if we should also append " [N times]". */
328 static int
329 message_log_check_duplicate (prev_bol, this_bol)
330 int prev_bol, this_bol;
332 int i;
333 int len = Z - 1 - this_bol;
334 int seen_dots = 0;
335 unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
336 unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
338 for (i = 0; i < len; i++)
340 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
341 && p1[i] != '\n')
342 seen_dots = 1;
343 if (p1[i] != p2[i])
344 return seen_dots;
346 p1 += len;
347 if (*p1 == '\n')
348 return 2;
349 if (*p1++ == ' ' && *p1++ == '[')
351 int n = 0;
352 while (*p1 >= '0' && *p1 <= '9')
353 n = n * 10 + *p1++ - '0';
354 if (strncmp (p1, " times]\n", 8) == 0)
355 return n+1;
357 return 0;
360 /* Display an echo area message M with a specified length of LEN chars.
361 The string may include null characters. If m is 0, clear out any
362 existing message, and let the minibuffer text show through.
363 Do not pass text that is stored in a Lisp string. */
365 void
366 message2 (m, len)
367 char *m;
368 int len;
370 /* First flush out any partial line written with print. */
371 message_log_maybe_newline ();
372 if (m)
373 message_dolog (m, len, 1);
374 message2_nolog (m, len);
378 /* The non-logging part of that function. */
380 void
381 message2_nolog (m, len)
382 char *m;
383 int len;
385 if (noninteractive)
387 if (noninteractive_need_newline)
388 putc ('\n', stderr);
389 noninteractive_need_newline = 0;
390 fwrite (m, len, 1, stderr);
391 if (cursor_in_echo_area == 0)
392 fprintf (stderr, "\n");
393 fflush (stderr);
395 /* A null message buffer means that the frame hasn't really been
396 initialized yet. Error messages get reported properly by
397 cmd_error, so this must be just an informative message; toss it. */
398 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
400 Lisp_Object mini_window;
401 FRAME_PTR f;
403 /* Get the frame containing the minibuffer
404 that the selected frame is using. */
405 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
406 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
408 #ifdef MULTI_FRAME
409 FRAME_SAMPLE_VISIBILITY (f);
410 if (FRAME_VISIBLE_P (selected_frame)
411 && ! FRAME_VISIBLE_P (f))
412 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
413 #endif
415 if (m)
417 echo_area_glyphs = m;
418 echo_area_glyphs_length = len;
420 else
421 echo_area_glyphs = previous_echo_glyphs = 0;
423 do_pending_window_change ();
424 echo_area_display ();
425 update_frame (f, 1, 1);
426 do_pending_window_change ();
427 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
428 (*frame_up_to_date_hook) (f);
432 void
433 message1 (m)
434 char *m;
436 message2 (m, (m ? strlen (m) : 0));
439 void
440 message1_nolog (m)
441 char *m;
443 message2_nolog (m, (m ? strlen (m) : 0));
446 /* Truncate what will be displayed in the echo area
447 the next time we display it--but don't redisplay it now. */
449 void
450 truncate_echo_area (len)
451 int len;
453 /* A null message buffer means that the frame hasn't really been
454 initialized yet. Error messages get reported properly by
455 cmd_error, so this must be just an informative message; toss it. */
456 if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
457 echo_area_glyphs_length = len;
460 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
461 zero if being used by message. */
462 int message_buf_print;
464 /* Dump an informative message to the minibuf. If m is 0, clear out
465 any existing message, and let the minibuffer text show through. */
466 /* VARARGS 1 */
467 void
468 message (m, a1, a2, a3)
469 char *m;
470 EMACS_INT a1, a2, a3;
472 if (noninteractive)
474 if (m)
476 if (noninteractive_need_newline)
477 putc ('\n', stderr);
478 noninteractive_need_newline = 0;
479 fprintf (stderr, m, a1, a2, a3);
480 if (cursor_in_echo_area == 0)
481 fprintf (stderr, "\n");
482 fflush (stderr);
485 else if (INTERACTIVE)
487 /* The frame whose minibuffer we're going to display the message on.
488 It may be larger than the selected frame, so we need
489 to use its buffer, not the selected frame's buffer. */
490 Lisp_Object mini_window;
491 FRAME_PTR f;
493 /* Get the frame containing the minibuffer
494 that the selected frame is using. */
495 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
496 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
498 /* A null message buffer means that the frame hasn't really been
499 initialized yet. Error messages get reported properly by
500 cmd_error, so this must be just an informative message; toss it. */
501 if (FRAME_MESSAGE_BUF (f))
503 if (m)
505 int len;
506 #ifdef NO_ARG_ARRAY
507 EMACS_INT a[3];
508 a[0] = a1;
509 a[1] = a2;
510 a[2] = a3;
512 len = doprnt (FRAME_MESSAGE_BUF (f),
513 FRAME_WIDTH (f), m, (char *)0, 3, a);
514 #else
515 len = doprnt (FRAME_MESSAGE_BUF (f),
516 FRAME_WIDTH (f), m, (char *)0, 3, &a1);
517 #endif /* NO_ARG_ARRAY */
519 message2 (FRAME_MESSAGE_BUF (f), len);
521 else
522 message1 (0);
524 /* Print should start at the beginning of the message
525 buffer next time. */
526 message_buf_print = 0;
531 /* The non-logging version of that function. */
532 void
533 message_nolog (m, a1, a2, a3)
534 char *m;
535 EMACS_INT a1, a2, a3;
537 Lisp_Object old_log_max;
538 old_log_max = Vmessage_log_max;
539 Vmessage_log_max = Qnil;
540 message (m, a1, a2, a3);
541 Vmessage_log_max = old_log_max;
544 void
545 update_echo_area ()
547 message2 (echo_area_glyphs, echo_area_glyphs_length);
550 static void
551 echo_area_display ()
553 register int vpos;
554 FRAME_PTR f;
555 Lisp_Object mini_window;
557 /* Choose the minibuffer window for this display.
558 It is the minibuffer window used by the selected frame. */
559 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
560 /* This is the frame that window is in. */
561 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
563 if (! FRAME_VISIBLE_P (f))
564 return;
566 if (frame_garbaged)
568 redraw_garbaged_frames ();
569 frame_garbaged = 0;
572 if (echo_area_glyphs || minibuf_level == 0)
574 echo_area_window = mini_window;
576 vpos = XFASTINT (XWINDOW (mini_window)->top);
577 get_display_line (f, vpos, 0);
578 display_string (XWINDOW (mini_window), vpos,
579 echo_area_glyphs ? echo_area_glyphs : "",
580 echo_area_glyphs ? echo_area_glyphs_length : -1,
581 0, 0, 0, 0, FRAME_WIDTH (f));
583 #if 0 /* This just gets in the way. update_frame does the job. */
584 /* If desired cursor location is on this line, put it at end of text */
585 if (cursor_in_echo_area)
586 FRAME_CURSOR_Y (f) = vpos;
587 if (FRAME_CURSOR_Y (f) == vpos)
588 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
589 #endif
591 /* Fill the rest of the minibuffer window with blank lines. */
593 int i;
595 for (i = vpos + 1;
596 i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
598 get_display_line (f, i, 0);
599 display_string (XWINDOW (mini_window), vpos,
600 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f));
604 else if (!EQ (mini_window, selected_window))
605 windows_or_buffers_changed++;
607 if (EQ (mini_window, selected_window))
608 this_line_bufpos = 0;
610 previous_echo_glyphs = echo_area_glyphs;
613 #ifdef HAVE_X_WINDOWS
614 static char frame_title_buf[512];
615 static char *frame_title_ptr;
617 static int
618 store_frame_title (str, mincol, maxcol)
619 char *str;
620 int mincol, maxcol;
622 char *limit;
623 if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
624 maxcol = sizeof (frame_title_buf);
625 limit = &frame_title_buf[maxcol];
626 while (*str != '\0' && frame_title_ptr < limit)
627 *frame_title_ptr++ = *str++;
628 while (frame_title_ptr < &frame_title_buf[mincol])
629 *frame_title_ptr++ = ' ';
630 return frame_title_ptr - frame_title_buf;
633 static void
634 x_consider_frame_title (frame)
635 Lisp_Object frame;
637 Lisp_Object fmt;
638 struct buffer *obuf;
639 int len;
640 FRAME_PTR f = XFRAME (frame);
642 if (!FRAME_X_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name)
643 return;
645 /* Do we have more than one visible frame on this X display? */
647 Lisp_Object tail;
649 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
651 FRAME_PTR tf = XFRAME (XCONS (tail)->car);
653 if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
654 && !FRAME_MINIBUF_ONLY_P (tf)
655 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
656 break;
659 multiple_frames = CONSP (tail);
662 obuf = current_buffer;
663 Fset_buffer (XWINDOW (f->selected_window)->buffer);
664 fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
665 frame_title_ptr = frame_title_buf;
666 len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
667 0, sizeof (frame_title_buf), fmt);
668 frame_title_ptr = 0;
669 set_buffer_internal (obuf);
670 /* Set the name only if it's changed. This avoids consing
671 in the common case where it hasn't. (If it turns out that we've
672 already wasted too much time by walking through the list with
673 display_mode_element, then we might need to optimize at a higher
674 level than this.) */
675 if (! STRINGP (f->name) || XSTRING (f->name)->size != len
676 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
677 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
679 #else
680 #define frame_title_ptr ((char *)0)
681 #define store_frame_title(str, mincol, maxcol) 0
682 #endif
684 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
685 This can call eval. */
687 void
688 prepare_menu_bars ()
690 register struct window *w = XWINDOW (selected_window);
691 int all_windows;
692 struct gcpro gcpro1, gcpro2;
694 all_windows = (update_mode_lines || buffer_shared > 1
695 || windows_or_buffers_changed);
697 /* Update all frame titles based on their buffer names, etc.
698 We do this before the menu bars so that the buffer-menu
699 will show the up-to-date frame titles.
701 This used to be done after the menu bars, for a reason that
702 was stated as follows but which I do not understand:
703 "We do this after the menu bars so that the frame will first
704 create its menu bar using the name `emacs' if no other name
705 has yet been specified."
706 I think that is no longer a concern. */
707 #ifdef HAVE_X_WINDOWS
708 if (windows_or_buffers_changed)
710 Lisp_Object tail, frame;
712 FOR_EACH_FRAME (tail, frame)
713 if (FRAME_VISIBLE_P (XFRAME (frame))
714 || FRAME_ICONIFIED_P (XFRAME (frame)))
715 x_consider_frame_title (frame);
717 #endif
719 /* Update the menu bar item lists, if appropriate.
720 This has to be done before any actual redisplay
721 or generation of display lines. */
722 if (all_windows)
724 Lisp_Object tail, frame;
725 int count = specpdl_ptr - specpdl;
727 record_unwind_protect (Fstore_match_data, Fmatch_data ());
729 FOR_EACH_FRAME (tail, frame)
731 /* If a window on this frame changed size,
732 report that to the user and clear the size-change flag. */
733 if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
735 Lisp_Object functions;
736 /* Clear flag first in case we get error below. */
737 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
738 functions = Vwindow_size_change_functions;
739 GCPRO2 (tail, functions);
740 while (CONSP (functions))
742 call1 (XCONS (functions)->car, frame);
743 functions = XCONS (functions)->cdr;
745 UNGCPRO;
747 GCPRO1 (tail);
748 update_menu_bar (XFRAME (frame), 0);
749 UNGCPRO;
752 unbind_to (count, Qnil);
754 else
755 update_menu_bar (selected_frame, 1);
758 /* Do a frame update, taking possible shortcuts into account.
759 This is the main external entry point for redisplay.
761 If the last redisplay displayed an echo area message and that
762 message is no longer requested, we clear the echo area
763 or bring back the minibuffer if that is in use.
765 Do not call eval from within this function.
766 Calls to eval after the call to echo_area_display would confuse
767 the display_line mechanism and would cause a crash.
768 Calls to eval before that point will work most of the time,
769 but can still lose, because this function
770 can be called from signal handlers; with alarms set up;
771 or with synchronous processes running.
773 See Fcall_process; if you called it from here, it could be
774 entered recursively. */
776 static int do_verify_charstarts;
778 /* Counter is used to clear the face cache
779 no more than once ever 1000 redisplays. */
780 static int clear_face_cache_count;
782 /* Record the previous terminal frame we displayed. */
783 static FRAME_PTR previous_terminal_frame;
785 void
786 redisplay ()
788 register struct window *w = XWINDOW (selected_window);
789 register int pause;
790 int must_finish = 0;
791 int all_windows;
792 register int tlbufpos, tlendpos;
793 struct position pos;
795 if (noninteractive)
796 return;
798 #ifdef MULTI_FRAME
799 if (FRAME_TERMCAP_P (selected_frame)
800 && previous_terminal_frame != selected_frame)
802 /* Since frames on an ASCII terminal share the same display area,
803 displaying a different frame means redisplay the whole thing. */
804 windows_or_buffers_changed++;
805 SET_FRAME_GARBAGED (selected_frame);
806 XSETFRAME (Vterminal_frame, selected_frame);
808 previous_terminal_frame = selected_frame;
809 #endif
811 /* Set the visible flags for all frames.
812 Do this before checking for resized or garbaged frames; they want
813 to know if their frames are visible.
814 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
816 Lisp_Object tail, frame;
818 FOR_EACH_FRAME (tail, frame)
820 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
822 /* Clear out all the display lines in which we will generate the
823 glyphs to display. */
824 init_desired_glyphs (XFRAME (frame));
828 /* Notice any pending interrupt request to change frame size. */
829 do_pending_window_change ();
831 if (frame_garbaged)
833 redraw_garbaged_frames ();
834 frame_garbaged = 0;
837 prepare_menu_bars ();
839 if (windows_or_buffers_changed)
840 update_mode_lines++;
842 /* Detect case that we need to write a star in the mode line. */
843 if (XFASTINT (w->last_modified) < MODIFF
844 && XFASTINT (w->last_modified) <= SAVE_MODIFF)
846 w->update_mode_line = Qt;
847 if (buffer_shared > 1)
848 update_mode_lines++;
851 /* If %c is in use, update it if needed. */
852 if (!NILP (w->column_number_displayed)
853 /* This alternative quickly identifies a common case
854 where no change is needed. */
855 && !(PT == XFASTINT (w->last_point)
856 && XFASTINT (w->last_modified) >= MODIFF)
857 && XFASTINT (w->column_number_displayed) != current_column ())
858 w->update_mode_line = Qt;
860 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
862 all_windows = update_mode_lines || buffer_shared > 1;
864 /* If specs for an arrow have changed, do thorough redisplay
865 to ensure we remove any arrow that should no longer exist. */
866 if (! EQ (Voverlay_arrow_position, last_arrow_position)
867 || ! EQ (Voverlay_arrow_string, last_arrow_string))
868 all_windows = 1;
870 /* Normally the message* functions will have already displayed and
871 updated the echo area, but the frame may have been trashed, or
872 the update may have been preempted, so display the echo area
873 again here. */
874 if (echo_area_glyphs || previous_echo_glyphs)
876 echo_area_display ();
877 must_finish = 1;
880 /* If showing region, and mark has changed, must redisplay whole window. */
881 if (((!NILP (Vtransient_mark_mode)
882 && !NILP (XBUFFER (w->buffer)->mark_active))
883 != !NILP (w->region_showing))
884 || (!NILP (w->region_showing)
885 && !EQ (w->region_showing,
886 Fmarker_position (XBUFFER (w->buffer)->mark))))
887 this_line_bufpos = -1;
889 tlbufpos = this_line_bufpos;
890 tlendpos = this_line_endpos;
891 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
892 && !current_buffer->clip_changed
893 && FRAME_VISIBLE_P (XFRAME (w->frame))
894 /* Make sure recorded data applies to current buffer, etc */
895 && this_line_buffer == current_buffer
896 && current_buffer == XBUFFER (w->buffer)
897 && NILP (w->force_start)
898 /* Point must be on the line that we have info recorded about */
899 && PT >= tlbufpos
900 && PT <= Z - tlendpos
901 /* All text outside that line, including its final newline,
902 must be unchanged */
903 && (XFASTINT (w->last_modified) >= MODIFF
904 || (beg_unchanged >= tlbufpos - 1
905 && GPT >= tlbufpos
906 /* If selective display, can't optimize
907 if the changes start at the beginning of the line. */
908 && ((INTEGERP (current_buffer->selective_display)
909 && XINT (current_buffer->selective_display) > 0
910 ? (beg_unchanged >= tlbufpos
911 && GPT > tlbufpos)
912 : 1))
913 && end_unchanged >= tlendpos
914 && Z - GPT >= tlendpos)))
916 if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n'
917 && (tlbufpos == ZV
918 || FETCH_CHAR (tlbufpos) == '\n'))
919 /* Former continuation line has disappeared by becoming empty */
920 goto cancel;
921 else if (XFASTINT (w->last_modified) < MODIFF
922 || MINI_WINDOW_P (w))
924 cursor_vpos = -1;
925 overlay_arrow_seen = 0;
926 zv_strings_seen = 0;
927 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
928 pos_tab_offset (w, tlbufpos));
929 /* If line contains point, is not continued,
930 and ends at same distance from eob as before, we win */
931 if (cursor_vpos >= 0 && this_line_bufpos
932 && this_line_endpos == tlendpos)
934 /* If this is not the window's last line,
935 we must adjust the charstarts of the lines below. */
936 if (this_line_vpos + 1
937 < XFASTINT (w->top) + window_internal_height (w))
939 int left = XFASTINT (w->left);
940 int *charstart_next_line
941 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
942 int adjust;
944 if (Z - tlendpos == ZV)
945 /* This line ends at end of (accessible part of) buffer.
946 There is no newline to count. */
947 adjust = Z - tlendpos - charstart_next_line[left];
948 else
949 /* This line ends in a newline.
950 Must take account of the newline and the rest of the
951 text that follows. */
952 adjust = Z - tlendpos + 1 - charstart_next_line[left];
954 adjust_window_charstarts (w, this_line_vpos, adjust);
957 if (XFASTINT (w->width) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
958 preserve_other_columns (w);
959 goto update;
961 else
962 goto cancel;
964 else if (PT == XFASTINT (w->last_point)
965 /* Make sure the cursor was last displayed
966 in this window. Otherwise we have to reposition it. */
967 && XINT (w->top) <= FRAME_CURSOR_Y (selected_frame)
968 && (XINT (w->top) + XINT (w->height)
969 > FRAME_CURSOR_Y (selected_frame)))
971 if (!must_finish)
973 do_pending_window_change ();
974 return;
976 goto update;
978 /* If highlighting the region, or if the cursor is in the echo area,
979 then we can't just move the cursor. */
980 else if (! (!NILP (Vtransient_mark_mode)
981 && !NILP (current_buffer->mark_active))
982 && NILP (w->region_showing)
983 && !cursor_in_echo_area)
985 pos = *compute_motion (tlbufpos, 0,
986 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
988 PT, 2, - (1 << (SHORTBITS - 1)),
989 window_internal_width (w) - 1,
990 XINT (w->hscroll),
991 pos_tab_offset (w, tlbufpos), w);
992 if (pos.vpos < 1)
994 int width = window_internal_width (w) - 1;
995 FRAME_CURSOR_X (selected_frame)
996 = XFASTINT (w->left) + minmax (0, pos.hpos, width);
997 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
998 goto update;
1000 else
1001 goto cancel;
1003 cancel:
1004 /* Text changed drastically or point moved off of line */
1005 cancel_line (this_line_vpos, selected_frame);
1008 this_line_bufpos = 0;
1009 all_windows |= buffer_shared > 1;
1011 clear_face_cache_count++;
1013 if (all_windows)
1015 Lisp_Object tail, frame;
1017 #ifdef HAVE_FACES
1018 /* Clear the face cache, only when we do a full redisplay
1019 and not too often either. */
1020 if (clear_face_cache_count > 1000)
1022 clear_face_cache ();
1023 clear_face_cache_count = 0;
1025 #endif
1027 /* Recompute # windows showing selected buffer.
1028 This will be incremented each time such a window is displayed. */
1029 buffer_shared = 0;
1031 FOR_EACH_FRAME (tail, frame)
1033 FRAME_PTR f = XFRAME (frame);
1034 if (! FRAME_TERMCAP_P (f) || f == selected_frame)
1037 /* Mark all the scroll bars to be removed; we'll redeem the ones
1038 we want when we redisplay their windows. */
1039 if (condemn_scroll_bars_hook)
1040 (*condemn_scroll_bars_hook) (f);
1042 if (FRAME_VISIBLE_P (f))
1043 redisplay_windows (FRAME_ROOT_WINDOW (f));
1045 /* Any scroll bars which redisplay_windows should have nuked
1046 should now go away. */
1047 if (judge_scroll_bars_hook)
1048 (*judge_scroll_bars_hook) (f);
1052 else if (FRAME_VISIBLE_P (selected_frame))
1054 redisplay_window (selected_window, 1);
1055 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
1056 preserve_other_columns (w);
1059 update:
1060 /* Prevent various kinds of signals during display update.
1061 stdio is not robust about handling signals,
1062 which can cause an apparent I/O error. */
1063 if (interrupt_input)
1064 unrequest_sigio ();
1065 stop_polling ();
1067 #ifdef MULTI_FRAME
1068 if (all_windows)
1070 Lisp_Object tail;
1072 pause = 0;
1074 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1076 FRAME_PTR f;
1078 if (!FRAMEP (XCONS (tail)->car))
1079 continue;
1081 f = XFRAME (XCONS (tail)->car);
1083 if ((! FRAME_TERMCAP_P (f) || f == selected_frame)
1084 && FRAME_VISIBLE_P (f))
1086 pause |= update_frame (f, 0, 0);
1087 if (!pause)
1089 mark_window_display_accurate (f->root_window, 1);
1090 if (frame_up_to_date_hook != 0)
1091 (*frame_up_to_date_hook) (f);
1096 else
1097 #endif /* MULTI_FRAME */
1099 if (FRAME_VISIBLE_P (selected_frame))
1100 pause = update_frame (selected_frame, 0, 0);
1101 else
1102 pause = 0;
1104 /* We may have called echo_area_display at the top of this
1105 function. If the echo area is on another frame, that may
1106 have put text on a frame other than the selected one, so the
1107 above call to update_frame would not have caught it. Catch
1108 it here. */
1110 Lisp_Object mini_window;
1111 FRAME_PTR mini_frame;
1113 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
1114 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
1116 if (mini_frame != selected_frame
1117 && ! FRAME_TERMCAP_P (mini_frame))
1118 pause |= update_frame (mini_frame, 0, 0);
1122 /* If frame does not match, prevent doing single-line-update next time.
1123 Also, don't forget to check every line to update the arrow. */
1124 if (pause)
1126 this_line_bufpos = 0;
1127 if (!NILP (last_arrow_position))
1129 last_arrow_position = Qt;
1130 last_arrow_string = Qt;
1132 /* If we pause after scrolling, some lines in current_frame
1133 may be null, so preserve_other_columns won't be able to
1134 preserve all the vertical-bar separators. So, avoid using it
1135 in that case. */
1136 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
1137 update_mode_lines = 1;
1140 /* Now text on frame agrees with windows, so
1141 put info into the windows for partial redisplay to follow */
1143 if (!pause)
1145 register struct buffer *b = XBUFFER (w->buffer);
1147 blank_end_of_window = 0;
1148 unchanged_modified = BUF_MODIFF (b);
1149 beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
1150 end_unchanged = BUF_Z (b) - BUF_GPT (b);
1152 XSETFASTINT (w->last_point, BUF_PT (b));
1153 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
1154 XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
1156 if (all_windows)
1157 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
1158 else
1160 b->clip_changed = 0;
1161 w->update_mode_line = Qnil;
1162 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
1163 w->window_end_valid = w->buffer;
1164 last_arrow_position = Voverlay_arrow_position;
1165 last_arrow_string = Voverlay_arrow_string;
1166 if (do_verify_charstarts)
1167 verify_charstarts (w);
1168 if (frame_up_to_date_hook != 0)
1169 (*frame_up_to_date_hook) (selected_frame);
1171 update_mode_lines = 0;
1172 windows_or_buffers_changed = 0;
1175 /* Start SIGIO interrupts coming again.
1176 Having them off during the code above
1177 makes it less likely one will discard output,
1178 but not impossible, since there might be stuff
1179 in the system buffer here.
1180 But it is much hairier to try to do anything about that. */
1182 if (interrupt_input)
1183 request_sigio ();
1184 start_polling ();
1186 /* Change frame size now if a change is pending. */
1187 do_pending_window_change ();
1189 /* If we just did a pending size change, redisplay again
1190 for the new size. */
1191 if (windows_or_buffers_changed && !pause)
1192 redisplay ();
1195 /* Redisplay, but leave alone any recent echo area message
1196 unless another message has been requested in its place.
1198 This is useful in situations where you need to redisplay but no
1199 user action has occurred, making it inappropriate for the message
1200 area to be cleared. See tracking_off and
1201 wait_reading_process_input for examples of these situations. */
1203 redisplay_preserve_echo_area ()
1205 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
1207 echo_area_glyphs = previous_echo_glyphs;
1208 redisplay ();
1209 echo_area_glyphs = 0;
1211 else
1212 redisplay ();
1215 void
1216 mark_window_display_accurate (window, flag)
1217 Lisp_Object window;
1218 int flag;
1220 register struct window *w;
1222 for (;!NILP (window); window = w->next)
1224 if (!WINDOWP (window)) abort ();
1225 w = XWINDOW (window);
1227 if (!NILP (w->buffer))
1229 XSETFASTINT (w->last_modified,
1230 !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
1232 /* Record if we are showing a region, so can make sure to
1233 update it fully at next redisplay. */
1234 w->region_showing = (!NILP (Vtransient_mark_mode)
1235 && !NILP (XBUFFER (w->buffer)->mark_active)
1236 ? Fmarker_position (XBUFFER (w->buffer)->mark)
1237 : Qnil);
1240 w->window_end_valid = w->buffer;
1241 w->update_mode_line = Qnil;
1242 if (!NILP (w->buffer))
1243 XBUFFER (w->buffer)->clip_changed = 0;
1245 if (!NILP (w->vchild))
1246 mark_window_display_accurate (w->vchild, flag);
1247 if (!NILP (w->hchild))
1248 mark_window_display_accurate (w->hchild, flag);
1251 if (flag)
1253 last_arrow_position = Voverlay_arrow_position;
1254 last_arrow_string = Voverlay_arrow_string;
1256 else
1258 /* t is unequal to any useful value of Voverlay_arrow_... */
1259 last_arrow_position = Qt;
1260 last_arrow_string = Qt;
1264 /* Update the menu bar item list for frame F.
1265 This has to be done before we start to fill in any display lines,
1266 because it can call eval.
1268 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1270 static void
1271 update_menu_bar (f, save_match_data)
1272 FRAME_PTR f;
1273 int save_match_data;
1275 struct buffer *old = current_buffer;
1276 Lisp_Object window;
1277 register struct window *w;
1279 window = FRAME_SELECTED_WINDOW (f);
1280 w = XWINDOW (window);
1282 if (update_mode_lines)
1283 w->update_mode_line = Qt;
1285 if (
1286 #ifdef USE_X_TOOLKIT
1287 FRAME_EXTERNAL_MENU_BAR (f)
1288 #else
1289 FRAME_MENU_BAR_LINES (f) > 0
1290 #endif
1293 /* If the user has switched buffers or windows, we need to
1294 recompute to reflect the new bindings. But we'll
1295 recompute when update_mode_lines is set too; that means
1296 that people can use force-mode-line-update to request
1297 that the menu bar be recomputed. The adverse effect on
1298 the rest of the redisplay algorithm is about the same as
1299 windows_or_buffers_changed anyway. */
1300 if (windows_or_buffers_changed
1301 || !NILP (w->update_mode_line)
1302 || (XFASTINT (w->last_modified) < MODIFF
1303 && (XFASTINT (w->last_modified)
1304 <= BUF_SAVE_MODIFF (XBUFFER (w->buffer))))
1305 || ((!NILP (Vtransient_mark_mode)
1306 && !NILP (XBUFFER (w->buffer)->mark_active))
1307 != !NILP (w->region_showing)))
1309 struct buffer *prev = current_buffer;
1310 int count = specpdl_ptr - specpdl;
1312 set_buffer_internal_1 (XBUFFER (w->buffer));
1313 if (save_match_data)
1314 record_unwind_protect (Fstore_match_data, Fmatch_data ());
1315 if (NILP (Voverriding_local_map_menu_flag))
1317 specbind (Qoverriding_terminal_local_map, Qnil);
1318 specbind (Qoverriding_local_map, Qnil);
1321 /* Run the Lucid hook. */
1322 call1 (Vrun_hooks, Qactivate_menubar_hook);
1323 /* If it has changed current-menubar from previous value,
1324 really recompute the menubar from the value. */
1325 if (! NILP (Vlucid_menu_bar_dirty_flag))
1326 call0 (Qrecompute_lucid_menubar);
1327 call1 (Vrun_hooks, Qmenu_bar_update_hook);
1328 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1329 #ifdef USE_X_TOOLKIT
1330 set_frame_menubar (f, 0, 0);
1331 #endif /* USE_X_TOOLKIT */
1333 unbind_to (count, Qnil);
1334 set_buffer_internal_1 (prev);
1339 int do_id = 1;
1341 /* Redisplay WINDOW and its subwindows and siblings. */
1343 static void
1344 redisplay_windows (window)
1345 Lisp_Object window;
1347 for (; !NILP (window); window = XWINDOW (window)->next)
1348 redisplay_window (window, 0);
1351 /* Redisplay window WINDOW and its subwindows. */
1353 static void
1354 redisplay_window (window, just_this_one)
1355 Lisp_Object window;
1356 int just_this_one;
1358 register struct window *w = XWINDOW (window);
1359 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1360 int height;
1361 register int lpoint = PT;
1362 struct buffer *old = current_buffer;
1363 register int width = window_internal_width (w) - 1;
1364 register int startp;
1365 register int hscroll = XINT (w->hscroll);
1366 struct position pos;
1367 int opoint = PT;
1368 int tem;
1369 int update_mode_line;
1370 struct Lisp_Vector *dp = window_display_table (w);
1372 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1374 /* If this is a combination window, do its children; that's all. */
1376 if (!NILP (w->vchild))
1378 redisplay_windows (w->vchild);
1379 return;
1381 if (!NILP (w->hchild))
1383 redisplay_windows (w->hchild);
1384 return;
1386 if (NILP (w->buffer))
1387 abort ();
1389 height = window_internal_height (w);
1390 update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
1391 if (XBUFFER (w->buffer)->clip_changed)
1392 update_mode_line = 1;
1394 if (MINI_WINDOW_P (w))
1396 if (w == XWINDOW (echo_area_window) && echo_area_glyphs)
1397 /* We've already displayed the echo area glyphs in this window. */
1398 goto finish_scroll_bars;
1399 else if (w != XWINDOW (minibuf_window))
1401 /* This is a minibuffer, but it's not the currently active one,
1402 so clear it. */
1403 int vpos = XFASTINT (w->top);
1404 int i;
1406 for (i = 0; i < height; i++)
1408 get_display_line (f, vpos + i, 0);
1409 display_string (w, vpos + i, "", 0, 0, 0, 1, 0, width);
1412 goto finish_scroll_bars;
1416 /* Otherwise set up data on this window; select its buffer and point value */
1418 if (update_mode_line)
1419 set_buffer_internal_1 (XBUFFER (w->buffer));
1420 else
1421 set_buffer_temp (XBUFFER (w->buffer));
1423 opoint = PT;
1425 /* If %c is in mode line, update it if needed. */
1426 if (!NILP (w->column_number_displayed)
1427 /* This alternative quickly identifies a common case
1428 where no change is needed. */
1429 && !(PT == XFASTINT (w->last_point)
1430 && XFASTINT (w->last_modified) >= MODIFF)
1431 && XFASTINT (w->column_number_displayed) != current_column ())
1432 update_mode_line = 1;
1434 /* Count number of windows showing the selected buffer.
1435 An indirect buffer counts as its base buffer. */
1437 if (!just_this_one)
1439 struct buffer *current_base, *window_base;
1440 current_base = current_buffer;
1441 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
1442 if (current_base->base_buffer)
1443 current_base = current_base->base_buffer;
1444 if (window_base->base_buffer)
1445 window_base = window_base->base_buffer;
1446 if (current_base == window_base)
1447 buffer_shared++;
1450 /* POINT refers normally to the selected window.
1451 For any other window, set up appropriate value. */
1453 if (!EQ (window, selected_window))
1455 int new_pt = marker_position (w->pointm);
1456 if (new_pt < BEGV)
1458 new_pt = BEGV;
1459 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1461 else if (new_pt > (ZV - 1))
1463 new_pt = ZV;
1464 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1466 /* We don't use SET_PT so that the point-motion hooks don't run. */
1467 BUF_PT (current_buffer) = new_pt;
1470 /* If any of the character widths specified in the display table
1471 have changed, invalidate the width run cache. It's true that this
1472 may be a bit late to catch such changes, but the rest of
1473 redisplay goes (non-fatally) haywire when the display table is
1474 changed, so why should we worry about doing any better? */
1475 if (current_buffer->width_run_cache)
1477 struct Lisp_Vector *disptab = buffer_display_table ();
1479 if (! disptab_matches_widthtab (disptab,
1480 XVECTOR (current_buffer->width_table)))
1482 invalidate_region_cache (current_buffer,
1483 current_buffer->width_run_cache,
1484 BEG, Z);
1485 recompute_width_table (current_buffer, disptab);
1489 /* If window-start is screwed up, choose a new one. */
1490 if (XMARKER (w->start)->buffer != current_buffer)
1491 goto recenter;
1493 startp = marker_position (w->start);
1495 /* Handle case where place to start displaying has been specified,
1496 unless the specified location is outside the accessible range. */
1497 if (!NILP (w->force_start))
1499 /* Forget any recorded base line for line number display. */
1500 w->base_line_number = Qnil;
1501 /* Redisplay the mode line. Select the buffer properly for that. */
1502 if (!update_mode_line)
1504 set_buffer_temp (old);
1505 set_buffer_internal_1 (XBUFFER (w->buffer));
1506 update_mode_line = 1;
1507 w->update_mode_line = Qt;
1509 w->force_start = Qnil;
1510 XSETFASTINT (w->last_modified, 0);
1511 if (startp < BEGV) startp = BEGV;
1512 if (startp > ZV) startp = ZV;
1513 try_window (window, startp);
1514 if (cursor_vpos < 0)
1516 /* If point does not appear, move point so it does appear */
1517 pos = *compute_motion (startp, 0,
1518 (((EQ (window, minibuf_window)
1519 && startp == BEG)
1520 ? minibuf_prompt_width : 0)
1521 + (hscroll ? 1 - hscroll : 0)),
1523 ZV, height / 2,
1524 - (1 << (SHORTBITS - 1)),
1525 width, hscroll, pos_tab_offset (w, startp), w);
1526 BUF_PT (current_buffer) = pos.bufpos;
1527 if (w != XWINDOW (selected_window))
1528 Fset_marker (w->pointm, make_number (PT), Qnil);
1529 else
1531 if (current_buffer == old)
1532 lpoint = PT;
1533 FRAME_CURSOR_X (f) = (XFASTINT (w->left)
1534 + minmax (0, pos.hpos, width));
1535 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1537 /* If we are highlighting the region,
1538 then we just changed the region, so redisplay to show it. */
1539 if (!NILP (Vtransient_mark_mode)
1540 && !NILP (current_buffer->mark_active))
1542 cancel_my_columns (XWINDOW (window));
1543 try_window (window, startp);
1546 goto done;
1549 /* Handle case where text has not changed, only point,
1550 and it has not moved off the frame */
1552 /* This code is not used for minibuffer for the sake of
1553 the case of redisplaying to replace an echo area message;
1554 since in that case the minibuffer contents per se are usually unchanged.
1555 This code is of no real use in the minibuffer since
1556 the handling of this_line_bufpos, etc.,
1557 in redisplay handles the same cases. */
1559 if (XFASTINT (w->last_modified) >= MODIFF
1560 && PT >= startp && !current_buffer->clip_changed
1561 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
1562 /* If force-mode-line-update was called, really redisplay;
1563 that's how redisplay is forced after e.g. changing
1564 buffer-invisibility-spec. */
1565 && NILP (w->update_mode_line)
1566 /* Can't use this case if highlighting a region. */
1567 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1568 && NILP (w->region_showing)
1569 /* If end pos is out of date, scroll bar and percentage will be wrong */
1570 && INTEGERP (w->window_end_vpos)
1571 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
1572 && !EQ (window, minibuf_window))
1574 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
1575 PT, height, 0, width, hscroll,
1576 pos_tab_offset (w, startp), w);
1578 if (pos.vpos < height)
1580 /* Ok, point is still on frame */
1581 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1583 /* These variables are supposed to be origin 1 */
1584 FRAME_CURSOR_X (f) = (XFASTINT (w->left)
1585 + minmax (0, pos.hpos, width));
1586 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1588 /* This doesn't do the trick, because if a window to the right of
1589 this one must be redisplayed, this does nothing because there
1590 is nothing in DesiredFrame yet, and then the other window is
1591 redisplayed, making likes that are empty in this window's columns.
1592 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1593 preserve_my_columns (w);
1595 goto done;
1597 /* Don't bother trying redisplay with same start;
1598 we already know it will lose */
1600 /* If current starting point was originally the beginning of a line
1601 but no longer is, find a new starting point. */
1602 else if (!NILP (w->start_at_line_beg)
1603 && !(startp <= BEGV
1604 || FETCH_CHAR (startp - 1) == '\n'))
1606 goto recenter;
1608 else if (just_this_one && !MINI_WINDOW_P (w)
1609 && PT >= startp
1610 && XFASTINT (w->last_modified)
1611 /* or else vmotion on first line won't work. */
1612 && ! NILP (w->start_at_line_beg)
1613 && ! EQ (w->window_end_valid, Qnil)
1614 && do_id && !current_buffer->clip_changed
1615 && !blank_end_of_window
1616 && XFASTINT (w->width) == FRAME_WIDTH (f)
1617 /* Can't use this case if highlighting a region. */
1618 && !(!NILP (Vtransient_mark_mode)
1619 && !NILP (current_buffer->mark_active))
1620 /* Don't use try_window_id if newline
1621 doesn't display as the end of a line. */
1622 && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
1623 && NILP (w->region_showing)
1624 && EQ (last_arrow_position, Voverlay_arrow_position)
1625 && EQ (last_arrow_string, Voverlay_arrow_string)
1626 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
1627 && tem != -2)
1629 /* tem > 0 means success. tem == -1 means choose new start.
1630 tem == -2 means try again with same start,
1631 and nothing but whitespace follows the changed stuff.
1632 tem == 0 means try again with same start. */
1633 if (tem > 0)
1634 goto done;
1636 else if (startp >= BEGV && startp <= ZV
1637 /* Avoid starting display at end of buffer! */
1638 && (startp < ZV || startp == BEGV
1639 || (XFASTINT (w->last_modified) >= MODIFF)))
1641 /* Try to redisplay starting at same place as before */
1642 /* If point has not moved off frame, accept the results */
1643 try_window (window, startp);
1644 if (cursor_vpos >= 0)
1646 if (!just_this_one || current_buffer->clip_changed
1647 || beg_unchanged < startp)
1648 /* Forget any recorded base line for line number display. */
1649 w->base_line_number = Qnil;
1650 goto done;
1652 else
1653 cancel_my_columns (w);
1656 XSETFASTINT (w->last_modified, 0);
1657 /* Redisplay the mode line. Select the buffer properly for that. */
1658 if (!update_mode_line)
1660 set_buffer_temp (old);
1661 set_buffer_internal_1 (XBUFFER (w->buffer));
1662 update_mode_line = 1;
1663 w->update_mode_line = Qt;
1666 /* Try to scroll by specified few lines */
1668 if (scroll_step && !current_buffer->clip_changed)
1670 if (PT > startp)
1672 pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
1673 if (pos.vpos >= height)
1674 goto scroll_fail;
1677 pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
1679 if (PT >= pos.bufpos)
1681 try_window (window, pos.bufpos);
1682 if (cursor_vpos >= 0)
1684 if (!just_this_one || current_buffer->clip_changed
1685 || beg_unchanged < startp)
1686 /* Forget any recorded base line for line number display. */
1687 w->base_line_number = Qnil;
1688 goto done;
1690 else
1691 cancel_my_columns (w);
1693 scroll_fail: ;
1696 /* Finally, just choose place to start which centers point */
1698 recenter:
1699 /* Forget any previously recorded base line for line number display. */
1700 w->base_line_number = Qnil;
1702 pos = *vmotion (PT, - (height / 2), w);
1703 try_window (window, pos.bufpos);
1705 startp = marker_position (w->start);
1706 w->start_at_line_beg
1707 = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
1709 done:
1710 if ((update_mode_line
1711 /* If window not full width, must redo its mode line
1712 if the window to its side is being redone */
1713 || (!just_this_one && width < FRAME_WIDTH (f) - 1)
1714 || INTEGERP (w->base_line_pos)
1715 || (!NILP (w->column_number_displayed)
1716 && XFASTINT (w->column_number_displayed) != current_column ()))
1717 && height != XFASTINT (w->height))
1718 display_mode_line (w);
1719 if (! line_number_displayed
1720 && ! BUFFERP (w->base_line_pos))
1722 w->base_line_pos = Qnil;
1723 w->base_line_number = Qnil;
1726 /* When we reach a frame's selected window, redo the frame's menu bar. */
1727 if (update_mode_line
1728 #ifdef USE_X_TOOLKIT
1729 && FRAME_EXTERNAL_MENU_BAR (f)
1730 #else
1731 && FRAME_MENU_BAR_LINES (f) > 0
1732 #endif
1733 && EQ (FRAME_SELECTED_WINDOW (f), window))
1734 display_menu_bar (w);
1736 finish_scroll_bars:
1737 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1739 int start, end, whole;
1741 /* Calculate the start and end positions for the current window.
1742 At some point, it would be nice to choose between scrollbars
1743 which reflect the whole buffer size, with special markers
1744 indicating narrowing, and scrollbars which reflect only the
1745 visible region.
1747 Note that minibuffers sometimes aren't displaying any text. */
1748 if (! MINI_WINDOW_P (w)
1749 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
1751 whole = ZV - BEGV;
1752 start = marker_position (w->start) - BEGV;
1753 /* I don't think this is guaranteed to be right. For the
1754 moment, we'll pretend it is. */
1755 end = (Z - XINT (w->window_end_pos)) - BEGV;
1757 if (end < start) end = start;
1758 if (whole < (end - start)) whole = end - start;
1760 else
1761 start = end = whole = 0;
1763 /* Indicate what this scroll bar ought to be displaying now. */
1764 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
1766 /* Note that we actually used the scroll bar attached to this window,
1767 so it shouldn't be deleted at the end of redisplay. */
1768 (*redeem_scroll_bar_hook) (w);
1771 BUF_PT (current_buffer) = opoint;
1772 if (update_mode_line)
1773 set_buffer_internal_1 (old);
1774 else
1775 set_buffer_temp (old);
1776 BUF_PT (current_buffer) = lpoint;
1779 /* Do full redisplay on one window, starting at position `pos'. */
1781 static void
1782 try_window (window, pos)
1783 Lisp_Object window;
1784 register int pos;
1786 register struct window *w = XWINDOW (window);
1787 register int height = window_internal_height (w);
1788 register int vpos = XFASTINT (w->top);
1789 register int last_text_vpos = vpos;
1790 int tab_offset = pos_tab_offset (w, pos);
1791 FRAME_PTR f = XFRAME (w->frame);
1792 int width = window_internal_width (w) - 1;
1793 struct position val;
1795 Fset_marker (w->start, make_number (pos), Qnil);
1796 cursor_vpos = -1;
1797 overlay_arrow_seen = 0;
1798 zv_strings_seen = 0;
1799 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
1801 while (--height >= 0)
1803 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
1804 tab_offset += width;
1805 /* For the first line displayed, display_text_line
1806 subtracts the prompt width from the tab offset.
1807 But it does not affect the value of our variable tab_offset.
1808 So we do the subtraction again,
1809 for the sake of continuation lines of that first line. */
1810 if (MINI_WINDOW_P (w) && vpos == XFASTINT (w->top))
1811 tab_offset -= minibuf_prompt_width;
1813 if (val.vpos) tab_offset = 0;
1814 vpos++;
1815 if (pos != val.bufpos)
1817 int invis = 0;
1818 #ifdef USE_TEXT_PROPERTIES
1819 Lisp_Object invis_prop;
1820 invis_prop = Fget_char_property (val.bufpos-1, Qinvisible, window);
1821 invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
1822 #endif
1824 last_text_vpos
1825 /* Next line, unless prev line ended in end of buffer with no cr */
1826 = vpos - (val.vpos
1827 && (FETCH_CHAR (val.bufpos - 1) != '\n' || invis));
1829 pos = val.bufpos;
1832 /* If last line is continued in middle of character,
1833 include the split character in the text considered on the frame */
1834 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
1835 pos++;
1837 /* If bottom just moved off end of frame, change mode line percentage. */
1838 if (XFASTINT (w->window_end_pos) == 0
1839 && Z != pos)
1840 w->update_mode_line = Qt;
1842 /* Say where last char on frame will be, once redisplay is finished. */
1843 XSETFASTINT (w->window_end_pos, Z - pos);
1844 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
1845 /* But that is not valid info until redisplay finishes. */
1846 w->window_end_valid = Qnil;
1849 /* Try to redisplay when buffer is modified locally,
1850 computing insert/delete line to preserve text outside
1851 the bounds of the changes.
1852 Return 1 if successful, 0 if if cannot tell what to do,
1853 or -1 to tell caller to find a new window start,
1854 or -2 to tell caller to do normal redisplay with same window start. */
1856 static int
1857 try_window_id (window)
1858 Lisp_Object window;
1860 int pos;
1861 register struct window *w = XWINDOW (window);
1862 register int height = window_internal_height (w);
1863 FRAME_PTR f = XFRAME (w->frame);
1864 int top = XFASTINT (w->top);
1865 int start = marker_position (w->start);
1866 int width = window_internal_width (w) - 1;
1867 int hscroll = XINT (w->hscroll);
1868 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1869 int did_motion;
1870 register int vpos;
1871 register int i, tem;
1872 int last_text_vpos = 0;
1873 int stop_vpos;
1874 int selective = (INTEGERP (current_buffer->selective_display)
1875 ? XINT (current_buffer->selective_display)
1876 : !NILP (current_buffer->selective_display) ? -1 : 0);
1878 struct position val, bp, ep, xp, pp;
1879 int scroll_amount = 0;
1880 int delta;
1881 int tab_offset, epto;
1883 if (GPT - BEG < beg_unchanged)
1884 beg_unchanged = GPT - BEG;
1885 if (Z - GPT < end_unchanged)
1886 end_unchanged = Z - GPT;
1888 if (beg_unchanged + BEG < start)
1889 return 0; /* Give up if changes go above top of window */
1891 /* Find position before which nothing is changed. */
1892 bp = *compute_motion (start, 0, lmargin, 0,
1893 min (ZV, beg_unchanged + BEG), height, 0,
1894 width, hscroll, pos_tab_offset (w, start), w);
1895 if (bp.vpos >= height)
1897 if (PT < bp.bufpos)
1899 /* All changes are below the frame, and point is on the frame.
1900 We don't need to change the frame at all.
1901 But we need to update window_end_pos to account for
1902 any change in buffer size. */
1903 bp = *compute_motion (start, 0, lmargin, 0,
1904 Z, height, 0,
1905 width, hscroll, pos_tab_offset (w, start), w);
1906 XSETFASTINT (w->window_end_vpos, height);
1907 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
1908 goto findpoint;
1910 return 0;
1913 vpos = bp.vpos;
1915 /* Find beginning of that frame line. Must display from there. */
1916 bp = *vmotion (bp.bufpos, 0, w);
1918 pos = bp.bufpos;
1919 val.hpos = lmargin;
1920 if (pos < start)
1921 return -1;
1923 did_motion = 0;
1924 /* If about to start displaying at the beginning of a continuation line,
1925 really start with previous frame line, in case it was not
1926 continued when last redisplayed */
1927 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
1929 /* Likewise if we have to worry about selective display. */
1930 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
1932 bp = *vmotion (bp.bufpos, -1, w);
1933 --vpos;
1934 pos = bp.bufpos;
1937 if (bp.contin && bp.hpos != lmargin)
1939 val.hpos = bp.prevhpos - width + lmargin;
1940 did_motion = 1;
1941 pos--;
1944 bp.vpos = vpos;
1946 /* Find first visible newline after which no more is changed. */
1947 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
1948 if (selective > 0)
1949 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
1950 tem = find_next_newline (tem, 1);
1952 /* Compute the cursor position after that newline. */
1953 ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
1954 height, - (1 << (SHORTBITS - 1)),
1955 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
1957 /* If changes reach past the text available on the frame,
1958 just display rest of frame. */
1959 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
1960 stop_vpos = height;
1961 else
1962 stop_vpos = ep.vpos;
1964 /* If no newline before ep, the line ep is on includes some changes
1965 that must be displayed. Make sure we don't stop before it. */
1966 /* Also, if changes reach all the way until ep.bufpos,
1967 it is possible that something was deleted after the
1968 newline before it, so the following line must be redrawn. */
1969 if (stop_vpos == ep.vpos
1970 && (ep.bufpos == BEGV
1971 || FETCH_CHAR (ep.bufpos - 1) != '\n'
1972 || ep.bufpos == Z - end_unchanged))
1973 stop_vpos = ep.vpos + 1;
1975 cursor_vpos = -1;
1976 overlay_arrow_seen = 0;
1977 zv_strings_seen = 0;
1979 /* If changes do not reach to bottom of window,
1980 figure out how much to scroll the rest of the window */
1981 if (stop_vpos < height)
1983 /* Now determine how far up or down the rest of the window has moved */
1984 epto = pos_tab_offset (w, ep.bufpos);
1985 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
1986 Z - XFASTINT (w->window_end_pos),
1987 10000, 0, width, hscroll, epto, w);
1988 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
1990 /* Is everything on frame below the changes whitespace?
1991 If so, no scrolling is really necessary. */
1992 for (i = ep.bufpos; i < xp.bufpos; i++)
1994 tem = FETCH_CHAR (i);
1995 if (tem != ' ' && tem != '\n' && tem != '\t')
1996 break;
1998 if (i == xp.bufpos)
1999 return -2;
2001 XSETFASTINT (w->window_end_vpos,
2002 XFASTINT (w->window_end_vpos) + scroll_amount);
2004 /* Before doing any scrolling, verify that point will be on frame. */
2005 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
2007 if (PT <= xp.bufpos)
2009 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
2010 PT, height, - (1 << (SHORTBITS - 1)),
2011 width, hscroll, epto, w);
2013 else
2015 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
2016 PT, height, - (1 << (SHORTBITS - 1)),
2017 width, hscroll,
2018 pos_tab_offset (w, xp.bufpos), w);
2020 if (pp.bufpos < PT || pp.vpos == height)
2021 return 0;
2022 cursor_vpos = pp.vpos + top;
2023 cursor_hpos = XFASTINT (w->left) + minmax (0, pp.hpos, width);
2026 if (stop_vpos - scroll_amount >= height
2027 || ep.bufpos == xp.bufpos)
2029 if (scroll_amount < 0)
2030 stop_vpos -= scroll_amount;
2031 scroll_amount = 0;
2032 /* In this path, we have altered window_end_vpos
2033 and not left it negative.
2034 We must make sure that, in case display is preempted
2035 before the frame changes to reflect what we do here,
2036 further updates will not come to try_window_id
2037 and assume the frame and window_end_vpos match. */
2038 blank_end_of_window = 1;
2040 else if (!scroll_amount)
2042 /* Even if we don't need to scroll, we must adjust the
2043 charstarts of subsequent lines (that we won't redisplay)
2044 according to the amount of text inserted or deleted. */
2045 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2046 int adjust = ep.bufpos - oldpos;
2047 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
2049 else if (bp.bufpos == Z - end_unchanged)
2051 /* If reprinting everything is nearly as fast as scrolling,
2052 don't bother scrolling. Can happen if lines are short. */
2053 if (scroll_cost (f, bp.vpos + top - scroll_amount,
2054 top + height - max (0, scroll_amount),
2055 scroll_amount)
2056 > xp.bufpos - bp.bufpos - 20)
2057 /* Return "try normal display with same window-start."
2058 Too bad we can't prevent further scroll-thinking. */
2059 return -2;
2060 /* If pure deletion, scroll up as many lines as possible.
2061 In common case of killing a line, this can save the
2062 following line from being overwritten by scrolling
2063 and therefore having to be redrawn. */
2064 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
2065 top + height - max (0, scroll_amount),
2066 scroll_amount, bp.bufpos);
2067 if (!tem)
2068 stop_vpos = height;
2069 else
2071 /* scroll_frame_lines did not properly adjust subsequent
2072 lines' charstarts in the case where the text of the
2073 screen line at bp.vpos has changed.
2074 (This can happen in a deletion that ends in mid-line.)
2075 To adjust properly, we need to make things constent at
2076 the position ep.
2077 So do a second adjust to make that happen.
2078 Note that stop_vpos >= ep.vpos, so it is sufficient
2079 to update the charstarts for lines at ep.vpos and below. */
2080 int oldstart
2081 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2082 adjust_window_charstarts (w, ep.vpos + top - 1,
2083 ep.bufpos - oldstart);
2086 else if (scroll_amount)
2088 /* If reprinting everything is nearly as fast as scrolling,
2089 don't bother scrolling. Can happen if lines are short. */
2090 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2091 overestimate of cost of reprinting, since xp.bufpos
2092 would end up below the bottom of the window. */
2093 if (scroll_cost (f, ep.vpos + top - scroll_amount,
2094 top + height - max (0, scroll_amount),
2095 scroll_amount)
2096 > xp.bufpos - ep.bufpos - 20)
2097 /* Return "try normal display with same window-start."
2098 Too bad we can't prevent further scroll-thinking. */
2099 return -2;
2100 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
2101 top + height - max (0, scroll_amount),
2102 scroll_amount, ep.bufpos);
2103 if (!tem) stop_vpos = height;
2107 /* In any case, do not display past bottom of window */
2108 if (stop_vpos >= height)
2110 stop_vpos = height;
2111 scroll_amount = 0;
2114 /* Handle case where pos is before w->start --
2115 can happen if part of line had been clipped and is not clipped now */
2116 if (vpos == 0 && pos < marker_position (w->start))
2117 Fset_marker (w->start, make_number (pos), Qnil);
2119 /* Redisplay the lines where the text was changed */
2120 last_text_vpos = vpos;
2121 tab_offset = pos_tab_offset (w, pos);
2122 /* If we are starting display in mid-character, correct tab_offset
2123 to account for passing the line that that character really starts in. */
2124 if (val.hpos < lmargin)
2125 tab_offset += width;
2126 while (vpos < stop_vpos)
2128 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
2129 tab_offset += width;
2130 if (val.vpos) tab_offset = 0;
2131 if (pos != val.bufpos)
2132 last_text_vpos
2133 /* Next line, unless prev line ended in end of buffer with no cr */
2134 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
2135 pos = val.bufpos;
2138 /* There are two cases:
2139 1) we have displayed down to the bottom of the window
2140 2) we have scrolled lines below stop_vpos by scroll_amount */
2142 if (vpos == height)
2144 /* If last line is continued in middle of character,
2145 include the split character in the text considered on the frame */
2146 if (val.hpos < lmargin)
2147 val.bufpos++;
2148 XSETFASTINT (w->window_end_vpos, last_text_vpos);
2149 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
2152 /* If scrolling made blank lines at window bottom,
2153 redisplay to fill those lines */
2154 if (scroll_amount < 0)
2156 /* Don't consider these lines for general-purpose scrolling.
2157 That will save time in the scrolling computation. */
2158 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
2159 vpos = xp.vpos;
2160 pos = xp.bufpos;
2161 val.hpos = lmargin;
2162 if (pos == ZV)
2163 vpos = height + scroll_amount;
2164 else if (xp.contin && xp.hpos != lmargin)
2166 val.hpos = xp.prevhpos - width + lmargin;
2167 pos--;
2170 blank_end_of_window = 1;
2171 tab_offset = pos_tab_offset (w, pos);
2172 /* If we are starting display in mid-character, correct tab_offset
2173 to account for passing the line that that character starts in. */
2174 if (val.hpos < lmargin)
2175 tab_offset += width;
2177 while (vpos < height)
2179 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
2180 tab_offset += width;
2181 if (val.vpos) tab_offset = 0;
2182 pos = val.bufpos;
2185 /* Here is a case where display_text_line sets cursor_vpos wrong.
2186 Make it be fixed up, below. */
2187 if (xp.bufpos == ZV
2188 && xp.bufpos == PT)
2189 cursor_vpos = -1;
2192 /* If bottom just moved off end of frame, change mode line percentage. */
2193 if (XFASTINT (w->window_end_pos) == 0
2194 && Z != val.bufpos)
2195 w->update_mode_line = Qt;
2197 /* Attempt to adjust end-of-text positions to new bottom line */
2198 if (scroll_amount)
2200 delta = height - xp.vpos;
2201 if (delta < 0
2202 || (delta > 0 && xp.bufpos <= ZV)
2203 || (delta == 0 && xp.hpos))
2205 val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
2206 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
2207 XSETFASTINT (w->window_end_vpos,
2208 XFASTINT (w->window_end_vpos) + val.vpos);
2212 w->window_end_valid = Qnil;
2214 /* If point was not in a line that was displayed, find it */
2215 if (cursor_vpos < 0)
2217 findpoint:
2218 val = *compute_motion (start, 0, lmargin, 0, PT, 10000, 10000,
2219 width, hscroll, pos_tab_offset (w, start), w);
2220 /* Admit failure if point is off frame now */
2221 if (val.vpos >= height)
2223 for (vpos = 0; vpos < height; vpos++)
2224 cancel_line (vpos + top, f);
2225 return 0;
2227 cursor_vpos = val.vpos + top;
2228 cursor_hpos = XFASTINT (w->left) + minmax (0, val.hpos, width);
2231 FRAME_CURSOR_X (f) = cursor_hpos;
2232 FRAME_CURSOR_Y (f) = cursor_vpos;
2234 if (debug_end_pos)
2236 val = *compute_motion (start, 0, lmargin, 0, ZV,
2237 height, - (1 << (SHORTBITS - 1)),
2238 width, hscroll, pos_tab_offset (w, start), w);
2239 if (val.vpos != XFASTINT (w->window_end_vpos))
2240 abort ();
2241 if (XFASTINT (w->window_end_pos)
2242 != Z - val.bufpos)
2243 abort ();
2246 return 1;
2249 /* Mark a section of BUF as modified, but only for the sake of redisplay.
2250 This is useful for recording changes to overlays.
2252 We increment the buffer's modification timestamp and set the
2253 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
2254 as if the region of text between START and END had been modified;
2255 the redisplay code will check this against the windows' timestamps,
2256 and redraw the appropriate area of the buffer.
2258 However, if the buffer is unmodified, we bump the last-save
2259 timestamp as well, so that incrementing the timestamp doesn't fool
2260 Emacs into thinking that the buffer's text has been modified.
2262 Tweaking the timestamps shouldn't hurt the first-modification
2263 timestamps recorded in the undo records; those values aren't
2264 written until just before a real text modification is made, so they
2265 will never catch the timestamp value just before this function gets
2266 called. */
2268 void
2269 redisplay_region (buf, start, end)
2270 struct buffer *buf;
2271 int start, end;
2273 if (start == end)
2274 return;
2276 if (start > end)
2278 int temp = start;
2279 start = end; end = temp;
2282 /* If this is a buffer not in the selected window,
2283 we must do other windows. */
2284 if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
2285 windows_or_buffers_changed = 1;
2286 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
2287 else if (buf != current_buffer)
2288 windows_or_buffers_changed = 1;
2289 /* If multiple windows show this buffer, we must do other windows. */
2290 else if (buffer_shared > 1)
2291 windows_or_buffers_changed = 1;
2292 else
2294 if (unchanged_modified == MODIFF)
2296 beg_unchanged = start - BEG;
2297 end_unchanged = Z - end;
2299 else
2301 if (Z - end < end_unchanged)
2302 end_unchanged = Z - end;
2303 if (start - BEG < beg_unchanged)
2304 beg_unchanged = start - BEG;
2308 /* Increment the buffer's time stamp, but also increment the save
2309 and autosave timestamps, so as not to screw up that timekeeping. */
2310 if (BUF_MODIFF (buf) == BUF_SAVE_MODIFF (buf))
2311 BUF_SAVE_MODIFF (buf)++;
2312 if (BUF_MODIFF (buf) == buf->auto_save_modified)
2313 buf->auto_save_modified++;
2315 BUF_MODIFF (buf) ++;
2319 /* Copy LEN glyphs starting address FROM to the rope TO.
2320 But don't actually copy the parts that would come in before S.
2321 Value is TO, advanced past the copied data.
2322 F is the frame we are displaying in. */
2324 static GLYPH *
2325 copy_part_of_rope (f, to, s, from, len, face)
2326 FRAME_PTR f;
2327 register GLYPH *to; /* Copy to here. */
2328 register GLYPH *s; /* Starting point. */
2329 Lisp_Object *from; /* Data to copy. */
2330 int len;
2331 int face; /* Face to apply to glyphs which don't specify one. */
2333 int n = len;
2334 register Lisp_Object *fp = from;
2335 /* These cache the results of the last call to compute_glyph_face. */
2336 int last_code = -1;
2337 int last_merged = 0;
2339 #ifdef HAVE_FACES
2340 if (! FRAME_TERMCAP_P (f))
2341 while (n--)
2343 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2344 int facecode;
2346 if (FAST_GLYPH_FACE (glyph) == 0)
2347 /* If GLYPH has no face code, use FACE. */
2348 facecode = face;
2349 else if (FAST_GLYPH_FACE (glyph) == last_code)
2350 /* If it's same as previous glyph, use same result. */
2351 facecode = last_merged;
2352 else
2354 /* Merge this glyph's face and remember the result. */
2355 last_code = FAST_GLYPH_FACE (glyph);
2356 last_merged = facecode = compute_glyph_face (f, last_code, face);
2359 if (to >= s)
2360 *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
2361 ++to;
2362 ++fp;
2364 else
2365 #endif
2366 while (n--)
2368 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2369 ++to;
2370 ++fp;
2372 return to;
2375 /* Correct a glyph by replacing its specified user-level face code
2376 with a displayable computed face code. */
2378 static GLYPH
2379 fix_glyph (f, glyph, cface)
2380 FRAME_PTR f;
2381 GLYPH glyph;
2382 int cface;
2384 #ifdef HAVE_FACES
2385 if (! FRAME_TERMCAP_P (f))
2387 if (FAST_GLYPH_FACE (glyph) != 0)
2388 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
2389 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
2391 #endif
2392 return glyph;
2395 /* Display one line of window W, starting at position START in W's buffer.
2397 Display starting at horizontal position HPOS, expressed relative to
2398 W's left edge. In situations where the text at START shouldn't
2399 start at the left margin (i.e. when the window is hscrolled, or
2400 we're continuing a line which left off in the midst of a
2401 multi-column character), HPOS should be negative; we throw away
2402 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2403 account.
2405 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2407 Display on position VPOS on the frame. It is origin 0, relative to
2408 the top of the frame, not W.
2410 Returns a STRUCT POSITION giving character to start next line with
2411 and where to display it, including a zero or negative hpos.
2412 The vpos field is not really a vpos; it is 1 unless the line is continued */
2414 struct position val_display_text_line;
2416 static struct position *
2417 display_text_line (w, start, vpos, hpos, taboffset)
2418 struct window *w;
2419 int start;
2420 int vpos;
2421 int hpos;
2422 int taboffset;
2424 register int pos = start;
2425 register int c;
2426 register GLYPH *p1;
2427 register int pause;
2428 register unsigned char *p;
2429 GLYPH *endp;
2430 register GLYPH *leftmargin;
2431 register GLYPH *p1prev;
2432 register GLYPH *p1start;
2433 int prevpos;
2434 int *charstart;
2435 FRAME_PTR f = XFRAME (w->frame);
2436 int tab_width = XINT (current_buffer->tab_width);
2437 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
2438 int width = window_internal_width (w) - 1;
2439 struct position val;
2440 int lastpos;
2441 int invis;
2442 int last_invis_skip = 0;
2443 Lisp_Object last_invis_prop;
2444 int hscroll = XINT (w->hscroll);
2445 int truncate = (hscroll
2446 || (truncate_partial_width_windows
2447 && XFASTINT (w->width) < FRAME_WIDTH (f))
2448 || !NILP (current_buffer->truncate_lines));
2450 /* 1 if we should highlight the region. */
2451 int highlight_region
2452 = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
2453 int region_beg, region_end;
2455 int selective = (INTEGERP (current_buffer->selective_display)
2456 ? XINT (current_buffer->selective_display)
2457 : !NILP (current_buffer->selective_display) ? -1 : 0);
2458 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
2459 register struct Lisp_Vector *dp = window_display_table (w);
2461 Lisp_Object default_invis_vector[3];
2462 /* Number of characters of ellipsis to display after an invisible line
2463 if it calls for an ellipsis.
2464 Note that this value can be nonzero regardless of whether
2465 selective display is enabled--you must check that separately. */
2466 int selective_rlen
2467 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2468 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
2469 : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
2470 /* This is the sequence of Lisp objects to display
2471 when there are invisible lines. */
2472 Lisp_Object *invis_vector_contents
2473 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2474 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2475 : default_invis_vector);
2477 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
2478 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
2479 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
2480 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
2482 /* The next buffer location at which the face should change, due
2483 to overlays or text property changes. */
2484 int next_face_change;
2486 /* The next location where the `invisible' property changes, or an
2487 overlay starts or ends. */
2488 int next_boundary;
2490 /* The face we're currently using. */
2491 int current_face = 0;
2492 int i;
2494 XSETFASTINT (default_invis_vector[2], '.');
2495 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2497 hpos += XFASTINT (w->left);
2498 get_display_line (f, vpos, XFASTINT (w->left));
2499 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
2501 /* Show where to highlight the region. */
2502 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
2503 /* Maybe highlight only in selected window. */
2504 && (highlight_nonselected_windows
2505 || w == XWINDOW (selected_window)))
2507 region_beg = marker_position (current_buffer->mark);
2508 if (PT < region_beg)
2510 region_end = region_beg;
2511 region_beg = PT;
2513 else
2514 region_end = PT;
2515 w->region_showing = Qt;
2517 else
2518 region_beg = region_end = -1;
2520 if (MINI_WINDOW_P (w)
2521 && start == BEG
2522 && vpos == XFASTINT (w->top))
2524 if (! NILP (minibuf_prompt))
2526 minibuf_prompt_width
2527 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2528 XSTRING (minibuf_prompt)->size, hpos,
2529 /* Display a space if we truncate. */
2530 ' ',
2531 1, -1,
2532 /* Truncate the prompt a little before the
2533 margin, so user input can at least start
2534 on the first line. */
2535 w->width > 10 ? w->width - 4 : -1)
2536 - hpos);
2537 hpos += minibuf_prompt_width;
2538 taboffset -= minibuf_prompt_width;
2540 else
2541 minibuf_prompt_width = 0;
2544 /* If we're hscrolled at all, use compute_motion to skip over any
2545 text off the left edge of the window. compute_motion may know
2546 tricks to do this faster than we can. */
2547 if (hpos < 0)
2549 struct position *left_edge
2550 = compute_motion (pos, vpos, hpos, 0,
2551 ZV, vpos, 0,
2552 width, hscroll, taboffset, w);
2554 /* Retrieve the buffer position and column provided by
2555 compute_motion. We can't assume that the column will be
2556 zero, because you may have multi-column characters crossing
2557 the left margin.
2559 compute_motion may have moved us past the screen position we
2560 requested, if we hit a multi-column character, or the end of
2561 the line. If so, back up. */
2562 if (left_edge->vpos > vpos
2563 || left_edge->hpos > 0)
2565 pos = left_edge->bufpos - 1;
2566 hpos = left_edge->prevhpos;
2568 else
2570 pos = left_edge->bufpos;
2571 hpos = left_edge->hpos;
2575 desired_glyphs->bufp[vpos] = start;
2576 p1 = desired_glyphs->glyphs[vpos] + hpos;
2577 p1start = p1;
2578 charstart = desired_glyphs->charstarts[vpos] + hpos;
2579 /* In case we don't ever write anything into it... */
2580 desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
2581 leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
2582 endp = leftmargin + width;
2584 /* Arrange the overlays nicely for our purposes. Usually, we call
2585 display_text_line on only one line at a time, in which case this
2586 can't really hurt too much, or we call it on lines which appear
2587 one after another in the buffer, in which case all calls to
2588 recenter_overlay_lists but the first will be pretty cheap. */
2589 recenter_overlay_lists (current_buffer, pos);
2591 /* Loop generating characters.
2592 Stop at end of buffer, before newline,
2593 if reach or pass continuation column,
2594 or at face change. */
2595 pause = pos;
2596 next_face_change = pos;
2597 next_boundary = pos;
2598 p1prev = p1;
2599 prevpos = pos;
2600 while (1)
2602 if (pos >= pause)
2604 while (pos == next_boundary)
2606 Lisp_Object position, limit, prop, ww;
2608 /* Display the overlay strings here, unless we're at ZV
2609 and have already displayed the appropriate strings
2610 on an earlier line. */
2611 if (pos < ZV || !zv_strings_seen++)
2613 int ovlen;
2614 char *ovstr;
2615 ovlen = overlay_strings (pos, w, &ovstr);
2616 for (; ovlen; ovlen--, ovstr++)
2618 if (p1 >= leftmargin && p1 < endp)
2619 *p1 = MAKE_GLYPH (f, *ovstr, current_face);
2620 p1++;
2624 /* Did we reach point? Record the cursor location. */
2625 if (pos == PT && cursor_vpos < 0)
2627 cursor_vpos = vpos;
2628 cursor_hpos = p1 - leftmargin;
2631 if (pos >= ZV)
2632 break;
2634 XSETFASTINT (position, pos);
2635 limit = Fnext_overlay_change (position);
2636 #ifdef USE_TEXT_PROPERTIES
2637 /* This is just an estimate to give reasonable
2638 performance; nothing should go wrong if it is too small. */
2639 if (XFASTINT (limit) > pos + 50)
2640 XSETFASTINT (limit, pos + 50);
2641 limit = Fnext_single_property_change (position, Qinvisible,
2642 Fcurrent_buffer (), limit);
2643 #endif
2644 next_boundary = XFASTINT (limit);
2645 /* if the `invisible' property is set, we can skip to
2646 the next property change. */
2647 XSETWINDOW (ww, w);
2648 prop = Fget_char_property (position, Qinvisible, ww);
2649 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2651 if (pos < PT && next_boundary >= PT)
2653 cursor_vpos = vpos;
2654 cursor_hpos = p1 - leftmargin;
2656 pos = next_boundary;
2657 last_invis_skip = pos;
2658 last_invis_prop = prop;
2662 /* Did we reach point? Record the cursor location. */
2663 if (pos == PT && cursor_vpos < 0)
2665 cursor_vpos = vpos;
2666 cursor_hpos = p1 - leftmargin;
2669 /* Did we hit the end of the visible region of the buffer?
2670 Stop here. */
2671 if (pos >= ZV)
2673 /* Update charstarts for the end of this line. */
2674 /* Do nothing if off the left edge or at the right edge. */
2675 if (p1 >= leftmargin && p1 + 1 != endp)
2677 int *p2x = &charstart[(p1 < leftmargin
2678 ? leftmargin : p1)
2679 - p1start];
2680 *p2x++ = pos;
2682 break;
2685 #ifdef HAVE_FACES
2686 /* Did we hit a face change? Figure out what face we should
2687 use now. We also hit this the first time through the
2688 loop, to see what face we should start with. */
2689 if (pos >= next_face_change && FRAME_X_P (f))
2690 current_face = compute_char_face (f, w, pos,
2691 region_beg, region_end,
2692 &next_face_change, pos + 50, 0);
2693 #endif
2695 pause = ZV;
2697 if (pos < next_boundary && next_boundary < pause)
2698 pause = next_boundary;
2699 if (pos < next_face_change && next_face_change < pause)
2700 pause = next_face_change;
2702 /* Wouldn't you hate to read the next line to someone over
2703 the phone? */
2704 if (pos < PT && PT < pause)
2705 pause = PT;
2706 if (pos < GPT && GPT < pause)
2707 pause = GPT;
2709 p = &FETCH_CHAR (pos);
2712 if (p1 >= endp)
2713 break;
2715 p1prev = p1;
2717 c = *p++;
2718 /* Let a display table override all standard display methods. */
2719 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
2721 p1 = copy_part_of_rope (f, p1, leftmargin,
2722 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
2723 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
2724 current_face);
2726 else if (c >= 040 && c < 0177)
2728 if (p1 >= leftmargin)
2729 *p1 = MAKE_GLYPH (f, c, current_face);
2730 p1++;
2732 else if (c == '\n')
2734 invis = 0;
2735 if (last_invis_skip == pos
2736 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
2737 invis = 1;
2738 while (pos + 1 < ZV
2739 && selective > 0
2740 && indented_beyond_p (pos + 1, selective))
2742 invis = 1;
2743 pos = find_next_newline (pos + 1, 1);
2744 if (FETCH_CHAR (pos - 1) == '\n')
2745 pos--;
2747 if (invis && selective_rlen > 0 && p1 >= leftmargin)
2749 p1 += selective_rlen;
2750 if (p1 - leftmargin > width)
2751 p1 = endp;
2752 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2753 (p1 - p1prev), current_face);
2755 #ifdef HAVE_FACES
2756 /* Draw the face of the newline character as extending all the
2757 way to the end of the frame line. */
2758 if (current_face)
2760 if (p1 < leftmargin)
2761 p1 = leftmargin;
2762 while (p1 < endp)
2763 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2765 #endif
2767 /* Update charstarts for the newline that ended this line. */
2768 /* Do nothing here for a char that's entirely off the left edge
2769 or if it starts at the right edge. */
2770 if (p1 >= leftmargin && p1prev != endp)
2772 /* Store the newline's position into charstarts
2773 for the column where the newline starts.
2774 Store -1 for the rest of the glyphs it occupies. */
2775 int *p2x = &charstart[(p1prev < leftmargin
2776 ? leftmargin : p1prev)
2777 - p1start];
2778 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2780 *p2x++ = pos;
2781 while (p2x < p2)
2782 *p2x++ = -1;
2785 break;
2787 else if (c == '\t')
2791 if (p1 >= leftmargin && p1 < endp)
2792 *p1 = MAKE_GLYPH (f, ' ', current_face);
2793 p1++;
2795 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
2796 % tab_width);
2798 else if (c == Ctl ('M') && selective == -1)
2800 pos = find_next_newline (pos, 1);
2801 if (FETCH_CHAR (pos - 1) == '\n')
2802 pos--;
2803 if (selective_rlen > 0)
2805 p1 += selective_rlen;
2806 if (p1 - leftmargin > width)
2807 p1 = endp;
2808 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2809 (p1 - p1prev), current_face);
2811 #ifdef HAVE_FACES
2812 /* Draw the face of the newline character as extending all the
2813 way to the end of the frame line. */
2814 if (current_face)
2816 if (p1 < leftmargin)
2817 p1 = leftmargin;
2818 while (p1 < endp)
2819 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2821 #endif
2823 /* Update charstarts for the ^M that ended this line. */
2824 /* Do nothing here for a char that's entirely off the left edge
2825 or if it starts at the right edge. */
2826 if (p1 >= leftmargin && p1prev != endp)
2828 /* Store the newline's position into charstarts
2829 for the column where the newline starts.
2830 Store -1 for the rest of the glyphs it occupies. */
2831 int *p2x = &charstart[(p1prev < leftmargin
2832 ? leftmargin : p1prev)
2833 - p1start];
2834 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2836 *p2x++ = pos;
2837 while (p2x < p2)
2838 *p2x++ = -1;
2840 break;
2842 else if (c < 0200 && ctl_arrow)
2844 if (p1 >= leftmargin)
2845 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
2846 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
2847 current_face);
2848 p1++;
2849 if (p1 >= leftmargin && p1 < endp)
2850 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
2851 p1++;
2853 else
2855 if (p1 >= leftmargin)
2856 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
2857 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
2858 current_face);
2859 p1++;
2860 if (p1 >= leftmargin && p1 < endp)
2861 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
2862 p1++;
2863 if (p1 >= leftmargin && p1 < endp)
2864 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
2865 p1++;
2866 if (p1 >= leftmargin && p1 < endp)
2867 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
2868 p1++;
2871 prevpos = pos;
2872 pos++;
2874 /* Update charstarts for the character just output. */
2876 /* Do nothing here for a char that's entirely off the left edge. */
2877 if (p1 >= leftmargin)
2879 /* Store the char's position into charstarts
2880 for the first glyph occupied by this char.
2881 Store -1 for the rest of the glyphs it occupies. */
2882 if (p1 != p1prev)
2884 int *p2x = &charstart[(p1prev < leftmargin
2885 ? leftmargin : p1prev)
2886 - p1start];
2887 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2889 if (p2x < p2)
2890 *p2x++ = prevpos;
2891 while (p2x < p2)
2892 *p2x++ = -1;
2897 val.hpos = - XINT (w->hscroll);
2898 if (val.hpos)
2899 val.hpos++;
2901 val.vpos = 1;
2903 lastpos = pos;
2905 /* Store 0 in this charstart line for the positions where
2906 there is no character. But do leave what was recorded
2907 for the character that ended the line. */
2908 /* Add 1 in the endtest to compensate for the fact that ENDP was
2909 made from WIDTH, which is 1 less than the window's actual
2910 internal width. */
2911 i = p1 - p1start + 1;
2912 if (p1 < leftmargin)
2913 i += leftmargin - p1;
2914 for (; i < endp - p1start + 1; i++)
2915 charstart[i] = 0;
2917 /* Handle continuation in middle of a character */
2918 /* by backing up over it */
2919 if (p1 > endp)
2921 /* Don't back up if we never actually displayed any text.
2922 This occurs when the minibuffer prompt takes up the whole line. */
2923 if (p1prev)
2925 /* Start the next line with that same character */
2926 pos--;
2927 /* but at negative hpos, to skip the columns output on this line. */
2928 val.hpos += p1prev - endp;
2931 /* Keep in this line everything up to the continuation column. */
2932 p1 = endp;
2935 /* Finish deciding which character to start the next line on,
2936 and what hpos to start it at.
2937 Also set `lastpos' to the last position which counts as "on this line"
2938 for cursor-positioning. */
2940 if (pos < ZV)
2942 if (FETCH_CHAR (pos) == '\n')
2944 /* If stopped due to a newline, start next line after it */
2945 pos++;
2946 /* Check again for hidden lines, in case the newline occurred exactly
2947 at the right margin. */
2948 while (pos < ZV && selective > 0
2949 && indented_beyond_p (pos, selective))
2950 pos = find_next_newline (pos, 1);
2952 else
2953 /* Stopped due to right margin of window */
2955 if (truncate)
2957 *p1++ = fix_glyph (f, truncator, 0);
2958 /* Truncating => start next line after next newline,
2959 and point is on this line if it is before the newline,
2960 and skip none of first char of next line */
2962 pos = find_next_newline (pos, 1);
2963 while (pos < ZV && selective > 0
2964 && indented_beyond_p (pos, selective));
2965 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
2967 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
2969 else
2971 *p1++ = fix_glyph (f, continuer, 0);
2972 val.vpos = 0;
2973 lastpos--;
2978 /* If point is at eol or in invisible text at eol,
2979 record its frame location now. */
2981 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
2983 cursor_vpos = vpos;
2984 cursor_hpos = p1 - leftmargin;
2987 if (cursor_vpos == vpos)
2989 if (cursor_hpos < 0) cursor_hpos = 0;
2990 if (cursor_hpos > width) cursor_hpos = width;
2991 cursor_hpos += XFASTINT (w->left);
2992 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
2994 if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
2995 && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
2997 FRAME_CURSOR_Y (f) = cursor_vpos;
2998 FRAME_CURSOR_X (f) = cursor_hpos;
3001 if (w == XWINDOW (selected_window))
3003 /* Line is not continued and did not start
3004 in middle of character */
3005 if ((hpos - XFASTINT (w->left)
3006 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
3007 && val.vpos)
3009 this_line_bufpos = start;
3010 this_line_buffer = current_buffer;
3011 this_line_vpos = cursor_vpos;
3012 this_line_start_hpos = hpos;
3013 this_line_endpos = Z - lastpos;
3015 else
3016 this_line_bufpos = 0;
3021 /* If hscroll and line not empty, insert truncation-at-left marker */
3022 if (hscroll && lastpos != start)
3024 *leftmargin = fix_glyph (f, truncator, 0);
3025 if (p1 <= leftmargin)
3026 p1 = leftmargin + 1;
3029 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f))
3031 endp++;
3032 if (p1 < leftmargin) p1 = leftmargin;
3033 while (p1 < endp) *p1++ = SPACEGLYPH;
3035 /* Don't draw vertical bars if we're using scroll bars. They're
3036 covered up by the scroll bars, and it's distracting to see
3037 them when the scroll bar windows are flickering around to be
3038 reconfigured. */
3039 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3041 int i;
3042 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
3043 *p1++ = SPACEGLYPH;
3045 else
3046 *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
3047 ? DISP_BORDER_GLYPH (dp)
3048 : '|');
3050 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
3051 p1 - desired_glyphs->glyphs[vpos]);
3052 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3054 /* If the start of this line is the overlay arrow-position,
3055 then put the arrow string into the display-line. */
3057 if (MARKERP (Voverlay_arrow_position)
3058 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
3059 && start == marker_position (Voverlay_arrow_position)
3060 && STRINGP (Voverlay_arrow_string)
3061 && ! overlay_arrow_seen)
3063 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
3064 int i;
3065 int len = XSTRING (Voverlay_arrow_string)->size;
3066 int arrow_end;
3068 if (len > width)
3069 len = width;
3070 #ifdef HAVE_FACES
3071 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
3073 /* If the arrow string has text props, obey them when displaying. */
3074 for (i = 0; i < len; i++)
3076 int c = p[i];
3077 Lisp_Object face, ilisp;
3078 int newface;
3080 XSETFASTINT (ilisp, i);
3081 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
3082 newface = compute_glyph_face_1 (f, face, 0);
3083 leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
3086 else
3087 #endif /* HAVE_FACES */
3089 for (i = 0; i < len; i++)
3090 leftmargin[i] = p[i];
3093 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
3094 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
3095 if (desired_glyphs->used[vpos] < arrow_end)
3096 desired_glyphs->used[vpos] = arrow_end;
3098 overlay_arrow_seen = 1;
3101 val.bufpos = pos;
3102 val_display_text_line = val;
3103 return &val_display_text_line;
3106 /* Redisplay the menu bar in the frame for window W. */
3108 static void
3109 display_menu_bar (w)
3110 struct window *w;
3112 Lisp_Object items, tail;
3113 register int vpos = 0;
3114 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3115 int maxendcol = FRAME_WIDTH (f);
3116 int hpos = 0;
3117 int i;
3119 #ifndef USE_X_TOOLKIT
3120 if (FRAME_MENU_BAR_LINES (f) <= 0)
3121 return;
3123 get_display_line (f, vpos, 0);
3125 items = FRAME_MENU_BAR_ITEMS (f);
3126 for (i = 0; i < XVECTOR (items)->size; i += 3)
3128 Lisp_Object pos, string;
3129 string = XVECTOR (items)->contents[i + 1];
3130 if (NILP (string))
3131 break;
3133 XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos);
3135 if (hpos < maxendcol)
3136 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
3137 XSTRING (string)->data,
3138 XSTRING (string)->size,
3139 hpos, 0, 0, hpos, maxendcol);
3140 /* Put a space between items. */
3141 if (hpos < maxendcol)
3143 int hpos1 = hpos + 1;
3144 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
3145 min (hpos1, maxendcol), maxendcol);
3149 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3150 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
3152 /* Fill out the line with spaces. */
3153 if (maxendcol > hpos)
3154 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
3156 /* Clear the rest of the lines allocated to the menu bar. */
3157 vpos++;
3158 while (vpos < FRAME_MENU_BAR_LINES (f))
3159 get_display_line (f, vpos++, 0);
3160 #endif /* not USE_X_TOOLKIT */
3163 /* Display the mode line for window w */
3165 static void
3166 display_mode_line (w)
3167 struct window *w;
3169 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
3170 register int left = XFASTINT (w->left);
3171 register int right = XFASTINT (w->width) + left;
3172 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3174 line_number_displayed = 0;
3175 w->column_number_displayed = Qnil;
3177 get_display_line (f, vpos, left);
3179 /* Temporarily make frame F's kboard the current kboard
3180 so that kboard-local variables in the mode_line_format
3181 will get the right values. */
3182 push_frame_kboard (f);
3184 display_mode_element (w, vpos, left, 0, right, right,
3185 current_buffer->mode_line_format);
3187 pop_frame_kboard ();
3189 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3191 /* Make the mode line inverse video if the entire line
3192 is made of mode lines.
3193 I.e. if this window is full width,
3194 or if it is the child of a full width window
3195 (which implies that that window is split side-by-side
3196 and the rest of this line is mode lines of the sibling windows). */
3197 if (XFASTINT (w->width) == FRAME_WIDTH (f)
3198 || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
3199 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
3200 #ifdef HAVE_FACES
3201 else if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
3203 /* For a partial width window, explicitly set face of each glyph. */
3204 int i;
3205 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
3206 for (i = left; i < right; ++i)
3207 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
3209 #endif
3212 /* Contribute ELT to the mode line for window W.
3213 How it translates into text depends on its data type.
3215 VPOS is the position of the mode line being displayed.
3217 HPOS is the position (absolute on frame) where this element's text
3218 should start. The output is truncated automatically at the right
3219 edge of window W.
3221 DEPTH is the depth in recursion. It is used to prevent
3222 infinite recursion here.
3224 MINENDCOL is the hpos before which the element may not end.
3225 The element is padded at the right with spaces if nec
3226 to reach this column.
3228 MAXENDCOL is the hpos past which this element may not extend.
3229 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3230 (This is necessary to make nested padding and truncation work.)
3232 Returns the hpos of the end of the text generated by ELT.
3233 The next element will receive that value as its HPOS arg,
3234 so as to concatenate the elements. */
3236 static int
3237 display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
3238 struct window *w;
3239 register int vpos, hpos;
3240 int depth;
3241 int minendcol;
3242 register int maxendcol;
3243 register Lisp_Object elt;
3245 tail_recurse:
3246 if (depth > 10)
3247 goto invalid;
3249 depth++;
3251 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
3253 case Lisp_String:
3255 /* A string: output it and check for %-constructs within it. */
3256 register unsigned char c;
3257 register unsigned char *this = XSTRING (elt)->data;
3259 while (hpos < maxendcol && *this)
3261 unsigned char *last = this;
3262 while ((c = *this++) != '\0' && c != '%')
3264 if (this - 1 != last)
3266 register int lim = --this - last + hpos;
3267 if (frame_title_ptr)
3268 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
3269 else
3270 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
3271 hpos, min (lim, maxendcol));
3273 else /* c == '%' */
3275 register int minendcol;
3276 register int spec_width = 0;
3278 /* We can't allow -ve args due to the "%-" construct */
3279 /* Argument specifies minwidth but not maxwidth
3280 (maxwidth can be specified by
3281 (<negative-number> . <stuff>) mode-line elements) */
3283 while ((c = *this++) >= '0' && c <= '9')
3285 spec_width = spec_width * 10 + (c - '0');
3288 minendcol = hpos + spec_width;
3289 if (minendcol > maxendcol)
3291 spec_width = maxendcol - hpos;
3292 minendcol = maxendcol;
3295 if (c == 'M')
3296 hpos = display_mode_element (w, vpos, hpos, depth,
3297 spec_width, maxendcol,
3298 Vglobal_mode_string);
3299 else if (c != 0)
3301 char *spec = decode_mode_spec (w, c, spec_width,
3302 maxendcol - hpos);
3303 if (frame_title_ptr)
3304 hpos = store_frame_title (spec, minendcol, maxendcol);
3305 else
3306 hpos = display_string (w, vpos, spec, -1,
3307 hpos, 0, 1,
3308 minendcol, maxendcol);
3313 break;
3315 case Lisp_Symbol:
3316 /* A symbol: process the value of the symbol recursively
3317 as if it appeared here directly. Avoid error if symbol void.
3318 Special case: if value of symbol is a string, output the string
3319 literally. */
3321 register Lisp_Object tem;
3322 tem = Fboundp (elt);
3323 if (!NILP (tem))
3325 tem = Fsymbol_value (elt);
3326 /* If value is a string, output that string literally:
3327 don't check for % within it. */
3328 if (STRINGP (tem))
3330 if (frame_title_ptr)
3331 hpos = store_frame_title (XSTRING (tem)->data,
3332 minendcol, maxendcol);
3333 else
3334 hpos = display_string (w, vpos, XSTRING (tem)->data,
3335 XSTRING (tem)->size,
3336 hpos, 0, 1, minendcol, maxendcol);
3338 /* Give up right away for nil or t. */
3339 else if (!EQ (tem, elt))
3340 { elt = tem; goto tail_recurse; }
3343 break;
3345 case Lisp_Cons:
3347 register Lisp_Object car, tem;
3349 /* A cons cell: three distinct cases.
3350 If first element is a string or a cons, process all the elements
3351 and effectively concatenate them.
3352 If first element is a negative number, truncate displaying cdr to
3353 at most that many characters. If positive, pad (with spaces)
3354 to at least that many characters.
3355 If first element is a symbol, process the cadr or caddr recursively
3356 according to whether the symbol's value is non-nil or nil. */
3357 car = XCONS (elt)->car;
3358 if (SYMBOLP (car))
3360 tem = Fboundp (car);
3361 elt = XCONS (elt)->cdr;
3362 if (!CONSP (elt))
3363 goto invalid;
3364 /* elt is now the cdr, and we know it is a cons cell.
3365 Use its car if CAR has a non-nil value. */
3366 if (!NILP (tem))
3368 tem = Fsymbol_value (car);
3369 if (!NILP (tem))
3370 { elt = XCONS (elt)->car; goto tail_recurse; }
3372 /* Symbol's value is nil (or symbol is unbound)
3373 Get the cddr of the original list
3374 and if possible find the caddr and use that. */
3375 elt = XCONS (elt)->cdr;
3376 if (NILP (elt))
3377 break;
3378 else if (!CONSP (elt))
3379 goto invalid;
3380 elt = XCONS (elt)->car;
3381 goto tail_recurse;
3383 else if (INTEGERP (car))
3385 register int lim = XINT (car);
3386 elt = XCONS (elt)->cdr;
3387 if (lim < 0)
3388 /* Negative int means reduce maximum width.
3389 DO NOT change MINENDCOL here!
3390 (20 -10 . foo) should truncate foo to 10 col
3391 and then pad to 20. */
3392 maxendcol = min (maxendcol, hpos - lim);
3393 else if (lim > 0)
3395 /* Padding specified. Don't let it be more than
3396 current maximum. */
3397 lim += hpos;
3398 if (lim > maxendcol)
3399 lim = maxendcol;
3400 /* If that's more padding than already wanted, queue it.
3401 But don't reduce padding already specified even if
3402 that is beyond the current truncation point. */
3403 if (lim > minendcol)
3404 minendcol = lim;
3406 goto tail_recurse;
3408 else if (STRINGP (car) || CONSP (car))
3410 register int limit = 50;
3411 /* LIMIT is to protect against circular lists. */
3412 while (CONSP (elt) && --limit > 0
3413 && hpos < maxendcol)
3415 hpos = display_mode_element (w, vpos, hpos, depth,
3416 hpos, maxendcol,
3417 XCONS (elt)->car);
3418 elt = XCONS (elt)->cdr;
3422 break;
3424 default:
3425 invalid:
3426 if (frame_title_ptr)
3427 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
3428 else
3429 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
3430 minendcol, maxendcol);
3431 return hpos;
3434 if (minendcol > hpos)
3435 if (frame_title_ptr)
3436 hpos = store_frame_title ("", minendcol, maxendcol);
3437 else
3438 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
3439 return hpos;
3442 /* Write a null-terminated, right justified decimal representation of
3443 the positive integer D to BUF using a minimal field width WIDTH. */
3445 static void
3446 pint2str (buf, width, d)
3447 register char *buf;
3448 register int width;
3449 register int d;
3451 register char *p = buf;
3453 if (d <= 0)
3454 *p++ = '0';
3455 else
3456 while (d > 0)
3458 *p++ = d % 10 + '0';
3459 d /= 10;
3461 for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
3462 *p-- = '\0';
3463 while (p > buf)
3465 d = *buf;
3466 *buf++ = *p;
3467 *p-- = d;
3471 /* Return a string for the output of a mode line %-spec for window W,
3472 generated by character C. SPEC_WIDTH is the field width when
3473 padding to the left (%c, %l). The value returned from this
3474 function will later be truncated to width MAXWIDTH. */
3476 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3478 static char *
3479 decode_mode_spec (w, c, spec_width, maxwidth)
3480 struct window *w;
3481 register char c;
3482 register int spec_width;
3483 register int maxwidth;
3485 Lisp_Object obj;
3486 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3487 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
3488 struct buffer *b = XBUFFER (w->buffer);
3490 obj = Qnil;
3491 if (maxwidth > FRAME_WIDTH (f))
3492 maxwidth = FRAME_WIDTH (f);
3494 switch (c)
3496 case '*':
3497 if (!NILP (b->read_only))
3498 return "%";
3499 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3500 return "*";
3501 return "-";
3503 case '+':
3504 /* This differs from %* only for a modified read-only buffer. */
3505 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3506 return "*";
3507 if (!NILP (b->read_only))
3508 return "%";
3509 return "-";
3511 case '&':
3512 /* This differs from %* in ignoring read-only-ness. */
3513 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3514 return "*";
3515 return "-";
3517 case '%':
3518 return "%";
3520 case '[':
3522 int i;
3523 char *p;
3525 if (command_loop_level > 5)
3526 return "[[[... ";
3527 p = decode_mode_spec_buf;
3528 for (i = 0; i < command_loop_level; i++)
3529 *p++ = '[';
3530 *p = 0;
3531 return decode_mode_spec_buf;
3534 case ']':
3536 int i;
3537 char *p;
3539 if (command_loop_level > 5)
3540 return " ...]]]";
3541 p = decode_mode_spec_buf;
3542 for (i = 0; i < command_loop_level; i++)
3543 *p++ = ']';
3544 *p = 0;
3545 return decode_mode_spec_buf;
3548 case '-':
3550 register char *p;
3551 register int i;
3553 if (maxwidth < sizeof (lots_of_dashes))
3554 return lots_of_dashes;
3555 else
3557 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
3558 *p++ = '-';
3559 *p = '\0';
3561 return decode_mode_spec_buf;
3564 case 'b':
3565 obj = b->name;
3566 #if 0
3567 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
3569 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
3570 decode_mode_spec_buf[maxwidth - 1] = '\\';
3571 decode_mode_spec_buf[maxwidth] = '\0';
3572 return decode_mode_spec_buf;
3574 #endif
3575 break;
3577 case 'c':
3579 int col = current_column ();
3580 XSETFASTINT (w->column_number_displayed, col);
3581 pint2str (decode_mode_spec_buf, spec_width, col);
3582 return decode_mode_spec_buf;
3585 case 'F':
3586 /* %F displays the frame name. */
3587 #ifdef MULTI_FRAME
3588 return (char *) XSTRING (selected_frame->name)->data;
3589 #else
3590 return "Emacs";
3591 #endif
3593 case 'f':
3594 obj = b->filename;
3595 #if 0
3596 if (NILP (obj))
3597 return "[none]";
3598 else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
3600 bcopy ("...", decode_mode_spec_buf, 3);
3601 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
3602 decode_mode_spec_buf + 3, maxwidth - 3);
3603 return decode_mode_spec_buf;
3605 #endif
3606 break;
3608 case 'l':
3610 int startpos = marker_position (w->start);
3611 int line, linepos, topline;
3612 int nlines, junk;
3613 Lisp_Object tem;
3614 int height = XFASTINT (w->height);
3616 /* If we decided that this buffer isn't suitable for line numbers,
3617 don't forget that too fast. */
3618 if (EQ (w->base_line_pos, w->buffer))
3619 goto no_value;
3621 /* If the buffer is very big, don't waste time. */
3622 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
3624 w->base_line_pos = Qnil;
3625 w->base_line_number = Qnil;
3626 goto no_value;
3629 if (!NILP (w->base_line_number)
3630 && !NILP (w->base_line_pos)
3631 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
3633 line = XFASTINT (w->base_line_number);
3634 linepos = XFASTINT (w->base_line_pos);
3636 else
3638 line = 1;
3639 linepos = BUF_BEGV (b);
3642 /* Count lines from base line to window start position. */
3643 nlines = display_count_lines (linepos, startpos, startpos, &junk);
3645 topline = nlines + line;
3647 /* Determine a new base line, if the old one is too close
3648 or too far away, or if we did not have one.
3649 "Too close" means it's plausible a scroll-down would
3650 go back past it. */
3651 if (startpos == BUF_BEGV (b))
3653 XSETFASTINT (w->base_line_number, topline);
3654 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
3656 else if (nlines < height + 25 || nlines > height * 3 + 50
3657 || linepos == BUF_BEGV (b))
3659 int limit = BUF_BEGV (b);
3660 int position;
3661 int distance = (height * 2 + 30) * 200;
3663 if (startpos - distance > limit)
3664 limit = startpos - distance;
3666 nlines = display_count_lines (startpos, limit,
3667 -(height * 2 + 30),
3668 &position);
3669 /* If we couldn't find the lines we wanted within
3670 200 chars per line,
3671 give up on line numbers for this window. */
3672 if (position == startpos - distance)
3674 w->base_line_pos = w->buffer;
3675 w->base_line_number = Qnil;
3676 goto no_value;
3679 XSETFASTINT (w->base_line_number, topline - nlines);
3680 XSETFASTINT (w->base_line_pos, position);
3683 /* Now count lines from the start pos to point. */
3684 nlines = display_count_lines (startpos, PT, PT, &junk);
3686 /* Record that we did display the line number. */
3687 line_number_displayed = 1;
3689 /* Make the string to show. */
3690 pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
3691 return decode_mode_spec_buf;
3692 no_value:
3694 char* p = decode_mode_spec_buf;
3695 for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
3696 strcpy (p, "??");
3697 return decode_mode_spec_buf;
3700 break;
3702 case 'm':
3703 obj = b->mode_name;
3704 break;
3706 case 'n':
3707 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
3708 return " Narrow";
3709 break;
3711 case 'p':
3713 int pos = marker_position (w->start);
3714 int total = BUF_ZV (b) - BUF_BEGV (b);
3716 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
3718 if (pos <= BUF_BEGV (b))
3719 return "All";
3720 else
3721 return "Bottom";
3723 else if (pos <= BUF_BEGV (b))
3724 return "Top";
3725 else
3727 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
3728 /* We can't normally display a 3-digit number,
3729 so get us a 2-digit number that is close. */
3730 if (total == 100)
3731 total = 99;
3732 sprintf (decode_mode_spec_buf, "%2d%%", total);
3733 return decode_mode_spec_buf;
3737 /* Display percentage of size above the bottom of the screen. */
3738 case 'P':
3740 int toppos = marker_position (w->start);
3741 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
3742 int total = BUF_ZV (b) - BUF_BEGV (b);
3744 if (botpos >= BUF_ZV (b))
3746 if (toppos <= BUF_BEGV (b))
3747 return "All";
3748 else
3749 return "Bottom";
3751 else
3753 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
3754 /* We can't normally display a 3-digit number,
3755 so get us a 2-digit number that is close. */
3756 if (total == 100)
3757 total = 99;
3758 if (toppos <= BUF_BEGV (b))
3759 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
3760 else
3761 sprintf (decode_mode_spec_buf, "%2d%%", total);
3762 return decode_mode_spec_buf;
3766 case 's':
3767 /* status of process */
3768 obj = Fget_buffer_process (w->buffer);
3769 if (NILP (obj))
3770 return "no process";
3771 #ifdef subprocesses
3772 obj = Fsymbol_name (Fprocess_status (obj));
3773 #endif
3774 break;
3776 case 't': /* indicate TEXT or BINARY */
3777 #ifdef MODE_LINE_BINARY_TEXT
3778 return MODE_LINE_BINARY_TEXT (b);
3779 #else
3780 return "T";
3781 #endif
3784 if (STRINGP (obj))
3785 return (char *) XSTRING (obj)->data;
3786 else
3787 return "";
3790 /* Search for COUNT instances of a line boundary, which means either a
3791 newline or (if selective display enabled) a carriage return.
3792 Start at START. If COUNT is negative, search backwards.
3794 If we find COUNT instances, set *SHORTAGE to zero, and return the
3795 position after the COUNTth match. Note that for reverse motion
3796 this is not the same as the usual convention for Emacs motion commands.
3798 If we don't find COUNT instances before reaching the end of the
3799 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3800 the number of line boundaries left unfound, and return the end of the
3801 buffer we bumped up against. */
3803 static int
3804 display_scan_buffer (start, count, shortage)
3805 int *shortage, start;
3806 register int count;
3808 int limit = ((count > 0) ? ZV - 1 : BEGV);
3809 int direction = ((count > 0) ? 1 : -1);
3811 register unsigned char *cursor;
3812 unsigned char *base;
3814 register int ceiling;
3815 register unsigned char *ceiling_addr;
3817 /* If we are not in selective display mode,
3818 check only for newlines. */
3819 if (! (!NILP (current_buffer->selective_display)
3820 && !INTEGERP (current_buffer->selective_display)))
3821 return scan_buffer ('\n', start, 0, count, shortage, 0);
3823 /* The code that follows is like scan_buffer
3824 but checks for either newline or carriage return. */
3826 if (shortage != 0)
3827 *shortage = 0;
3829 if (count > 0)
3830 while (start != limit + 1)
3832 ceiling = BUFFER_CEILING_OF (start);
3833 ceiling = min (limit, ceiling);
3834 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
3835 base = (cursor = &FETCH_CHAR (start));
3836 while (1)
3838 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
3840 if (cursor != ceiling_addr)
3842 if (--count == 0)
3844 immediate_quit = 0;
3845 return (start + cursor - base + 1);
3847 else
3848 if (++cursor == ceiling_addr)
3849 break;
3851 else
3852 break;
3854 start += cursor - base;
3856 else
3858 start--; /* first character we scan */
3859 while (start > limit - 1)
3860 { /* we WILL scan under start */
3861 ceiling = BUFFER_FLOOR_OF (start);
3862 ceiling = max (limit, ceiling);
3863 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
3864 base = (cursor = &FETCH_CHAR (start));
3865 cursor++;
3866 while (1)
3868 while (--cursor != ceiling_addr
3869 && *cursor != '\n' && *cursor != 015)
3871 if (cursor != ceiling_addr)
3873 if (++count == 0)
3875 immediate_quit = 0;
3876 return (start + cursor - base + 1);
3879 else
3880 break;
3882 start += cursor - base;
3886 if (shortage != 0)
3887 *shortage = count * direction;
3888 return (start + ((direction == 1 ? 0 : 1)));
3891 /* Count up to N lines starting from FROM.
3892 But don't go beyond LIMIT.
3893 Return the number of lines thus found (always positive).
3894 Store the position after what was found into *POS_PTR. */
3896 static int
3897 display_count_lines (from, limit, n, pos_ptr)
3898 int from, limit, n;
3899 int *pos_ptr;
3901 int oldbegv = BEGV;
3902 int oldzv = ZV;
3903 int shortage = 0;
3905 if (limit < from)
3906 BEGV = limit;
3907 else
3908 ZV = limit;
3910 *pos_ptr = display_scan_buffer (from, n, &shortage);
3912 ZV = oldzv;
3913 BEGV = oldbegv;
3915 if (n < 0)
3916 /* When scanning backwards, scan_buffer stops *after* the last newline
3917 it finds, but does count it. Compensate for that. */
3918 return - n - shortage - (*pos_ptr != limit);
3919 return n - shortage;
3922 /* Display STRING on one line of window W, starting at HPOS.
3923 Display at position VPOS. Caller should have done get_display_line.
3924 If VPOS == -1, display it as the current frame's title.
3925 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3927 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3929 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3930 MAXCOL is the last column ok to end at. Truncate here.
3931 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3932 Both count from the left edge of the frame, as does HPOS.
3933 The right edge of W is an implicit maximum.
3934 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3936 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3937 at the place where the current window ends in this line
3938 and not display anything beyond there. Otherwise, only MAXCOL
3939 controls where to stop output.
3941 Returns ending hpos. */
3943 static int
3944 display_string (w, vpos, string, length, hpos, truncate,
3945 obey_window_width, mincol, maxcol)
3946 struct window *w;
3947 unsigned char *string;
3948 int length;
3949 int vpos, hpos;
3950 GLYPH truncate;
3951 int obey_window_width;
3952 int mincol, maxcol;
3954 register int c;
3955 register GLYPH *p1;
3956 int hscroll = XINT (w->hscroll);
3957 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
3958 register GLYPH *start;
3959 register GLYPH *end;
3960 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3961 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
3962 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
3963 int window_width = XFASTINT (w->width);
3965 /* Use the standard display table, not the window's display table.
3966 We don't want the mode line in rot13. */
3967 register struct Lisp_Vector *dp = 0;
3968 int i;
3970 if (VECTORP (Vstandard_display_table)
3971 && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
3972 dp = XVECTOR (Vstandard_display_table);
3974 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
3976 p1 = p1start;
3977 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
3979 if (obey_window_width)
3981 end = start + window_width - (truncate != 0);
3983 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f))
3985 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3987 int i;
3989 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
3990 *end-- = ' ';
3992 else
3993 *end-- = '|';
3997 if (! obey_window_width
3998 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
3999 end = desired_glyphs->glyphs[vpos] + maxcol;
4001 /* Store 0 in charstart for these columns. */
4002 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
4003 desired_glyphs->charstarts[vpos][i] = 0;
4005 if (maxcol >= 0 && mincol > maxcol)
4006 mincol = maxcol;
4008 while (p1 < end)
4010 if (length == 0)
4011 break;
4012 c = *string++;
4013 /* Specified length. */
4014 if (length >= 0)
4015 length--;
4016 /* Unspecified length (null-terminated string). */
4017 else if (c == 0)
4018 break;
4020 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
4022 p1 = copy_part_of_rope (f, p1, start,
4023 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
4024 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
4027 else if (c >= 040 && c < 0177)
4029 if (p1 >= start)
4030 *p1 = c;
4031 p1++;
4033 else if (c == '\t')
4037 if (p1 >= start && p1 < end)
4038 *p1 = SPACEGLYPH;
4039 p1++;
4041 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
4043 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
4045 if (p1 >= start)
4046 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
4047 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
4049 p1++;
4050 if (p1 >= start && p1 < end)
4051 *p1 = c ^ 0100;
4052 p1++;
4054 else
4056 if (p1 >= start)
4057 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
4058 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
4060 p1++;
4061 if (p1 >= start && p1 < end)
4062 *p1 = (c >> 6) + '0';
4063 p1++;
4064 if (p1 >= start && p1 < end)
4065 *p1 = (7 & (c >> 3)) + '0';
4066 p1++;
4067 if (p1 >= start && p1 < end)
4068 *p1 = (7 & c) + '0';
4069 p1++;
4073 if (c && length > 0)
4075 p1 = end;
4076 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
4078 else if (mincol >= 0)
4080 end = desired_glyphs->glyphs[vpos] + mincol;
4081 while (p1 < end)
4082 *p1++ = SPACEGLYPH;
4086 register int len = p1 - desired_glyphs->glyphs[vpos];
4088 if (len > desired_glyphs->used[vpos])
4089 desired_glyphs->used[vpos] = len;
4090 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
4092 return len;
4096 /* This is like a combination of memq and assq.
4097 Return 1 if PROPVAL appears as an element of LIST
4098 or as the car of an element of LIST.
4099 If PROPVAL is a list, compare each element against LIST
4100 in that way, and return 1 if any element of PROPVAL is found in LIST.
4101 Otherwise return 0.
4102 This function cannot quit. */
4105 invisible_p (propval, list)
4106 register Lisp_Object propval;
4107 Lisp_Object list;
4109 register Lisp_Object tail, proptail;
4110 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4112 register Lisp_Object tem;
4113 tem = XCONS (tail)->car;
4114 if (EQ (propval, tem))
4115 return 1;
4116 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4117 return 1;
4119 if (CONSP (propval))
4120 for (proptail = propval; CONSP (proptail);
4121 proptail = XCONS (proptail)->cdr)
4123 Lisp_Object propelt;
4124 propelt = XCONS (proptail)->car;
4125 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4127 register Lisp_Object tem;
4128 tem = XCONS (tail)->car;
4129 if (EQ (propelt, tem))
4130 return 1;
4131 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4132 return 1;
4135 return 0;
4138 /* Return 1 if PROPVAL appears as the car of an element of LIST
4139 and the cdr of that element is non-nil.
4140 If PROPVAL is a list, check each element of PROPVAL in that way,
4141 and the first time some element is found,
4142 return 1 if the cdr of that element is non-nil.
4143 Otherwise return 0.
4144 This function cannot quit. */
4147 invisible_ellipsis_p (propval, list)
4148 register Lisp_Object propval;
4149 Lisp_Object list;
4151 register Lisp_Object tail, proptail;
4152 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4154 register Lisp_Object tem;
4155 tem = XCONS (tail)->car;
4156 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4157 return ! NILP (XCONS (tem)->cdr);
4159 if (CONSP (propval))
4160 for (proptail = propval; CONSP (proptail);
4161 proptail = XCONS (proptail)->cdr)
4163 Lisp_Object propelt;
4164 propelt = XCONS (proptail)->car;
4165 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4167 register Lisp_Object tem;
4168 tem = XCONS (tail)->car;
4169 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4170 return ! NILP (XCONS (tem)->cdr);
4173 return 0;
4176 void
4177 syms_of_xdisp ()
4179 staticpro (&Qmenu_bar_update_hook);
4180 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
4182 staticpro (&Qoverriding_terminal_local_map);
4183 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
4185 staticpro (&Qoverriding_local_map);
4186 Qoverriding_local_map = intern ("overriding-local-map");
4188 staticpro (&last_arrow_position);
4189 staticpro (&last_arrow_string);
4190 last_arrow_position = Qnil;
4191 last_arrow_string = Qnil;
4193 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
4194 "String (or mode line construct) included (normally) in `mode-line-format'.");
4195 Vglobal_mode_string = Qnil;
4197 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
4198 "Marker for where to display an arrow on top of the buffer text.\n\
4199 This must be the beginning of a line in order to work.\n\
4200 See also `overlay-arrow-string'.");
4201 Voverlay_arrow_position = Qnil;
4203 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
4204 "String to display as an arrow. See also `overlay-arrow-position'.");
4205 Voverlay_arrow_string = Qnil;
4207 DEFVAR_INT ("scroll-step", &scroll_step,
4208 "*The number of lines to try scrolling a window by when point moves out.\n\
4209 If that fails to bring point back on frame, point is centered instead.\n\
4210 If this is zero, point is always centered after it moves off frame.");
4212 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
4214 DEFVAR_BOOL ("truncate-partial-width-windows",
4215 &truncate_partial_width_windows,
4216 "*Non-nil means truncate lines in all windows less than full frame wide.");
4217 truncate_partial_width_windows = 1;
4219 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
4220 "*Non-nil means use inverse video for the mode line.");
4221 mode_line_inverse_video = 1;
4223 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
4224 "*Maximum buffer size for which line number should be displayed.");
4225 line_number_display_limit = 1000000;
4227 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
4228 "*Non-nil means highlight region even in nonselected windows.");
4229 highlight_nonselected_windows = 1;
4231 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
4232 "Non-nil if more than one frame is visible on this display.\n\
4233 Minibuffer-only frames don't count, but iconified frames do.\n\
4234 This variable is not guaranteed to be accurate except while processing\n\
4235 `frame-title-format' and `icon-title-format'.");
4237 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
4238 "Template for displaying the titlebar of visible frames.\n\
4239 \(Assuming the window manager supports this feature.)\n\
4240 This variable has the same structure as `mode-line-format' (which see),\n\
4241 and is used only on frames for which no explicit name has been set\n\
4242 \(see `modify-frame-parameters').");
4243 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
4244 "Template for displaying the titlebar of an iconified frame.\n\
4245 \(Assuming the window manager supports this feature.)\n\
4246 This variable has the same structure as `mode-line-format' (which see),\n\
4247 and is used only on frames for which no explicit name has been set\n\
4248 \(see `modify-frame-parameters').");
4249 Vicon_title_format
4250 = Vframe_title_format
4251 = Fcons (intern ("multiple-frames"),
4252 Fcons (build_string ("%b"),
4253 Fcons (Fcons (build_string (""),
4254 Fcons (intern ("invocation-name"),
4255 Fcons (build_string ("@"),
4256 Fcons (intern ("system-name"),
4257 Qnil)))),
4258 Qnil)));
4260 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
4261 "Maximum number of lines to keep in the message log buffer.\n\
4262 If nil, disable message logging. If t, log messages but don't truncate\n\
4263 the buffer when it becomes large.");
4264 XSETFASTINT (Vmessage_log_max, 50);
4266 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
4267 "Functions called before redisplay, if window sizes have changed.\n\
4268 The value should be a list of functions that take one argument.\n\
4269 Just before redisplay, for each frame, if any of its windows have changed\n\
4270 size since the last redisplay, or have been split or deleted,\n\
4271 all the functions in the list are called, with the frame as argument.");
4272 Vwindow_size_change_functions = Qnil;
4275 /* initialize the window system */
4276 init_xdisp ()
4278 Lisp_Object root_window;
4279 #ifndef COMPILER_REGISTER_BUG
4280 register
4281 #endif /* COMPILER_REGISTER_BUG */
4282 struct window *mini_w;
4284 this_line_bufpos = 0;
4286 mini_w = XWINDOW (minibuf_window);
4287 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
4289 echo_area_glyphs = 0;
4290 previous_echo_glyphs = 0;
4292 if (!noninteractive)
4294 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
4295 XSETFASTINT (XWINDOW (root_window)->top, 0);
4296 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
4297 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
4298 set_window_height (minibuf_window, 1, 0);
4300 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
4301 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));