Fix previous change.
[emacs.git] / src / xdisp.c
blob37f1300b2662ae1daf070d33cccd39f2244671d8
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"
38 #ifdef USE_X_TOOLKIT
39 extern void set_frame_menubar ();
40 #endif
42 extern int interrupt_input;
43 extern int command_loop_level;
45 extern Lisp_Object Qface;
47 /* Nonzero means print newline to stdout before next minibuffer message. */
49 int noninteractive_need_newline;
51 /* Nonzero means print newline to message log before next message. */
53 static int message_log_need_newline;
55 #define min(a, b) ((a) < (b) ? (a) : (b))
56 #define max(a, b) ((a) > (b) ? (a) : (b))
58 /* The buffer position of the first character appearing
59 entirely or partially on the current frame line.
60 Or zero, which disables the optimization for the current frame line. */
61 static int this_line_bufpos;
63 /* Number of characters past the end of this line,
64 including the terminating newline */
65 static int this_line_endpos;
67 /* The vertical position of this frame line. */
68 static int this_line_vpos;
70 /* Hpos value for start of display on this frame line.
71 Usually zero, but negative if first character really began
72 on previous line */
73 static int this_line_start_hpos;
75 /* Buffer that this_line variables are describing. */
76 static struct buffer *this_line_buffer;
78 /* Set by try_window_id to the vpos of first of any lines
79 scrolled on to the bottom of the frame. These lines should
80 not be included in any general scroll computation. */
81 static int scroll_bottom_vpos;
83 /* Value of echo_area_glyphs when it was last acted on.
84 If this is nonzero, there is a message on the frame
85 in the minibuffer and it should be erased as soon
86 as it is no longer requested to appear. */
87 char *previous_echo_glyphs;
89 /* Nonzero means truncate lines in all windows less wide than the frame */
90 int truncate_partial_width_windows;
92 /* Nonzero means we have more than one non-minibuffer-only frame.
93 Not guaranteed to be accurate except while parsing frame-title-format. */
94 int multiple_frames;
96 Lisp_Object Vglobal_mode_string;
98 /* Marker for where to display an arrow on top of the buffer text. */
99 Lisp_Object Voverlay_arrow_position;
101 /* String to display for the arrow. */
102 Lisp_Object Voverlay_arrow_string;
104 /* Like mode-line-format, but for the titlebar on a visible frame. */
105 Lisp_Object Vframe_title_format;
107 /* Like mode-line-format, but for the titlebar on an iconified frame. */
108 Lisp_Object Vicon_title_format;
110 /* Values of those variables at last redisplay. */
111 static Lisp_Object last_arrow_position, last_arrow_string;
113 Lisp_Object Qmenu_bar_update_hook;
115 /* Nonzero if overlay arrow has been displayed once in this window. */
116 static int overlay_arrow_seen;
118 /* Nonzero means highlight the region even in nonselected windows. */
119 static int highlight_nonselected_windows;
121 /* If cursor motion alone moves point off frame,
122 Try scrolling this many lines up or down if that will bring it back. */
123 int scroll_step;
125 /* Nonzero if try_window_id has made blank lines at window bottom
126 since the last redisplay that paused */
127 static int blank_end_of_window;
129 /* Number of windows showing the buffer of the selected window
130 (or another buffer with the same base buffer).
131 keyboard.c refers to this. */
132 int buffer_shared;
134 /* display_text_line sets these to the frame position (origin 0) of point,
135 whether the window is selected or not.
136 Set one to -1 first to determine whether point was found afterwards. */
138 static int cursor_vpos;
139 static int cursor_hpos;
141 int debug_end_pos;
143 /* Nonzero means display mode line highlighted */
144 int mode_line_inverse_video;
146 static void echo_area_display ();
147 void mark_window_display_accurate ();
148 static void redisplay_windows ();
149 static void redisplay_window ();
150 static void update_menu_bars ();
151 static void update_menu_bar ();
152 static void try_window ();
153 static int try_window_id ();
154 static struct position *display_text_line ();
155 static void display_mode_line ();
156 static int display_mode_element ();
157 static char *fmodetrunc ();
158 static char *decode_mode_spec ();
159 static int display_string ();
160 static void display_menu_bar ();
161 static int display_count_lines ();
163 /* Prompt to display in front of the minibuffer contents */
164 Lisp_Object minibuf_prompt;
166 /* Width in columns of current minibuffer prompt. */
167 int minibuf_prompt_width;
169 /* Message to display instead of minibuffer contents
170 This is what the functions error and message make,
171 and command echoing uses it as well.
172 It overrides the minibuf_prompt as well as the buffer. */
173 char *echo_area_glyphs;
175 /* This is the length of the message in echo_area_glyphs. */
176 int echo_area_glyphs_length;
178 /* true iff we should redraw the mode lines on the next redisplay */
179 int update_mode_lines;
181 /* Smallest number of characters before the gap
182 at any time since last redisplay that finished.
183 Valid for current buffer when try_window_id can be called. */
184 int beg_unchanged;
186 /* Smallest number of characters after the gap
187 at any time since last redisplay that finished.
188 Valid for current buffer when try_window_id can be called. */
189 int end_unchanged;
191 /* MODIFF as of last redisplay that finished;
192 if it matches MODIFF, beg_unchanged and end_unchanged
193 contain no useful information */
194 int unchanged_modified;
196 /* Nonzero if head_clip or tail_clip of current buffer has changed
197 since last redisplay that finished */
198 int clip_changed;
200 /* Nonzero if window sizes or contents have changed
201 since last redisplay that finished */
202 int windows_or_buffers_changed;
204 /* Nonzero after display_mode_line if %l was used
205 and it displayed a line number. */
206 int line_number_displayed;
208 /* Maximum buffer size for which to display line numbers. */
209 int line_number_display_limit;
211 /* Number of lines to keep in the message log buffer.
212 t means infinite. nil means don't log at all. */
213 Lisp_Object Vmessage_log_max;
215 void
216 message_log_maybe_newline ()
218 if (message_log_need_newline)
219 message_dolog ("", 0, 1);
223 /* Add a string to the message log, optionally terminated with a newline.
224 This function calls low-level routines in order to bypass text property
225 hooks, etc. which might not be safe to run. */
227 void
228 message_dolog (m, len, nlflag)
229 char *m;
230 int len, nlflag;
232 if (!NILP (Vmessage_log_max))
234 struct buffer *oldbuf;
235 int oldpoint, oldbegv, oldzv;
237 oldbuf = current_buffer;
238 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
239 oldpoint = PT;
240 oldbegv = BEGV;
241 oldzv = ZV;
242 BEGV = BEG;
243 ZV = Z;
244 if (oldpoint == Z)
245 oldpoint += len + nlflag;
246 if (oldzv == Z)
247 oldzv += len + nlflag;
248 TEMP_SET_PT (Z);
249 if (len)
250 insert_1 (m, len, 1, 0);
251 if (nlflag)
252 insert_1 ("\n", 1, 1, 0);
253 if (NATNUMP (Vmessage_log_max))
255 int pos = scan_buffer ('\n', PT, 0,
256 -XFASTINT (Vmessage_log_max) - 1, 0, 1);
257 oldpoint -= min (pos, oldpoint) - BEG;
258 oldbegv -= min (pos, oldbegv) - BEG;
259 oldzv -= min (pos, oldzv) - BEG;
260 del_range_1 (BEG, pos, 0);
262 BEGV = oldbegv;
263 ZV = oldzv;
264 TEMP_SET_PT (oldpoint);
265 set_buffer_internal (oldbuf);
266 message_log_need_newline = !nlflag;
271 /* Display an echo area message M with a specified length of LEN chars.
272 The string may include null characters. If m is 0, clear out any
273 existing message, and let the minibuffer text show through.
274 Do not pass text that is stored in a Lisp string. */
276 void
277 message2 (m, len)
278 char *m;
279 int len;
281 /* First flush out any partial line written with print. */
282 message_log_maybe_newline ();
283 if (m)
284 message_dolog (m, len, 1);
285 message2_nolog (m, len);
289 /* The non-logging part of that function. */
291 void
292 message2_nolog (m, len)
293 char *m;
294 int len;
296 if (noninteractive)
298 if (noninteractive_need_newline)
299 putc ('\n', stderr);
300 noninteractive_need_newline = 0;
301 fwrite (m, len, 1, stderr);
302 if (cursor_in_echo_area == 0)
303 fprintf (stderr, "\n");
304 fflush (stderr);
306 /* A null message buffer means that the frame hasn't really been
307 initialized yet. Error messages get reported properly by
308 cmd_error, so this must be just an informative message; toss it. */
309 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
311 #ifdef MULTI_FRAME
312 Lisp_Object minibuf_frame;
314 choose_minibuf_frame ();
315 minibuf_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
316 FRAME_SAMPLE_VISIBILITY (XFRAME (minibuf_frame));
317 if (FRAME_VISIBLE_P (selected_frame)
318 && ! FRAME_VISIBLE_P (XFRAME (minibuf_frame)))
319 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (minibuf_window)));
320 #endif
322 if (m)
324 echo_area_glyphs = m;
325 echo_area_glyphs_length = len;
327 else
328 echo_area_glyphs = previous_echo_glyphs = 0;
330 do_pending_window_change ();
331 echo_area_display ();
332 update_frame (XFRAME (XWINDOW (minibuf_window)->frame), 1, 1);
333 do_pending_window_change ();
334 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
335 (*frame_up_to_date_hook) (XFRAME (XWINDOW (minibuf_window)->frame));
339 void
340 message1 (m)
341 char *m;
343 message2 (m, (m ? strlen (m) : 0));
346 void
347 message1_nolog (m)
348 char *m;
350 message2_nolog (m, (m ? strlen (m) : 0));
353 /* Truncate what will be displayed in the echo area
354 the next time we display it--but don't redisplay it now. */
356 void
357 truncate_echo_area (len)
358 int len;
360 /* A null message buffer means that the frame hasn't really been
361 initialized yet. Error messages get reported properly by
362 cmd_error, so this must be just an informative message; toss it. */
363 if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
364 echo_area_glyphs_length = len;
367 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
368 zero if being used by message. */
369 int message_buf_print;
371 /* Dump an informative message to the minibuf. If m is 0, clear out
372 any existing message, and let the minibuffer text show through. */
373 /* VARARGS 1 */
374 void
375 message (m, a1, a2, a3)
376 char *m;
377 EMACS_INT a1, a2, a3;
379 if (noninteractive)
381 if (m)
383 if (noninteractive_need_newline)
384 putc ('\n', stderr);
385 noninteractive_need_newline = 0;
386 fprintf (stderr, m, a1, a2, a3);
387 if (cursor_in_echo_area == 0)
388 fprintf (stderr, "\n");
389 fflush (stderr);
392 else if (INTERACTIVE)
394 /* The frame whose minibuffer we're going to display the message on.
395 It may be larger than the selected frame, so we need
396 to use its buffer, not the selected frame's buffer. */
397 FRAME_PTR echo_frame;
398 #ifdef MULTI_FRAME
399 choose_minibuf_frame ();
400 echo_frame = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
401 #else
402 echo_frame = selected_frame;
403 #endif
405 /* A null message buffer means that the frame hasn't really been
406 initialized yet. Error messages get reported properly by
407 cmd_error, so this must be just an informative message; toss it. */
408 if (FRAME_MESSAGE_BUF (echo_frame))
410 if (m)
412 int len;
413 #ifdef NO_ARG_ARRAY
414 EMACS_INT a[3];
415 a[0] = a1;
416 a[1] = a2;
417 a[2] = a3;
419 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
420 FRAME_WIDTH (echo_frame), m, 0, 3, a);
421 #else
422 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
423 FRAME_WIDTH (echo_frame), m, 0, 3, &a1);
424 #endif /* NO_ARG_ARRAY */
426 message2 (FRAME_MESSAGE_BUF (echo_frame), len);
428 else
429 message1 (0);
431 /* Print should start at the beginning of the message
432 buffer next time. */
433 message_buf_print = 0;
438 void
439 update_echo_area ()
441 message2 (echo_area_glyphs, echo_area_glyphs_length);
444 static void
445 echo_area_display ()
447 register int vpos;
448 FRAME_PTR f;
450 #ifdef MULTI_FRAME
451 choose_minibuf_frame ();
452 #endif
454 f = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
456 if (! FRAME_VISIBLE_P (f))
457 return;
459 if (frame_garbaged)
461 redraw_garbaged_frames ();
462 frame_garbaged = 0;
465 if (echo_area_glyphs || minibuf_level == 0)
467 vpos = XFASTINT (XWINDOW (minibuf_window)->top);
468 get_display_line (f, vpos, 0);
469 display_string (XWINDOW (minibuf_window), vpos,
470 echo_area_glyphs ? echo_area_glyphs : "",
471 echo_area_glyphs ? echo_area_glyphs_length : -1,
472 0, 0, 0, 0, FRAME_WIDTH (f));
474 /* If desired cursor location is on this line, put it at end of text */
475 if (FRAME_CURSOR_Y (f) == vpos)
476 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
478 /* Fill the rest of the minibuffer window with blank lines. */
480 int i;
482 for (i = vpos + 1;
483 i < vpos + XFASTINT (XWINDOW (minibuf_window)->height); i++)
485 get_display_line (f, i, 0);
486 display_string (XWINDOW (minibuf_window), vpos,
487 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f));
491 else if (!EQ (minibuf_window, selected_window))
492 windows_or_buffers_changed++;
494 if (EQ (minibuf_window, selected_window))
495 this_line_bufpos = 0;
497 previous_echo_glyphs = echo_area_glyphs;
500 #ifdef HAVE_X_WINDOWS
501 static char frame_title_buf[512];
502 static char *frame_title_ptr;
504 static int
505 store_frame_title (str, mincol, maxcol)
506 char *str;
507 int mincol, maxcol;
509 char *limit;
510 if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
511 maxcol = sizeof (frame_title_buf);
512 limit = &frame_title_buf[maxcol];
513 while (*str != '\0' && frame_title_ptr < limit)
514 *frame_title_ptr++ = *str++;
515 while (frame_title_ptr < &frame_title_buf[mincol])
516 *frame_title_ptr++ = ' ';
517 return frame_title_ptr - frame_title_buf;
520 static void
521 x_consider_frame_title (frame)
522 Lisp_Object frame;
524 Lisp_Object fmt;
525 struct buffer *obuf;
526 int len;
527 FRAME_PTR f = XFRAME (frame);
529 if (!FRAME_X_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name)
530 return;
531 multiple_frames = !EQ (Fnext_frame (frame, Qnil), frame);
532 obuf = current_buffer;
533 Fset_buffer (XWINDOW (f->selected_window)->buffer);
534 fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
535 frame_title_ptr = frame_title_buf;
536 len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
537 0, sizeof (frame_title_buf), fmt);
538 frame_title_ptr = 0;
539 set_buffer_internal (obuf);
540 /* Set the name only if it's changed. This avoids consing
541 in the common case where it hasn't. (If it turns out that we've
542 already wasted too much time by walking through the list with
543 display_mode_element, then we might need to optimize at a higher
544 level than this.) */
545 if (! STRINGP (f->name) || XSTRING (f->name)->size != len
546 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
547 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
549 #else
550 #define frame_title_ptr ((char *)0)
551 #define store_frame_title(str, mincol, maxcol) 0
552 #endif
554 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
555 This can't be done in `redisplay' itself because it can call eval. */
557 void
558 prepare_menu_bars ()
560 register struct window *w = XWINDOW (selected_window);
561 int all_windows;
563 if (noninteractive)
564 return;
566 /* Set the visible flags for all frames.
567 Do this before checking for resized or garbaged frames; they want
568 to know if their frames are visible.
569 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
571 Lisp_Object tail, frame;
573 FOR_EACH_FRAME (tail, frame)
574 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
577 /* Notice any pending interrupt request to change frame size. */
578 do_pending_window_change ();
580 if (frame_garbaged)
582 redraw_garbaged_frames ();
583 frame_garbaged = 0;
586 all_windows = (update_mode_lines || buffer_shared > 1
587 || clip_changed || windows_or_buffers_changed);
589 #ifdef HAVE_X_WINDOWS
590 if (windows_or_buffers_changed)
592 Lisp_Object tail, frame;
594 FOR_EACH_FRAME (tail, frame)
595 if (FRAME_VISIBLE_P (XFRAME (frame))
596 || FRAME_ICONIFIED_P (XFRAME (frame)))
597 x_consider_frame_title (frame);
599 #endif
601 /* Update the menu bar item lists, if appropriate.
602 This has to be done before any actual redisplay
603 or generation of display lines. */
604 if (all_windows)
606 Lisp_Object tail, frame;
608 FOR_EACH_FRAME (tail, frame)
609 update_menu_bar (XFRAME (frame));
611 else
612 update_menu_bar (selected_frame);
615 /* Do a frame update, taking possible shortcuts into account.
616 This is the main external entry point for redisplay.
618 If the last redisplay displayed an echo area message and that
619 message is no longer requested, we clear the echo area
620 or bring back the minibuffer if that is in use.
622 Do not call eval from within this function.
623 Calls to eval after the call to echo_area_display would confuse
624 the display_line mechanism and would cause a crash.
625 Calls to eval before that point will work most of the time,
626 but can still lose, because this function
627 can be called from signal handlers; with alarms set up;
628 or with synchronous processes running.
630 See Fcall_process; if you called it from here, it could be
631 entered recursively. */
633 static int do_verify_charstarts;
635 /* Counter is used to clear the face cache
636 no more than once ever 1000 redisplays. */
637 static int clear_face_cache_count;
639 void
640 redisplay ()
642 register struct window *w = XWINDOW (selected_window);
643 register int pause;
644 int must_finish = 0;
645 int all_windows;
646 register int tlbufpos, tlendpos;
647 struct position pos;
648 extern int input_pending;
650 if (noninteractive)
651 return;
653 /* Set the visible flags for all frames.
654 Do this before checking for resized or garbaged frames; they want
655 to know if their frames are visible.
656 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
658 Lisp_Object tail, frame;
660 FOR_EACH_FRAME (tail, frame)
661 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
664 /* Notice any pending interrupt request to change frame size. */
665 do_pending_window_change ();
667 if (frame_garbaged)
669 redraw_garbaged_frames ();
670 frame_garbaged = 0;
673 if (clip_changed || windows_or_buffers_changed
674 || (!NILP (w->column_number_displayed)
675 && XFASTINT (w->column_number_displayed) != current_column ()))
676 update_mode_lines++;
678 /* Detect case that we need to write a star in the mode line. */
679 if (XFASTINT (w->last_modified) < MODIFF
680 && XFASTINT (w->last_modified) <= SAVE_MODIFF)
682 w->update_mode_line = Qt;
683 if (buffer_shared > 1)
684 update_mode_lines++;
687 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
689 all_windows = update_mode_lines || buffer_shared > 1;
691 /* If specs for an arrow have changed, do thorough redisplay
692 to ensure we remove any arrow that should no longer exist. */
693 if (! EQ (Voverlay_arrow_position, last_arrow_position)
694 || ! EQ (Voverlay_arrow_string, last_arrow_string))
695 all_windows = 1, clip_changed = 1;
697 /* Normally the message* functions will have already displayed and
698 updated the echo area, but the frame may have been trashed, or
699 the update may have been preempted, so display the echo area
700 again here. */
701 if (echo_area_glyphs || previous_echo_glyphs)
703 echo_area_display ();
704 must_finish = 1;
707 /* If showing region, and mark has changed, must redisplay whole window. */
708 if (((!NILP (Vtransient_mark_mode)
709 && !NILP (XBUFFER (w->buffer)->mark_active))
710 != !NILP (w->region_showing))
711 || (!NILP (w->region_showing)
712 && !EQ (w->region_showing,
713 Fmarker_position (XBUFFER (w->buffer)->mark))))
714 this_line_bufpos = -1;
716 tlbufpos = this_line_bufpos;
717 tlendpos = this_line_endpos;
718 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
719 && FRAME_VISIBLE_P (XFRAME (w->frame))
720 /* Make sure recorded data applies to current buffer, etc */
721 && this_line_buffer == current_buffer
722 && current_buffer == XBUFFER (w->buffer)
723 && NILP (w->force_start)
724 /* Point must be on the line that we have info recorded about */
725 && PT >= tlbufpos
726 && PT <= Z - tlendpos
727 /* All text outside that line, including its final newline,
728 must be unchanged */
729 && (XFASTINT (w->last_modified) >= MODIFF
730 || (beg_unchanged >= tlbufpos - 1
731 && GPT >= tlbufpos
732 /* If selective display, can't optimize
733 if the changes start at the beginning of the line. */
734 && ((INTEGERP (current_buffer->selective_display)
735 && XINT (current_buffer->selective_display) > 0
736 ? (beg_unchanged >= tlbufpos
737 && GPT > tlbufpos)
738 : 1))
739 && end_unchanged >= tlendpos
740 && Z - GPT >= tlendpos)))
742 if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n'
743 && (tlbufpos == ZV
744 || FETCH_CHAR (tlbufpos) == '\n'))
745 /* Former continuation line has disappeared by becoming empty */
746 goto cancel;
747 else if (XFASTINT (w->last_modified) < MODIFF
748 || MINI_WINDOW_P (w))
750 cursor_vpos = -1;
751 overlay_arrow_seen = 0;
752 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
753 pos_tab_offset (w, tlbufpos));
754 /* If line contains point, is not continued,
755 and ends at same distance from eob as before, we win */
756 if (cursor_vpos >= 0 && this_line_bufpos
757 && this_line_endpos == tlendpos)
759 /* If this is not the window's last line,
760 we must adjust the charstarts of the lines below. */
761 if (this_line_vpos + 1
762 < XFASTINT (w->top) + window_internal_height (w))
764 int left = XFASTINT (w->left);
765 int *charstart_next_line
766 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
767 int i;
768 int adjust;
770 if (Z - tlendpos == ZV)
771 /* This line ends at end of (accessible part of) buffer.
772 There is no newline to count. */
773 adjust = Z - tlendpos - charstart_next_line[left];
774 else
775 /* This line ends in a newline.
776 Must take account of the newline and the rest of the
777 text that follows. */
778 adjust = Z - tlendpos + 1 - charstart_next_line[left];
780 adjust_window_charstarts (w, this_line_vpos, adjust);
783 if (XFASTINT (w->width) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
784 preserve_other_columns (w);
785 goto update;
787 else
788 goto cancel;
790 else if (PT == XFASTINT (w->last_point))
792 if (!must_finish)
794 do_pending_window_change ();
795 return;
797 goto update;
799 /* If highlighting the region, we can't just move the cursor. */
800 else if (! (!NILP (Vtransient_mark_mode)
801 && !NILP (current_buffer->mark_active))
802 && NILP (w->region_showing))
804 pos = *compute_motion (tlbufpos, 0,
805 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
806 PT, 2, - (1 << (SHORTBITS - 1)),
807 window_internal_width (w) - 1,
808 XINT (w->hscroll),
809 pos_tab_offset (w, tlbufpos), w);
810 if (pos.vpos < 1)
812 FRAME_CURSOR_X (selected_frame)
813 = XFASTINT (w->left) + max (pos.hpos, 0);
814 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
815 goto update;
817 else
818 goto cancel;
820 cancel:
821 /* Text changed drastically or point moved off of line */
822 cancel_line (this_line_vpos, selected_frame);
825 this_line_bufpos = 0;
826 all_windows |= buffer_shared > 1;
828 clear_face_cache_count++;
830 if (all_windows)
832 Lisp_Object tail, frame;
834 #ifdef HAVE_FACES
835 /* Clear the face cache, only when we do a full redisplay
836 and not too often either. */
837 if (clear_face_cache_count > 1000)
839 clear_face_cache ();
840 clear_face_cache_count = 0;
842 #endif
844 /* Recompute # windows showing selected buffer.
845 This will be incremented each time such a window is displayed. */
846 buffer_shared = 0;
848 FOR_EACH_FRAME (tail, frame)
850 FRAME_PTR f = XFRAME (frame);
852 /* Mark all the scroll bars to be removed; we'll redeem the ones
853 we want when we redisplay their windows. */
854 if (condemn_scroll_bars_hook)
855 (*condemn_scroll_bars_hook) (f);
857 if (FRAME_VISIBLE_P (f))
858 redisplay_windows (FRAME_ROOT_WINDOW (f));
860 /* Any scroll bars which redisplay_windows should have nuked
861 should now go away. */
862 if (judge_scroll_bars_hook)
863 (*judge_scroll_bars_hook) (f);
866 else if (FRAME_VISIBLE_P (selected_frame))
868 redisplay_window (selected_window, 1);
869 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
870 preserve_other_columns (w);
873 update:
874 /* Prevent various kinds of signals during display update.
875 stdio is not robust about handling signals,
876 which can cause an apparent I/O error. */
877 if (interrupt_input)
878 unrequest_sigio ();
879 stop_polling ();
881 #ifdef MULTI_FRAME
882 if (all_windows)
884 Lisp_Object tail;
886 pause = 0;
888 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
890 FRAME_PTR f;
892 if (!FRAMEP (XCONS (tail)->car))
893 continue;
895 f = XFRAME (XCONS (tail)->car);
896 if (FRAME_VISIBLE_P (f))
898 pause |= update_frame (f, 0, 0);
899 if (!pause)
901 mark_window_display_accurate (f->root_window, 1);
902 if (frame_up_to_date_hook != 0)
903 (*frame_up_to_date_hook) (f);
908 else
909 #endif /* MULTI_FRAME */
911 if (FRAME_VISIBLE_P (selected_frame))
912 pause = update_frame (selected_frame, 0, 0);
914 /* We may have called echo_area_display at the top of this
915 function. If the echo area is on another frame, that may
916 have put text on a frame other than the selected one, so the
917 above call to update_frame would not have caught it. Catch
918 it here. */
920 FRAME_PTR mini_frame
921 = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
923 if (mini_frame != selected_frame)
924 pause |= update_frame (mini_frame, 0, 0);
928 /* If frame does not match, prevent doing single-line-update next time.
929 Also, don't forget to check every line to update the arrow. */
930 if (pause)
932 this_line_bufpos = 0;
933 if (!NILP (last_arrow_position))
935 last_arrow_position = Qt;
936 last_arrow_string = Qt;
938 /* If we pause after scrolling, some lines in current_frame
939 may be null, so preserve_other_columns won't be able to
940 preserve all the vertical-bar separators. So, avoid using it
941 in that case. */
942 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
943 update_mode_lines = 1;
946 /* Now text on frame agrees with windows, so
947 put info into the windows for partial redisplay to follow */
949 if (!pause)
951 register struct buffer *b = XBUFFER (w->buffer);
953 blank_end_of_window = 0;
954 clip_changed = 0;
955 unchanged_modified = BUF_MODIFF (b);
956 beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
957 end_unchanged = BUF_Z (b) - BUF_GPT (b);
959 XSETFASTINT (w->last_point, BUF_PT (b));
960 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
961 XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
963 if (all_windows)
964 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
965 else
967 w->update_mode_line = Qnil;
968 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
969 w->window_end_valid = w->buffer;
970 last_arrow_position = Voverlay_arrow_position;
971 last_arrow_string = Voverlay_arrow_string;
972 if (do_verify_charstarts)
973 verify_charstarts (w);
974 if (frame_up_to_date_hook != 0)
975 (*frame_up_to_date_hook) (selected_frame);
977 update_mode_lines = 0;
978 windows_or_buffers_changed = 0;
981 /* Start SIGIO interrupts coming again.
982 Having them off during the code above
983 makes it less likely one will discard output,
984 but not impossible, since there might be stuff
985 in the system buffer here.
986 But it is much hairier to try to do anything about that. */
988 if (interrupt_input)
989 request_sigio ();
990 start_polling ();
992 /* Change frame size now if a change is pending. */
993 do_pending_window_change ();
995 /* If we just did a pending size change, redisplay again
996 for the new size. */
997 if (windows_or_buffers_changed && !pause)
998 redisplay ();
1001 /* Redisplay, but leave alone any recent echo area message
1002 unless another message has been requested in its place.
1004 This is useful in situations where you need to redisplay but no
1005 user action has occurred, making it inappropriate for the message
1006 area to be cleared. See tracking_off and
1007 wait_reading_process_input for examples of these situations. */
1009 redisplay_preserve_echo_area ()
1011 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
1013 echo_area_glyphs = previous_echo_glyphs;
1014 redisplay ();
1015 echo_area_glyphs = 0;
1017 else
1018 redisplay ();
1021 void
1022 mark_window_display_accurate (window, flag)
1023 Lisp_Object window;
1024 int flag;
1026 register struct window *w;
1028 for (;!NILP (window); window = w->next)
1030 if (!WINDOWP (window)) abort ();
1031 w = XWINDOW (window);
1033 if (!NILP (w->buffer))
1035 XSETFASTINT (w->last_modified,
1036 !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
1038 /* Record if we are showing a region, so can make sure to
1039 update it fully at next redisplay. */
1040 w->region_showing = (!NILP (Vtransient_mark_mode)
1041 && !NILP (XBUFFER (w->buffer)->mark_active)
1042 ? Fmarker_position (XBUFFER (w->buffer)->mark)
1043 : Qnil);
1046 w->window_end_valid = w->buffer;
1047 w->update_mode_line = Qnil;
1049 if (!NILP (w->vchild))
1050 mark_window_display_accurate (w->vchild, flag);
1051 if (!NILP (w->hchild))
1052 mark_window_display_accurate (w->hchild, flag);
1055 if (flag)
1057 last_arrow_position = Voverlay_arrow_position;
1058 last_arrow_string = Voverlay_arrow_string;
1060 else
1062 /* t is unequal to any useful value of Voverlay_arrow_... */
1063 last_arrow_position = Qt;
1064 last_arrow_string = Qt;
1068 /* Update the menu bar item list for frame F.
1069 This has to be done before we start to fill in any display lines,
1070 because it can call eval. */
1072 static void
1073 update_menu_bar (f)
1074 FRAME_PTR f;
1076 struct buffer *old = current_buffer;
1077 Lisp_Object window;
1078 register struct window *w;
1079 window = FRAME_SELECTED_WINDOW (f);
1080 w = XWINDOW (window);
1082 if (update_mode_lines)
1083 w->update_mode_line = Qt;
1085 if (
1086 #ifdef USE_X_TOOLKIT
1087 FRAME_EXTERNAL_MENU_BAR (f)
1088 #else
1089 FRAME_MENU_BAR_LINES (f) > 0
1090 #endif
1093 /* If the user has switched buffers or windows, we need to
1094 recompute to reflect the new bindings. But we'll
1095 recompute when update_mode_lines is set too; that means
1096 that people can use force-mode-line-update to request
1097 that the menu bar be recomputed. The adverse effect on
1098 the rest of the redisplay algorithm is about the same as
1099 windows_or_buffers_changed anyway. */
1100 if (windows_or_buffers_changed
1101 || !NILP (w->update_mode_line)
1102 || (XFASTINT (w->last_modified) < MODIFF
1103 && (XFASTINT (w->last_modified)
1104 <= BUF_SAVE_MODIFF (XBUFFER (w->buffer)))))
1106 struct buffer *prev = current_buffer;
1107 call1 (Vrun_hooks, Qmenu_bar_update_hook);
1108 current_buffer = XBUFFER (w->buffer);
1109 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1110 current_buffer = prev;
1111 #ifdef USE_X_TOOLKIT
1112 set_frame_menubar (f, 0);
1113 #endif /* USE_X_TOOLKIT */
1118 int do_id = 1;
1120 /* Redisplay WINDOW and its subwindows and siblings. */
1122 static void
1123 redisplay_windows (window)
1124 Lisp_Object window;
1126 for (; !NILP (window); window = XWINDOW (window)->next)
1127 redisplay_window (window, 0);
1130 /* Redisplay window WINDOW and its subwindows. */
1132 static void
1133 redisplay_window (window, just_this_one)
1134 Lisp_Object window;
1135 int just_this_one;
1137 register struct window *w = XWINDOW (window);
1138 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1139 int height;
1140 register int lpoint = PT;
1141 struct buffer *old = current_buffer;
1142 register int width = window_internal_width (w) - 1;
1143 register int startp;
1144 register int hscroll = XINT (w->hscroll);
1145 struct position pos;
1146 int opoint = PT;
1147 int tem;
1148 int window_needs_modeline;
1150 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1152 /* If this is a combination window, do its children; that's all. */
1154 if (!NILP (w->vchild))
1156 redisplay_windows (w->vchild);
1157 return;
1159 if (!NILP (w->hchild))
1161 redisplay_windows (w->hchild);
1162 return;
1164 if (NILP (w->buffer))
1165 abort ();
1167 height = window_internal_height (w);
1169 if (MINI_WINDOW_P (w))
1171 if (w == XWINDOW (minibuf_window))
1173 if (echo_area_glyphs)
1174 /* We've already displayed the echo area glyphs, if any. */
1175 goto finish_scroll_bars;
1177 else
1179 /* This is a minibuffer, but it's not the currently active one, so
1180 clear it. */
1181 int vpos = XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1182 int i;
1184 for (i = 0; i < height; i++)
1186 get_display_line (f, vpos + i, 0);
1187 display_string (w, vpos + i, "", 0, 0, 0, 1, 0, width);
1190 goto finish_scroll_bars;
1194 if (update_mode_lines)
1195 w->update_mode_line = Qt;
1197 /* Otherwise set up data on this window; select its buffer and point value */
1199 set_buffer_temp (XBUFFER (w->buffer));
1200 opoint = PT;
1202 /* Count number of windows showing the selected buffer.
1203 An indirect buffer counts as its base buffer. */
1205 if (!just_this_one)
1207 struct buffer *current_base, *window_base;
1208 current_base = current_buffer;
1209 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
1210 if (current_base->base_buffer)
1211 current_base = current_base->base_buffer;
1212 if (window_base->base_buffer)
1213 window_base = window_base->base_buffer;
1214 if (current_base == window_base)
1215 buffer_shared++;
1218 /* POINT refers normally to the selected window.
1219 For any other window, set up appropriate value. */
1221 if (!EQ (window, selected_window))
1223 int new_pt = marker_position (w->pointm);
1224 if (new_pt < BEGV)
1226 new_pt = BEGV;
1227 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1229 else if (new_pt > (ZV - 1))
1231 new_pt = ZV;
1232 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1234 /* We don't use SET_PT so that the point-motion hooks don't run. */
1235 BUF_PT (current_buffer) = new_pt;
1238 /* If any of the character widths specified in the display table
1239 have changed, invalidate the width run cache. It's true that this
1240 may be a bit late to catch such changes, but the rest of
1241 redisplay goes (non-fatally) haywire when the display table is
1242 changed, so why should we worry about doing any better? */
1243 if (current_buffer->width_run_cache)
1245 struct Lisp_Vector *disptab = buffer_display_table ();
1247 if (! disptab_matches_widthtab (disptab,
1248 XVECTOR (current_buffer->width_table)))
1250 invalidate_region_cache (current_buffer,
1251 current_buffer->width_run_cache,
1252 BEG, Z);
1253 recompute_width_table (current_buffer, disptab);
1257 /* If window-start is screwed up, choose a new one. */
1258 if (XMARKER (w->start)->buffer != current_buffer)
1259 goto recenter;
1261 startp = marker_position (w->start);
1263 /* Handle case where place to start displaying has been specified,
1264 unless the specified location is outside the accessible range. */
1265 if (!NILP (w->force_start))
1267 /* Forget any recorded base line for line number display. */
1268 w->base_line_number = Qnil;
1269 w->update_mode_line = Qt;
1270 w->force_start = Qnil;
1271 XSETFASTINT (w->last_modified, 0);
1272 if (startp < BEGV) startp = BEGV;
1273 if (startp > ZV) startp = ZV;
1274 try_window (window, startp);
1275 if (cursor_vpos < 0)
1277 /* If point does not appear, move point so it does appear */
1278 pos = *compute_motion (startp, 0,
1279 ((EQ (window, minibuf_window) && startp == 1)
1280 ? minibuf_prompt_width : 0)
1282 (hscroll ? 1 - hscroll : 0),
1283 ZV, height / 2,
1284 - (1 << (SHORTBITS - 1)),
1285 width, hscroll, pos_tab_offset (w, startp), w);
1286 BUF_PT (current_buffer) = pos.bufpos;
1287 if (w != XWINDOW (selected_window))
1288 Fset_marker (w->pointm, make_number (PT), Qnil);
1289 else
1291 if (current_buffer == old)
1292 lpoint = PT;
1293 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1294 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1296 /* If we are highlighting the region,
1297 then we just changed the region, so redisplay to show it. */
1298 if (!NILP (Vtransient_mark_mode)
1299 && !NILP (current_buffer->mark_active))
1301 cancel_my_columns (XWINDOW (window));
1302 try_window (window, startp);
1305 goto done;
1308 /* Handle case where text has not changed, only point,
1309 and it has not moved off the frame */
1311 /* This code is not used for minibuffer for the sake of
1312 the case of redisplaying to replace an echo area message;
1313 since in that case the minibuffer contents per se are usually unchanged.
1314 This code is of no real use in the minibuffer since
1315 the handling of this_line_bufpos, etc.,
1316 in redisplay handles the same cases. */
1318 if (XFASTINT (w->last_modified) >= MODIFF
1319 && PT >= startp && !clip_changed
1320 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
1321 /* Can't use this case if highlighting a region. */
1322 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1323 && NILP (w->region_showing)
1324 /* If end pos is out of date, scroll bar and percentage will be wrong */
1325 && INTEGERP (w->window_end_vpos)
1326 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
1327 && !EQ (window, minibuf_window))
1329 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
1330 PT, height + 1, 10000, width, hscroll,
1331 pos_tab_offset (w, startp), w);
1333 if (pos.vpos < height)
1335 /* Ok, point is still on frame */
1336 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1338 /* These variables are supposed to be origin 1 */
1339 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1340 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1342 /* This doesn't do the trick, because if a window to the right of
1343 this one must be redisplayed, this does nothing because there
1344 is nothing in DesiredFrame yet, and then the other window is
1345 redisplayed, making likes that are empty in this window's columns.
1346 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1347 preserve_my_columns (w);
1349 goto done;
1351 /* Don't bother trying redisplay with same start;
1352 we already know it will lose */
1354 /* If current starting point was originally the beginning of a line
1355 but no longer is, find a new starting point. */
1356 else if (!NILP (w->start_at_line_beg)
1357 && !(startp <= BEGV
1358 || FETCH_CHAR (startp - 1) == '\n'))
1360 goto recenter;
1362 else if (just_this_one && !MINI_WINDOW_P (w)
1363 && PT >= startp
1364 && XFASTINT (w->last_modified)
1365 /* or else vmotion on first line won't work. */
1366 && ! NILP (w->start_at_line_beg)
1367 && ! EQ (w->window_end_valid, Qnil)
1368 && do_id && !clip_changed
1369 && !blank_end_of_window
1370 && XFASTINT (w->width) == FRAME_WIDTH (f)
1371 /* Can't use this case if highlighting a region. */
1372 && !(!NILP (Vtransient_mark_mode)
1373 && !NILP (current_buffer->mark_active))
1374 && NILP (w->region_showing)
1375 && EQ (last_arrow_position, Voverlay_arrow_position)
1376 && EQ (last_arrow_string, Voverlay_arrow_string)
1377 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
1378 && tem != -2)
1380 /* tem > 0 means success. tem == -1 means choose new start.
1381 tem == -2 means try again with same start,
1382 and nothing but whitespace follows the changed stuff.
1383 tem == 0 means try again with same start. */
1384 if (tem > 0)
1385 goto done;
1387 else if (startp >= BEGV && startp <= ZV
1388 /* Avoid starting display at end of buffer! */
1389 && (startp < ZV || startp == BEGV
1390 || (XFASTINT (w->last_modified) >= MODIFF)))
1392 /* Try to redisplay starting at same place as before */
1393 /* If point has not moved off frame, accept the results */
1394 try_window (window, startp);
1395 if (cursor_vpos >= 0)
1397 if (!just_this_one || clip_changed || beg_unchanged < startp)
1398 /* Forget any recorded base line for line number display. */
1399 w->base_line_number = Qnil;
1400 goto done;
1402 else
1403 cancel_my_columns (w);
1406 XSETFASTINT (w->last_modified, 0);
1407 w->update_mode_line = Qt;
1409 /* Try to scroll by specified few lines */
1411 if (scroll_step && !clip_changed)
1413 if (PT > startp)
1415 pos = *vmotion (Z - XFASTINT (w->window_end_pos),
1416 scroll_step, width, hscroll, window);
1417 if (pos.vpos >= height)
1418 goto scroll_fail;
1421 pos = *vmotion (startp, PT < startp ? - scroll_step : scroll_step,
1422 width, hscroll, window);
1424 if (PT >= pos.bufpos)
1426 try_window (window, pos.bufpos);
1427 if (cursor_vpos >= 0)
1429 if (!just_this_one || clip_changed || beg_unchanged < startp)
1430 /* Forget any recorded base line for line number display. */
1431 w->base_line_number = Qnil;
1432 goto done;
1434 else
1435 cancel_my_columns (w);
1437 scroll_fail: ;
1440 /* Finally, just choose place to start which centers point */
1442 recenter:
1443 /* Forget any previously recorded base line for line number display. */
1444 w->base_line_number = Qnil;
1446 pos = *vmotion (PT, - (height / 2), width, hscroll, window);
1447 try_window (window, pos.bufpos);
1449 startp = marker_position (w->start);
1450 w->start_at_line_beg
1451 = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
1453 done:
1454 if ((!NILP (w->update_mode_line)
1455 /* If window not full width, must redo its mode line
1456 if the window to its side is being redone */
1457 || (!just_this_one && width < FRAME_WIDTH (f) - 1)
1458 || INTEGERP (w->base_line_pos)
1459 || (!NILP (w->column_number_displayed)
1460 && XFASTINT (w->column_number_displayed) != current_column ()))
1461 && height != XFASTINT (w->height))
1462 display_mode_line (w);
1463 if (! line_number_displayed
1464 && ! BUFFERP (w->base_line_pos))
1466 w->base_line_pos = Qnil;
1467 w->base_line_number = Qnil;
1470 /* When we reach a frame's selected window, redo the frame's menu bar. */
1471 if (!NILP (w->update_mode_line)
1472 #ifdef USE_X_TOOLKIT
1473 && FRAME_EXTERNAL_MENU_BAR (f)
1474 #else
1475 && FRAME_MENU_BAR_LINES (f) > 0
1476 #endif
1477 && EQ (FRAME_SELECTED_WINDOW (f), window))
1478 display_menu_bar (w);
1480 finish_scroll_bars:
1481 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1483 int start, end, whole;
1485 /* Calculate the start and end positions for the current window.
1486 At some point, it would be nice to choose between scrollbars
1487 which reflect the whole buffer size, with special markers
1488 indicating narrowing, and scrollbars which reflect only the
1489 visible region.
1491 Note that minibuffers sometimes aren't displaying any text. */
1492 if (! MINI_WINDOW_P (w)
1493 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
1495 whole = ZV - BEGV;
1496 start = startp - BEGV;
1497 /* I don't think this is guaranteed to be right. For the
1498 moment, we'll pretend it is. */
1499 end = (Z - XINT (w->window_end_pos)) - BEGV;
1501 if (end < start) end = start;
1502 if (whole < (end - start)) whole = end - start;
1504 else
1505 start = end = whole = 0;
1507 /* Indicate what this scroll bar ought to be displaying now. */
1508 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
1510 /* Note that we actually used the scroll bar attached to this window,
1511 so it shouldn't be deleted at the end of redisplay. */
1512 (*redeem_scroll_bar_hook) (w);
1515 BUF_PT (current_buffer) = opoint;
1516 set_buffer_temp (old);
1517 BUF_PT (current_buffer) = lpoint;
1520 /* Do full redisplay on one window, starting at position `pos'. */
1522 static void
1523 try_window (window, pos)
1524 Lisp_Object window;
1525 register int pos;
1527 register struct window *w = XWINDOW (window);
1528 register int height = window_internal_height (w);
1529 register int vpos = XFASTINT (w->top);
1530 register int last_text_vpos = vpos;
1531 int tab_offset = pos_tab_offset (w, pos);
1532 FRAME_PTR f = XFRAME (w->frame);
1533 int width = window_internal_width (w) - 1;
1534 struct position val;
1536 Fset_marker (w->start, make_number (pos), Qnil);
1537 cursor_vpos = -1;
1538 overlay_arrow_seen = 0;
1539 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
1541 while (--height >= 0)
1543 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
1544 tab_offset += width;
1545 if (val.vpos) tab_offset = 0;
1546 vpos++;
1547 if (pos != val.bufpos)
1548 last_text_vpos
1549 /* Next line, unless prev line ended in end of buffer with no cr */
1550 = vpos - (val.vpos && (FETCH_CHAR (val.bufpos - 1) != '\n'
1551 #ifdef USE_TEXT_PROPERTIES
1552 || ! NILP (Fget_char_property (val.bufpos-1,
1553 Qinvisible,
1554 window))
1555 #endif
1557 pos = val.bufpos;
1560 /* If last line is continued in middle of character,
1561 include the split character in the text considered on the frame */
1562 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
1563 pos++;
1565 /* If bottom just moved off end of frame, change mode line percentage. */
1566 if (XFASTINT (w->window_end_pos) == 0
1567 && Z != pos)
1568 w->update_mode_line = Qt;
1570 /* Say where last char on frame will be, once redisplay is finished. */
1571 XSETFASTINT (w->window_end_pos, Z - pos);
1572 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
1573 /* But that is not valid info until redisplay finishes. */
1574 w->window_end_valid = Qnil;
1577 /* Try to redisplay when buffer is modified locally,
1578 computing insert/delete line to preserve text outside
1579 the bounds of the changes.
1580 Return 1 if successful, 0 if if cannot tell what to do,
1581 or -1 to tell caller to find a new window start,
1582 or -2 to tell caller to do normal redisplay with same window start. */
1584 static int
1585 try_window_id (window)
1586 Lisp_Object window;
1588 int pos;
1589 register struct window *w = XWINDOW (window);
1590 register int height = window_internal_height (w);
1591 FRAME_PTR f = XFRAME (w->frame);
1592 int top = XFASTINT (w->top);
1593 int start = marker_position (w->start);
1594 int width = window_internal_width (w) - 1;
1595 int hscroll = XINT (w->hscroll);
1596 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1597 register int vpos;
1598 register int i, tem;
1599 int last_text_vpos = 0;
1600 int stop_vpos;
1601 int selective = (INTEGERP (current_buffer->selective_display)
1602 ? XINT (current_buffer->selective_display)
1603 : !NILP (current_buffer->selective_display) ? -1 : 0);
1605 struct position val, bp, ep, xp, pp;
1606 int scroll_amount = 0;
1607 int delta;
1608 int tab_offset, epto;
1610 if (GPT - BEG < beg_unchanged)
1611 beg_unchanged = GPT - BEG;
1612 if (Z - GPT < end_unchanged)
1613 end_unchanged = Z - GPT;
1615 if (beg_unchanged + BEG < start)
1616 return 0; /* Give up if changes go above top of window */
1618 /* Find position before which nothing is changed. */
1619 bp = *compute_motion (start, 0, lmargin,
1620 min (ZV, beg_unchanged + BEG), height + 1, 0,
1621 width, hscroll, pos_tab_offset (w, start), w);
1622 if (bp.vpos >= height)
1624 if (PT < bp.bufpos && !bp.contin)
1626 /* All changes are below the frame, and point is on the frame.
1627 We don't need to change the frame at all.
1628 But we need to update window_end_pos to account for
1629 any change in buffer size. */
1630 bp = *compute_motion (start, 0, lmargin,
1631 Z, height, 0,
1632 width, hscroll, pos_tab_offset (w, start), w);
1633 XSETFASTINT (w->window_end_vpos, height);
1634 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
1635 return 1;
1637 return 0;
1640 vpos = bp.vpos;
1642 /* Find beginning of that frame line. Must display from there. */
1643 bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
1645 pos = bp.bufpos;
1646 val.hpos = lmargin;
1647 if (pos < start)
1648 return -1;
1650 /* If about to start displaying at the beginning of a continuation line,
1651 really start with previous frame line, in case it was not
1652 continued when last redisplayed */
1653 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
1655 /* Likewise if we have to worry about selective display. */
1656 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
1658 bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
1659 --vpos;
1660 pos = bp.bufpos;
1663 if (bp.contin && bp.hpos != lmargin)
1665 val.hpos = bp.prevhpos - width + lmargin;
1666 pos--;
1669 bp.vpos = vpos;
1671 /* Find first visible newline after which no more is changed. */
1672 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
1673 if (selective > 0)
1674 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
1675 tem = find_next_newline (tem, 1);
1677 /* Compute the cursor position after that newline. */
1678 ep = *compute_motion (pos, vpos, val.hpos, tem,
1679 height, - (1 << (SHORTBITS - 1)),
1680 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
1682 /* If changes reach past the text available on the frame,
1683 just display rest of frame. */
1684 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
1685 stop_vpos = height;
1686 else
1687 stop_vpos = ep.vpos;
1689 /* If no newline before ep, the line ep is on includes some changes
1690 that must be displayed. Make sure we don't stop before it. */
1691 /* Also, if changes reach all the way until ep.bufpos,
1692 it is possible that something was deleted after the
1693 newline before it, so the following line must be redrawn. */
1694 if (stop_vpos == ep.vpos
1695 && (ep.bufpos == BEGV
1696 || FETCH_CHAR (ep.bufpos - 1) != '\n'
1697 || ep.bufpos == Z - end_unchanged))
1698 stop_vpos = ep.vpos + 1;
1700 cursor_vpos = -1;
1701 overlay_arrow_seen = 0;
1703 /* If changes do not reach to bottom of window,
1704 figure out how much to scroll the rest of the window */
1705 if (stop_vpos < height)
1707 /* Now determine how far up or down the rest of the window has moved */
1708 epto = pos_tab_offset (w, ep.bufpos);
1709 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
1710 Z - XFASTINT (w->window_end_pos),
1711 10000, 0, width, hscroll, epto, w);
1712 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
1714 /* Is everything on frame below the changes whitespace?
1715 If so, no scrolling is really necessary. */
1716 for (i = ep.bufpos; i < xp.bufpos; i++)
1718 tem = FETCH_CHAR (i);
1719 if (tem != ' ' && tem != '\n' && tem != '\t')
1720 break;
1722 if (i == xp.bufpos)
1723 return -2;
1725 XSETFASTINT (w->window_end_vpos,
1726 XFASTINT (w->window_end_vpos) + scroll_amount);
1728 /* Before doing any scrolling, verify that point will be on frame. */
1729 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
1731 if (PT <= xp.bufpos)
1733 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
1734 PT, height, - (1 << (SHORTBITS - 1)),
1735 width, hscroll, epto, w);
1737 else
1739 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
1740 PT, height, - (1 << (SHORTBITS - 1)),
1741 width, hscroll,
1742 pos_tab_offset (w, xp.bufpos), w);
1744 if (pp.bufpos < PT || pp.vpos == height)
1745 return 0;
1746 cursor_vpos = pp.vpos + top;
1747 cursor_hpos = pp.hpos + XFASTINT (w->left);
1750 if (stop_vpos - scroll_amount >= height
1751 || ep.bufpos == xp.bufpos)
1753 if (scroll_amount < 0)
1754 stop_vpos -= scroll_amount;
1755 scroll_amount = 0;
1756 /* In this path, we have altered window_end_vpos
1757 and not left it negative.
1758 We must make sure that, in case display is preempted
1759 before the frame changes to reflect what we do here,
1760 further updates will not come to try_window_id
1761 and assume the frame and window_end_vpos match. */
1762 blank_end_of_window = 1;
1764 else if (!scroll_amount)
1766 /* Even if we don't need to scroll, we must adjust the
1767 charstarts of subsequent lines (that we won't redisplay)
1768 according to the amount of text inserted or deleted. */
1769 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1770 int adjust = ep.bufpos - oldpos;
1771 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
1773 else if (bp.bufpos == Z - end_unchanged)
1775 /* If reprinting everything is nearly as fast as scrolling,
1776 don't bother scrolling. Can happen if lines are short. */
1777 if (scroll_cost (f, bp.vpos + top - scroll_amount,
1778 top + height - max (0, scroll_amount),
1779 scroll_amount)
1780 > xp.bufpos - bp.bufpos - 20)
1781 /* Return "try normal display with same window-start."
1782 Too bad we can't prevent further scroll-thinking. */
1783 return -2;
1784 /* If pure deletion, scroll up as many lines as possible.
1785 In common case of killing a line, this can save the
1786 following line from being overwritten by scrolling
1787 and therefore having to be redrawn. */
1788 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
1789 top + height - max (0, scroll_amount),
1790 scroll_amount, bp.bufpos);
1791 if (!tem)
1792 stop_vpos = height;
1793 else
1795 /* scroll_frame_lines did not properly adjust subsequent
1796 lines' charstarts in the case where the text of the
1797 screen line at bp.vpos has changed.
1798 (This can happen in a deletion that ends in mid-line.)
1799 To adjust properly, we need to make things constent at
1800 the position ep.
1801 So do a second adjust to make that happen.
1802 Note that stop_vpos >= ep.vpos, so it is sufficient
1803 to update the charstarts for lines at ep.vpos and below. */
1804 int oldstart
1805 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1806 adjust_window_charstarts (w, ep.vpos + top - 1,
1807 ep.bufpos - oldstart);
1810 else if (scroll_amount)
1812 /* If reprinting everything is nearly as fast as scrolling,
1813 don't bother scrolling. Can happen if lines are short. */
1814 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
1815 overestimate of cost of reprinting, since xp.bufpos
1816 would end up below the bottom of the window. */
1817 if (scroll_cost (f, ep.vpos + top - scroll_amount,
1818 top + height - max (0, scroll_amount),
1819 scroll_amount)
1820 > xp.bufpos - ep.bufpos - 20)
1821 /* Return "try normal display with same window-start."
1822 Too bad we can't prevent further scroll-thinking. */
1823 return -2;
1824 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
1825 top + height - max (0, scroll_amount),
1826 scroll_amount, ep.bufpos);
1827 if (!tem) stop_vpos = height;
1831 /* In any case, do not display past bottom of window */
1832 if (stop_vpos >= height)
1834 stop_vpos = height;
1835 scroll_amount = 0;
1838 /* Handle case where pos is before w->start --
1839 can happen if part of line had been clipped and is not clipped now */
1840 if (vpos == 0 && pos < marker_position (w->start))
1841 Fset_marker (w->start, make_number (pos), Qnil);
1843 /* Redisplay the lines where the text was changed */
1844 last_text_vpos = vpos;
1845 tab_offset = pos_tab_offset (w, pos);
1846 /* If we are starting display in mid-character, correct tab_offset
1847 to account for passing the line that that character really starts in. */
1848 if (val.hpos < lmargin)
1849 tab_offset += width;
1850 while (vpos < stop_vpos)
1852 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1853 tab_offset += width;
1854 if (val.vpos) tab_offset = 0;
1855 if (pos != val.bufpos)
1856 last_text_vpos
1857 /* Next line, unless prev line ended in end of buffer with no cr */
1858 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
1859 pos = val.bufpos;
1862 /* There are two cases:
1863 1) we have displayed down to the bottom of the window
1864 2) we have scrolled lines below stop_vpos by scroll_amount */
1866 if (vpos == height)
1868 /* If last line is continued in middle of character,
1869 include the split character in the text considered on the frame */
1870 if (val.hpos < lmargin)
1871 val.bufpos++;
1872 XSETFASTINT (w->window_end_vpos, last_text_vpos);
1873 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
1876 /* If scrolling made blank lines at window bottom,
1877 redisplay to fill those lines */
1878 if (scroll_amount < 0)
1880 /* Don't consider these lines for general-purpose scrolling.
1881 That will save time in the scrolling computation. */
1882 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
1883 vpos = xp.vpos;
1884 pos = xp.bufpos;
1885 val.hpos = lmargin;
1886 if (pos == ZV)
1887 vpos = height + scroll_amount;
1888 else if (xp.contin && xp.hpos != lmargin)
1890 val.hpos = xp.prevhpos - width + lmargin;
1891 pos--;
1894 blank_end_of_window = 1;
1895 tab_offset = pos_tab_offset (w, pos);
1896 /* If we are starting display in mid-character, correct tab_offset
1897 to account for passing the line that that character starts in. */
1898 if (val.hpos < lmargin)
1899 tab_offset += width;
1901 while (vpos < height)
1903 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1904 tab_offset += width;
1905 if (val.vpos) tab_offset = 0;
1906 pos = val.bufpos;
1909 /* Here is a case where display_text_line sets cursor_vpos wrong.
1910 Make it be fixed up, below. */
1911 if (xp.bufpos == ZV
1912 && xp.bufpos == PT)
1913 cursor_vpos = -1;
1916 /* If bottom just moved off end of frame, change mode line percentage. */
1917 if (XFASTINT (w->window_end_pos) == 0
1918 && Z != val.bufpos)
1919 w->update_mode_line = Qt;
1921 /* Attempt to adjust end-of-text positions to new bottom line */
1922 if (scroll_amount)
1924 delta = height - xp.vpos;
1925 if (delta < 0
1926 || (delta > 0 && xp.bufpos <= ZV)
1927 || (delta == 0 && xp.hpos))
1929 val = *vmotion (Z - XFASTINT (w->window_end_pos),
1930 delta, width, hscroll, window);
1931 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
1932 XSETFASTINT (w->window_end_vpos,
1933 XFASTINT (w->window_end_vpos) + val.vpos);
1937 w->window_end_valid = Qnil;
1939 /* If point was not in a line that was displayed, find it */
1940 if (cursor_vpos < 0)
1942 val = *compute_motion (start, 0, lmargin, PT, 10000, 10000,
1943 width, hscroll, pos_tab_offset (w, start), w);
1944 /* Admit failure if point is off frame now */
1945 if (val.vpos >= height)
1947 for (vpos = 0; vpos < height; vpos++)
1948 cancel_line (vpos + top, f);
1949 return 0;
1951 cursor_vpos = val.vpos + top;
1952 cursor_hpos = val.hpos + XFASTINT (w->left);
1955 FRAME_CURSOR_X (f) = max (0, cursor_hpos);
1956 FRAME_CURSOR_Y (f) = cursor_vpos;
1958 if (debug_end_pos)
1960 val = *compute_motion (start, 0, lmargin, ZV,
1961 height, - (1 << (SHORTBITS - 1)),
1962 width, hscroll, pos_tab_offset (w, start), w);
1963 if (val.vpos != XFASTINT (w->window_end_vpos))
1964 abort ();
1965 if (XFASTINT (w->window_end_pos)
1966 != Z - val.bufpos)
1967 abort ();
1970 return 1;
1973 /* Mark a section of BUF as modified, but only for the sake of redisplay.
1974 This is useful for recording changes to overlays.
1976 We increment the buffer's modification timestamp and set the
1977 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
1978 as if the region of text between START and END had been modified;
1979 the redisplay code will check this against the windows' timestamps,
1980 and redraw the appropriate area of the buffer.
1982 However, if the buffer is unmodified, we bump the last-save
1983 timestamp as well, so that incrementing the timestamp doesn't fool
1984 Emacs into thinking that the buffer's text has been modified.
1986 Tweaking the timestamps shouldn't hurt the first-modification
1987 timestamps recorded in the undo records; those values aren't
1988 written until just before a real text modification is made, so they
1989 will never catch the timestamp value just before this function gets
1990 called. */
1992 void
1993 redisplay_region (buf, start, end)
1994 struct buffer *buf;
1995 int start, end;
1997 if (start == end)
1998 return;
2000 if (start > end)
2002 int temp = start;
2003 start = end; end = temp;
2006 /* If this is a buffer not in the selected window,
2007 we must do other windows. */
2008 if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
2009 windows_or_buffers_changed = 1;
2010 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
2011 else if (buf != current_buffer)
2012 windows_or_buffers_changed = 1;
2013 /* If multiple windows show this buffer, we must do other windows. */
2014 else if (buffer_shared > 1)
2015 windows_or_buffers_changed = 1;
2016 else
2018 if (unchanged_modified == MODIFF)
2020 beg_unchanged = start - BEG;
2021 end_unchanged = Z - end;
2023 else
2025 if (Z - end < end_unchanged)
2026 end_unchanged = Z - end;
2027 if (start - BEG < beg_unchanged)
2028 beg_unchanged = start - BEG;
2032 /* Increment the buffer's time stamp, but also increment the save
2033 and autosave timestamps, so as not to screw up that timekeeping. */
2034 if (BUF_MODIFF (buf) == BUF_SAVE_MODIFF (buf))
2035 BUF_SAVE_MODIFF (buf)++;
2036 if (BUF_MODIFF (buf) == buf->auto_save_modified)
2037 buf->auto_save_modified++;
2039 BUF_MODIFF (buf) ++;
2043 /* Copy LEN glyphs starting address FROM to the rope TO.
2044 But don't actually copy the parts that would come in before S.
2045 Value is TO, advanced past the copied data.
2046 F is the frame we are displaying in. */
2048 static GLYPH *
2049 copy_part_of_rope (f, to, s, from, len, face)
2050 FRAME_PTR f;
2051 register GLYPH *to; /* Copy to here. */
2052 register GLYPH *s; /* Starting point. */
2053 Lisp_Object *from; /* Data to copy. */
2054 int len;
2055 int face; /* Face to apply to glyphs which don't specify one. */
2057 int n = len;
2058 register Lisp_Object *fp = from;
2059 /* These cache the results of the last call to compute_glyph_face. */
2060 int last_code = -1;
2061 int last_merged = 0;
2063 #ifdef HAVE_FACES
2064 if (! FRAME_TERMCAP_P (f))
2065 while (n--)
2067 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2068 int facecode;
2070 if (FAST_GLYPH_FACE (glyph) == 0)
2071 /* If GLYPH has no face code, use FACE. */
2072 facecode = face;
2073 else if (FAST_GLYPH_FACE (glyph) == last_code)
2074 /* If it's same as previous glyph, use same result. */
2075 facecode = last_merged;
2076 else
2078 /* Merge this glyph's face and remember the result. */
2079 last_code = FAST_GLYPH_FACE (glyph);
2080 last_merged = facecode = compute_glyph_face (f, last_code, face);
2083 if (to >= s)
2084 *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
2085 ++to;
2086 ++fp;
2088 else
2089 #endif
2090 while (n--)
2092 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2093 ++to;
2094 ++fp;
2096 return to;
2099 /* Correct a glyph by replacing its specified user-level face code
2100 with a displayable computed face code. */
2102 static GLYPH
2103 fix_glyph (f, glyph, cface)
2104 FRAME_PTR f;
2105 GLYPH glyph;
2106 int cface;
2108 #ifdef HAVE_FACES
2109 if (! FRAME_TERMCAP_P (f))
2111 if (FAST_GLYPH_FACE (glyph) != 0)
2112 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
2113 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
2115 #endif
2116 return glyph;
2119 /* Display one line of window W, starting at position START in W's buffer.
2121 Display starting at horizontal position HPOS, expressed relative to
2122 W's left edge. In situations where the text at START shouldn't
2123 start at the left margin (i.e. when the window is hscrolled, or
2124 we're continuing a line which left off in the midst of a
2125 multi-column character), HPOS should be negative; we throw away
2126 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2127 account.
2129 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2131 Display on position VPOS on the frame. It is origin 0, relative to
2132 the top of the frame, not W.
2134 Returns a STRUCT POSITION giving character to start next line with
2135 and where to display it, including a zero or negative hpos.
2136 The vpos field is not really a vpos; it is 1 unless the line is continued */
2138 struct position val_display_text_line;
2140 static struct position *
2141 display_text_line (w, start, vpos, hpos, taboffset)
2142 struct window *w;
2143 int start;
2144 int vpos;
2145 int hpos;
2146 int taboffset;
2148 register int pos = start;
2149 register int c;
2150 register GLYPH *p1;
2151 int end;
2152 register int pause;
2153 register unsigned char *p;
2154 GLYPH *endp;
2155 register GLYPH *leftmargin;
2156 register GLYPH *p1prev = 0;
2157 register GLYPH *p1start;
2158 int *charstart;
2159 FRAME_PTR f = XFRAME (w->frame);
2160 int tab_width = XINT (current_buffer->tab_width);
2161 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
2162 int width = window_internal_width (w) - 1;
2163 struct position val;
2164 int lastpos;
2165 int invis;
2166 int hscroll = XINT (w->hscroll);
2167 int truncate = (hscroll
2168 || (truncate_partial_width_windows
2169 && XFASTINT (w->width) < FRAME_WIDTH (f))
2170 || !NILP (current_buffer->truncate_lines));
2172 /* 1 if we should highlight the region. */
2173 int highlight_region
2174 = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
2175 int region_beg, region_end;
2177 int selective = (INTEGERP (current_buffer->selective_display)
2178 ? XINT (current_buffer->selective_display)
2179 : !NILP (current_buffer->selective_display) ? -1 : 0);
2180 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
2181 register struct Lisp_Vector *dp = window_display_table (w);
2183 Lisp_Object default_invis_vector[3];
2184 /* Nonzero means display something where there are invisible lines.
2185 The precise value is the number of glyphs to display. */
2186 int selective_rlen
2187 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
2188 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
2189 : selective && !NILP (current_buffer->selective_display_ellipses)
2190 ? 3 : 0);
2191 /* This is the sequence of Lisp objects to display
2192 when there are invisible lines. */
2193 Lisp_Object *invis_vector_contents
2194 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2195 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2196 : default_invis_vector);
2198 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
2199 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
2200 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
2201 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
2203 /* The next buffer location at which the face should change, due
2204 to overlays or text property changes. */
2205 int next_face_change;
2207 #ifdef USE_TEXT_PROPERTIES
2208 /* The next location where the `invisible' property changes */
2209 int next_invisible;
2210 #endif
2212 /* The face we're currently using. */
2213 int current_face = 0;
2214 int i;
2216 XSETFASTINT (default_invis_vector[2], '.');
2217 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2219 hpos += XFASTINT (w->left);
2220 get_display_line (f, vpos, XFASTINT (w->left));
2221 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
2223 /* Show where to highlight the region. */
2224 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
2225 /* Maybe highlight only in selected window. */
2226 && (highlight_nonselected_windows
2227 || w == XWINDOW (selected_window)))
2229 region_beg = marker_position (current_buffer->mark);
2230 if (PT < region_beg)
2232 region_end = region_beg;
2233 region_beg = PT;
2235 else
2236 region_end = PT;
2237 w->region_showing = Qt;
2239 else
2240 region_beg = region_end = -1;
2242 if (MINI_WINDOW_P (w)
2243 && start == 1
2244 && vpos == XFASTINT (w->top))
2246 if (! NILP (minibuf_prompt))
2248 minibuf_prompt_width
2249 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2250 XSTRING (minibuf_prompt)->size, hpos,
2251 /* Display a space if we truncate. */
2252 ' ',
2253 1, -1,
2254 /* Truncate the prompt a little before the
2255 margin, so user input can at least start
2256 on the first line. */
2257 w->width > 10 ? w->width - 4 : -1)
2258 - hpos);
2259 hpos += minibuf_prompt_width;
2261 else
2262 minibuf_prompt_width = 0;
2265 end = ZV;
2267 /* If we're hscrolled at all, use compute_motion to skip over any
2268 text off the left edge of the window. compute_motion may know
2269 tricks to do this faster than we can. */
2270 if (hpos < 0)
2272 struct position *left_edge
2273 = compute_motion (pos, vpos, hpos,
2274 end, vpos, 0,
2275 width, hscroll, taboffset, w);
2277 /* Retrieve the buffer position and column provided by
2278 compute_motion. We can't assume that the column will be
2279 zero, because you may have multi-column characters crossing
2280 the left margin.
2282 compute_motion may have moved us past the screen position we
2283 requested, if we hit a multi-column character, or the end of
2284 the line. If so, back up. */
2285 if (left_edge->vpos > vpos
2286 || left_edge->hpos > 0)
2288 pos = left_edge->bufpos - 1;
2289 hpos = left_edge->prevhpos;
2291 else
2293 pos = left_edge->bufpos;
2294 hpos = left_edge->hpos;
2298 desired_glyphs->bufp[vpos] = start;
2299 p1 = desired_glyphs->glyphs[vpos] + hpos;
2300 p1start = p1;
2301 charstart = desired_glyphs->charstarts[vpos] + hpos;
2302 /* In case we don't ever write anything into it... */
2303 desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
2304 leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
2305 endp = leftmargin + width;
2307 /* Arrange the overlays nicely for our purposes. Usually, we call
2308 display_text_line on only one line at a time, in which case this
2309 can't really hurt too much, or we call it on lines which appear
2310 one after another in the buffer, in which case all calls to
2311 recenter_overlay_lists but the first will be pretty cheap. */
2312 recenter_overlay_lists (current_buffer, pos);
2314 /* Loop generating characters.
2315 Stop at end of buffer, before newline,
2316 if reach or pass continuation column,
2317 or at face change. */
2318 pause = pos;
2319 next_face_change = pos;
2320 #ifdef USE_TEXT_PROPERTIES
2321 next_invisible = pos;
2322 #endif
2323 while (1)
2325 /* Record which glyph starts a character,
2326 and the character position of that character. */
2327 if (p1 >= leftmargin)
2328 charstart[p1 - p1start] = pos;
2330 if (p1 >= endp)
2331 break;
2333 p1prev = p1;
2334 if (pos >= pause)
2336 /* Did we hit the end of the visible region of the buffer?
2337 Stop here. */
2338 if (pos >= end)
2339 break;
2341 /* Did we reach point? Record the cursor location. */
2342 if (pos == PT && cursor_vpos < 0)
2344 cursor_vpos = vpos;
2345 cursor_hpos = p1 - leftmargin;
2348 #ifdef USE_TEXT_PROPERTIES
2349 /* if the `invisible' property is set to t, we can skip to
2350 the next property change */
2351 while (pos == next_invisible && pos < end)
2353 Lisp_Object position, limit, endpos, prop, ww;
2354 XSETFASTINT (position, pos);
2355 XSETWINDOW (ww, w);
2356 prop = Fget_char_property (position, Qinvisible, ww);
2357 /* This is just an estimate to give reasonable
2358 performance; nothing should go wrong if it is too small. */
2359 limit = Fnext_overlay_change (position);
2360 if (XFASTINT (limit) > pos + 50)
2361 XSETFASTINT (limit, pos + 50);
2362 endpos = Fnext_single_property_change (position, Qinvisible,
2363 Fcurrent_buffer (), limit);
2364 if (INTEGERP (endpos))
2365 next_invisible = XINT (endpos);
2366 else
2367 next_invisible = end;
2368 if (! NILP (prop))
2370 if (pos < PT && next_invisible >= PT)
2372 cursor_vpos = vpos;
2373 cursor_hpos = p1 - leftmargin;
2375 pos = next_invisible;
2378 if (pos >= end)
2379 break;
2380 #endif
2382 #ifdef HAVE_FACES
2383 /* Did we hit a face change? Figure out what face we should
2384 use now. We also hit this the first time through the
2385 loop, to see what face we should start with. */
2386 if (pos >= next_face_change && FRAME_X_P (f))
2387 current_face = compute_char_face (f, w, pos,
2388 region_beg, region_end,
2389 &next_face_change, pos + 50, 0);
2390 #endif
2392 pause = end;
2394 #ifdef USE_TEXT_PROPERTIES
2395 if (pos < next_invisible && next_invisible < pause)
2396 pause = next_invisible;
2397 #endif
2398 if (pos < next_face_change && next_face_change < pause)
2399 pause = next_face_change;
2401 /* Wouldn't you hate to read the next line to someone over
2402 the phone? */
2403 if (pos < PT && PT < pause)
2404 pause = PT;
2405 if (pos < GPT && GPT < pause)
2406 pause = GPT;
2408 p = &FETCH_CHAR (pos);
2410 c = *p++;
2411 if (c >= 040 && c < 0177
2412 && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
2414 if (p1 >= leftmargin)
2415 *p1 = MAKE_GLYPH (f, c, current_face);
2416 p1++;
2418 else if (c == '\n')
2420 invis = 0;
2421 while (pos + 1 < end
2422 && selective > 0
2423 && indented_beyond_p (pos + 1, selective))
2425 invis = 1;
2426 pos = find_next_newline (pos + 1, 1);
2427 if (FETCH_CHAR (pos - 1) == '\n')
2428 pos--;
2430 if (invis && selective_rlen > 0 && p1 >= leftmargin)
2432 p1 += selective_rlen;
2433 if (p1 - leftmargin > width)
2434 p1 = endp;
2435 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2436 (p1 - p1prev), current_face);
2438 #ifdef HAVE_FACES
2439 /* Draw the face of the newline character as extending all the
2440 way to the end of the frame line. */
2441 if (current_face)
2443 if (p1 < leftmargin)
2444 p1 = leftmargin;
2445 while (p1 < endp)
2446 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2448 #endif
2449 break;
2451 else if (c == '\t')
2455 if (p1 >= leftmargin && p1 < endp)
2456 *p1 = MAKE_GLYPH (f, ' ', current_face);
2457 p1++;
2459 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
2460 % tab_width);
2462 else if (c == Ctl ('M') && selective == -1)
2464 pos = find_next_newline (pos, 1);
2465 if (FETCH_CHAR (pos - 1) == '\n')
2466 pos--;
2467 if (selective_rlen > 0)
2469 p1 += selective_rlen;
2470 if (p1 - leftmargin > width)
2471 p1 = endp;
2472 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2473 (p1 - p1prev), current_face);
2475 #ifdef HAVE_FACES
2476 /* Draw the face of the newline character as extending all the
2477 way to the end of the frame line. */
2478 if (current_face)
2480 if (p1 < leftmargin)
2481 p1 = leftmargin;
2482 while (p1 < endp)
2483 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2485 #endif
2486 break;
2488 else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
2490 p1 = copy_part_of_rope (f, p1, leftmargin,
2491 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
2492 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
2493 current_face);
2495 else if (c < 0200 && ctl_arrow)
2497 if (p1 >= leftmargin)
2498 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
2499 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
2500 current_face);
2501 p1++;
2502 if (p1 >= leftmargin && p1 < endp)
2503 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
2504 p1++;
2506 else
2508 if (p1 >= leftmargin)
2509 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
2510 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
2511 current_face);
2512 p1++;
2513 if (p1 >= leftmargin && p1 < endp)
2514 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
2515 p1++;
2516 if (p1 >= leftmargin && p1 < endp)
2517 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
2518 p1++;
2519 if (p1 >= leftmargin && p1 < endp)
2520 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
2521 p1++;
2524 /* Do nothing here for a char that's entirely off the left edge. */
2525 if (p1 >= leftmargin)
2527 /* For all the glyphs occupied by this character, except for the
2528 first, store -1 in charstarts. */
2529 if (p1 != p1prev)
2531 int *p2x = &charstart[p1prev - p1start];
2532 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2534 /* The window's left column should always
2535 contain a character position.
2536 And don't clobber anything to the left of that. */
2537 if (p1prev < leftmargin)
2539 p2x = charstart + (leftmargin - p1start);
2540 *p2x = pos;
2543 /* This loop skips over the char p2x initially points to. */
2544 while (++p2x < p2)
2545 *p2x = -1;
2549 pos++;
2552 val.hpos = - XINT (w->hscroll);
2553 if (val.hpos)
2554 val.hpos++;
2556 val.vpos = 1;
2558 lastpos = pos;
2560 /* Store 0 in this charstart line for the positions where
2561 there is no character. But do leave what was recorded
2562 for the character that ended the line. */
2563 /* Add 1 in the endtest to compensate for the fact that ENDP was
2564 made from WIDTH, which is 1 less than the window's actual
2565 internal width. */
2566 i = p1 - p1start + 1;
2567 if (p1 < leftmargin)
2568 i += leftmargin - p1;
2569 for (; i < endp - p1start + 1; i++)
2570 charstart[i] = 0;
2572 /* Handle continuation in middle of a character */
2573 /* by backing up over it */
2574 if (p1 > endp)
2576 /* Don't back up if we never actually displayed any text.
2577 This occurs when the minibuffer prompt takes up the whole line. */
2578 if (p1prev)
2580 /* Start the next line with that same character */
2581 pos--;
2582 /* but at negative hpos, to skip the columns output on this line. */
2583 val.hpos += p1prev - endp;
2586 /* Keep in this line everything up to the continuation column. */
2587 p1 = endp;
2590 /* Finish deciding which character to start the next line on,
2591 and what hpos to start it at.
2592 Also set `lastpos' to the last position which counts as "on this line"
2593 for cursor-positioning. */
2595 if (pos < ZV)
2597 if (FETCH_CHAR (pos) == '\n')
2599 /* If stopped due to a newline, start next line after it */
2600 pos++;
2601 /* Check again for hidden lines, in case the newline occurred exactly
2602 at the right margin. */
2603 while (pos < ZV && selective > 0
2604 && indented_beyond_p (pos, selective))
2605 pos = find_next_newline (pos, 1);
2607 else
2608 /* Stopped due to right margin of window */
2610 if (truncate)
2612 *p1++ = fix_glyph (f, truncator, 0);
2613 /* Truncating => start next line after next newline,
2614 and point is on this line if it is before the newline,
2615 and skip none of first char of next line */
2617 pos = find_next_newline (pos, 1);
2618 while (pos < ZV && selective > 0
2619 && indented_beyond_p (pos, selective));
2620 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
2622 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
2624 else
2626 *p1++ = fix_glyph (f, continuer, 0);
2627 val.vpos = 0;
2628 lastpos--;
2633 /* If point is at eol or in invisible text at eol,
2634 record its frame location now. */
2636 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
2638 cursor_vpos = vpos;
2639 cursor_hpos = p1 - leftmargin;
2642 if (cursor_vpos == vpos)
2644 if (cursor_hpos < 0) cursor_hpos = 0;
2645 if (cursor_hpos > width) cursor_hpos = width;
2646 cursor_hpos += XFASTINT (w->left);
2647 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
2649 FRAME_CURSOR_Y (f) = cursor_vpos;
2650 FRAME_CURSOR_X (f) = cursor_hpos;
2652 if (w == XWINDOW (selected_window))
2654 /* Line is not continued and did not start
2655 in middle of character */
2656 if ((hpos - XFASTINT (w->left)
2657 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
2658 && val.vpos)
2660 this_line_bufpos = start;
2661 this_line_buffer = current_buffer;
2662 this_line_vpos = cursor_vpos;
2663 this_line_start_hpos = hpos;
2664 this_line_endpos = Z - lastpos;
2666 else
2667 this_line_bufpos = 0;
2672 /* If hscroll and line not empty, insert truncation-at-left marker */
2673 if (hscroll && lastpos != start)
2675 *leftmargin = fix_glyph (f, truncator, 0);
2676 if (p1 <= leftmargin)
2677 p1 = leftmargin + 1;
2680 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f))
2682 endp++;
2683 if (p1 < leftmargin) p1 = leftmargin;
2684 while (p1 < endp) *p1++ = SPACEGLYPH;
2686 /* Don't draw vertical bars if we're using scroll bars. They're
2687 covered up by the scroll bars, and it's distracting to see
2688 them when the scroll bar windows are flickering around to be
2689 reconfigured. */
2690 *p1++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2691 ? ' '
2692 : (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
2693 ? DISP_BORDER_GLYPH (dp)
2694 : '|'));
2696 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
2697 p1 - desired_glyphs->glyphs[vpos]);
2698 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
2700 /* If the start of this line is the overlay arrow-position,
2701 then put the arrow string into the display-line. */
2703 if (MARKERP (Voverlay_arrow_position)
2704 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
2705 && start == marker_position (Voverlay_arrow_position)
2706 && STRINGP (Voverlay_arrow_string)
2707 && ! overlay_arrow_seen)
2709 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
2710 int i;
2711 int len = XSTRING (Voverlay_arrow_string)->size;
2712 int arrow_end;
2714 if (len > width)
2715 len = width;
2716 #ifdef HAVE_FACES
2717 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
2719 /* If the arrow string has text props, obey them when displaying. */
2720 for (i = 0; i < len; i++)
2722 int c = p[i];
2723 Lisp_Object face, ilisp;
2724 int newface;
2726 XSETFASTINT (ilisp, i);
2727 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
2728 newface = compute_glyph_face_1 (f, face, 0);
2729 leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
2732 else
2733 #endif /* HAVE_FACES */
2735 for (i = 0; i < len; i++)
2736 leftmargin[i] = p[i];
2739 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
2740 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
2741 if (desired_glyphs->used[vpos] < arrow_end)
2742 desired_glyphs->used[vpos] = arrow_end;
2744 overlay_arrow_seen = 1;
2747 val.bufpos = pos;
2748 val_display_text_line = val;
2749 return &val_display_text_line;
2752 /* Redisplay the menu bar in the frame for window W. */
2754 static void
2755 display_menu_bar (w)
2756 struct window *w;
2758 Lisp_Object items, tail;
2759 register int vpos = 0;
2760 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2761 int maxendcol = FRAME_WIDTH (f);
2762 int hpos = 0;
2763 int i;
2765 #ifndef USE_X_TOOLKIT
2766 if (FRAME_MENU_BAR_LINES (f) <= 0)
2767 return;
2769 get_display_line (f, vpos, 0);
2771 items = FRAME_MENU_BAR_ITEMS (f);
2772 for (i = 0; i < XVECTOR (items)->size; i += 3)
2774 Lisp_Object pos, string;
2775 string = XVECTOR (items)->contents[i + 1];
2776 if (NILP (string))
2777 break;
2779 XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos);
2781 if (hpos < maxendcol)
2782 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
2783 XSTRING (string)->data,
2784 XSTRING (string)->size,
2785 hpos, 0, 0, hpos, maxendcol);
2786 /* Put a gap of 3 spaces between items. */
2787 if (hpos < maxendcol)
2789 int hpos1 = hpos + 3;
2790 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
2791 min (hpos1, maxendcol), maxendcol);
2795 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
2796 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2798 /* Fill out the line with spaces. */
2799 if (maxendcol > hpos)
2800 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
2802 /* Clear the rest of the lines allocated to the menu bar. */
2803 vpos++;
2804 while (vpos < FRAME_MENU_BAR_LINES (f))
2805 get_display_line (f, vpos++, 0);
2806 #endif /* not USE_X_TOOLKIT */
2809 /* Display the mode line for window w */
2811 static void
2812 display_mode_line (w)
2813 struct window *w;
2815 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
2816 register int left = XFASTINT (w->left);
2817 register int right = XFASTINT (w->width) + left;
2818 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2820 line_number_displayed = 0;
2821 w->column_number_displayed = Qnil;
2823 get_display_line (f, vpos, left);
2824 display_mode_element (w, vpos, left, 0, right, right,
2825 current_buffer->mode_line_format);
2826 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
2828 /* Make the mode line inverse video if the entire line
2829 is made of mode lines.
2830 I.e. if this window is full width,
2831 or if it is the child of a full width window
2832 (which implies that that window is split side-by-side
2833 and the rest of this line is mode lines of the sibling windows). */
2834 if (XFASTINT (w->width) == FRAME_WIDTH (f)
2835 || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
2836 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2837 #ifdef HAVE_FACES
2838 else if (! FRAME_TERMCAP_P (f))
2840 /* For a partial width window, explicitly set face of each glyph. */
2841 int i;
2842 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
2843 for (i = left; i < right; ++i)
2844 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
2846 #endif
2849 /* Contribute ELT to the mode line for window W.
2850 How it translates into text depends on its data type.
2852 VPOS is the position of the mode line being displayed.
2854 HPOS is the position (absolute on frame) where this element's text
2855 should start. The output is truncated automatically at the right
2856 edge of window W.
2858 DEPTH is the depth in recursion. It is used to prevent
2859 infinite recursion here.
2861 MINENDCOL is the hpos before which the element may not end.
2862 The element is padded at the right with spaces if nec
2863 to reach this column.
2865 MAXENDCOL is the hpos past which this element may not extend.
2866 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
2867 (This is necessary to make nested padding and truncation work.)
2869 Returns the hpos of the end of the text generated by ELT.
2870 The next element will receive that value as its HPOS arg,
2871 so as to concatenate the elements. */
2873 static int
2874 display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2875 struct window *w;
2876 register int vpos, hpos;
2877 int depth;
2878 int minendcol;
2879 register int maxendcol;
2880 register Lisp_Object elt;
2882 tail_recurse:
2883 if (depth > 10)
2884 goto invalid;
2886 depth++;
2888 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
2890 case Lisp_String:
2892 /* A string: output it and check for %-constructs within it. */
2893 register unsigned char c;
2894 register unsigned char *this = XSTRING (elt)->data;
2896 while (hpos < maxendcol && *this)
2898 unsigned char *last = this;
2899 while ((c = *this++) != '\0' && c != '%')
2901 if (this - 1 != last)
2903 register int lim = --this - last + hpos;
2904 if (frame_title_ptr)
2905 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
2906 else
2907 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
2908 hpos, min (lim, maxendcol));
2910 else /* c == '%' */
2912 register int spec_width = 0;
2914 /* We can't allow -ve args due to the "%-" construct */
2915 /* Argument specifies minwidth but not maxwidth
2916 (maxwidth can be specified by
2917 (<negative-number> . <stuff>) mode-line elements) */
2919 while ((c = *this++) >= '0' && c <= '9')
2921 spec_width = spec_width * 10 + (c - '0');
2924 spec_width += hpos;
2925 if (spec_width > maxendcol)
2926 spec_width = maxendcol;
2928 if (c == 'M')
2929 hpos = display_mode_element (w, vpos, hpos, depth,
2930 spec_width, maxendcol,
2931 Vglobal_mode_string);
2932 else if (c != 0)
2934 char *spec = decode_mode_spec (w, c, maxendcol - hpos);
2935 if (frame_title_ptr)
2936 hpos = store_frame_title (spec, spec_width, maxendcol);
2937 else
2938 hpos = display_string (w, vpos, spec, -1,
2939 hpos, 0, 1,
2940 spec_width, maxendcol);
2945 break;
2947 case Lisp_Symbol:
2948 /* A symbol: process the value of the symbol recursively
2949 as if it appeared here directly. Avoid error if symbol void.
2950 Special case: if value of symbol is a string, output the string
2951 literally. */
2953 register Lisp_Object tem;
2954 tem = Fboundp (elt);
2955 if (!NILP (tem))
2957 tem = Fsymbol_value (elt);
2958 /* If value is a string, output that string literally:
2959 don't check for % within it. */
2960 if (STRINGP (tem))
2962 if (frame_title_ptr)
2963 hpos = store_frame_title (XSTRING (tem)->data,
2964 minendcol, maxendcol);
2965 else
2966 hpos = display_string (w, vpos, XSTRING (tem)->data,
2967 XSTRING (tem)->size,
2968 hpos, 0, 1, minendcol, maxendcol);
2970 /* Give up right away for nil or t. */
2971 else if (!EQ (tem, elt))
2972 { elt = tem; goto tail_recurse; }
2975 break;
2977 case Lisp_Cons:
2979 register Lisp_Object car, tem;
2981 /* A cons cell: three distinct cases.
2982 If first element is a string or a cons, process all the elements
2983 and effectively concatenate them.
2984 If first element is a negative number, truncate displaying cdr to
2985 at most that many characters. If positive, pad (with spaces)
2986 to at least that many characters.
2987 If first element is a symbol, process the cadr or caddr recursively
2988 according to whether the symbol's value is non-nil or nil. */
2989 car = XCONS (elt)->car;
2990 if (SYMBOLP (car))
2992 tem = Fboundp (car);
2993 elt = XCONS (elt)->cdr;
2994 if (!CONSP (elt))
2995 goto invalid;
2996 /* elt is now the cdr, and we know it is a cons cell.
2997 Use its car if CAR has a non-nil value. */
2998 if (!NILP (tem))
3000 tem = Fsymbol_value (car);
3001 if (!NILP (tem))
3002 { elt = XCONS (elt)->car; goto tail_recurse; }
3004 /* Symbol's value is nil (or symbol is unbound)
3005 Get the cddr of the original list
3006 and if possible find the caddr and use that. */
3007 elt = XCONS (elt)->cdr;
3008 if (NILP (elt))
3009 break;
3010 else if (!CONSP (elt))
3011 goto invalid;
3012 elt = XCONS (elt)->car;
3013 goto tail_recurse;
3015 else if (INTEGERP (car))
3017 register int lim = XINT (car);
3018 elt = XCONS (elt)->cdr;
3019 if (lim < 0)
3020 /* Negative int means reduce maximum width.
3021 DO NOT change MINENDCOL here!
3022 (20 -10 . foo) should truncate foo to 10 col
3023 and then pad to 20. */
3024 maxendcol = min (maxendcol, hpos - lim);
3025 else if (lim > 0)
3027 /* Padding specified. Don't let it be more than
3028 current maximum. */
3029 lim += hpos;
3030 if (lim > maxendcol)
3031 lim = maxendcol;
3032 /* If that's more padding than already wanted, queue it.
3033 But don't reduce padding already specified even if
3034 that is beyond the current truncation point. */
3035 if (lim > minendcol)
3036 minendcol = lim;
3038 goto tail_recurse;
3040 else if (STRINGP (car) || CONSP (car))
3042 register int limit = 50;
3043 /* LIMIT is to protect against circular lists. */
3044 while (CONSP (elt) && --limit > 0
3045 && hpos < maxendcol)
3047 hpos = display_mode_element (w, vpos, hpos, depth,
3048 hpos, maxendcol,
3049 XCONS (elt)->car);
3050 elt = XCONS (elt)->cdr;
3054 break;
3056 default:
3057 invalid:
3058 if (frame_title_ptr)
3059 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
3060 else
3061 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
3062 minendcol, maxendcol);
3063 return hpos;
3066 if (minendcol > hpos)
3067 if (frame_title_ptr)
3068 hpos = store_frame_title ("", minendcol, maxendcol);
3069 else
3070 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
3071 return hpos;
3074 /* Return a string for the output of a mode line %-spec for window W,
3075 generated by character C and width MAXWIDTH. */
3077 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3079 static char *
3080 decode_mode_spec (w, c, maxwidth)
3081 struct window *w;
3082 register char c;
3083 register int maxwidth;
3085 Lisp_Object obj;
3086 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3087 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
3088 struct buffer *b = XBUFFER (w->buffer);
3090 obj = Qnil;
3091 if (maxwidth > FRAME_WIDTH (f))
3092 maxwidth = FRAME_WIDTH (f);
3094 switch (c)
3096 case 'b':
3097 obj = b->name;
3098 #if 0
3099 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
3101 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
3102 decode_mode_spec_buf[maxwidth - 1] = '\\';
3103 decode_mode_spec_buf[maxwidth] = '\0';
3104 return decode_mode_spec_buf;
3106 #endif
3107 break;
3109 case 'f':
3110 obj = b->filename;
3111 #if 0
3112 if (NILP (obj))
3113 return "[none]";
3114 else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
3116 bcopy ("...", decode_mode_spec_buf, 3);
3117 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
3118 decode_mode_spec_buf + 3, maxwidth - 3);
3119 return decode_mode_spec_buf;
3121 #endif
3122 break;
3124 case 'c':
3126 int col = current_column ();
3127 XSETFASTINT (w->column_number_displayed, col);
3128 sprintf (decode_mode_spec_buf, "%d", col);
3129 return decode_mode_spec_buf;
3132 case 'l':
3134 int startpos = marker_position (w->start);
3135 int line, linepos, topline;
3136 int nlines, junk;
3137 Lisp_Object tem;
3138 int height = XFASTINT (w->height);
3140 /* If we decided that this buffer isn't suitable for line numbers,
3141 don't forget that too fast. */
3142 if (EQ (w->base_line_pos, w->buffer))
3143 return "??";
3145 /* If the buffer is very big, don't waste time. */
3146 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
3148 w->base_line_pos = Qnil;
3149 w->base_line_number = Qnil;
3150 return "??";
3153 if (!NILP (w->base_line_number)
3154 && !NILP (w->base_line_pos)
3155 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
3157 line = XFASTINT (w->base_line_number);
3158 linepos = XFASTINT (w->base_line_pos);
3160 else
3162 line = 1;
3163 linepos = BUF_BEGV (b);
3166 /* Count lines from base line to window start position. */
3167 nlines = display_count_lines (linepos, startpos, startpos, &junk);
3169 topline = nlines + line;
3171 /* Determine a new base line, if the old one is too close
3172 or too far away, or if we did not have one.
3173 "Too close" means it's plausible a scroll-down would
3174 go back past it. */
3175 if (startpos == BUF_BEGV (b))
3177 XSETFASTINT (w->base_line_number, topline);
3178 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
3180 else if (nlines < height + 25 || nlines > height * 3 + 50
3181 || linepos == BUF_BEGV (b))
3183 int limit = BUF_BEGV (b);
3184 int position;
3185 int distance = (height * 2 + 30) * 200;
3187 if (startpos - distance > limit)
3188 limit = startpos - distance;
3190 nlines = display_count_lines (startpos, limit,
3191 -(height * 2 + 30),
3192 &position);
3193 /* If we couldn't find the lines we wanted within
3194 200 chars per line,
3195 give up on line numbers for this window. */
3196 if (position == startpos - distance)
3198 w->base_line_pos = w->buffer;
3199 w->base_line_number = Qnil;
3200 return "??";
3203 XSETFASTINT (w->base_line_number, topline - nlines);
3204 XSETFASTINT (w->base_line_pos, position);
3207 /* Now count lines from the start pos to point. */
3208 nlines = display_count_lines (startpos, PT, PT, &junk);
3210 /* Record that we did display the line number. */
3211 line_number_displayed = 1;
3213 /* Make the string to show. */
3214 sprintf (decode_mode_spec_buf, "%d", topline + nlines);
3215 return decode_mode_spec_buf;
3217 break;
3219 case 'm':
3220 obj = b->mode_name;
3221 break;
3223 case 'n':
3224 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
3225 return " Narrow";
3226 break;
3228 case '*':
3229 if (!NILP (b->read_only))
3230 return "%";
3231 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3232 return "*";
3233 return "-";
3235 case '+':
3236 /* This differs from %* only for a modified read-only buffer. */
3237 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3238 return "*";
3239 if (!NILP (b->read_only))
3240 return "%";
3241 return "-";
3243 case '&':
3244 /* This differs from %* in ignoring read-only-ness. */
3245 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3246 return "*";
3247 return "-";
3249 case 's':
3250 /* status of process */
3251 obj = Fget_buffer_process (w->buffer);
3252 if (NILP (obj))
3253 return "no process";
3254 #ifdef subprocesses
3255 obj = Fsymbol_name (Fprocess_status (obj));
3256 #endif
3257 break;
3259 case 't': /* indicate TEXT or BINARY */
3260 #ifdef MODE_LINE_BINARY_TEXT
3261 return MODE_LINE_BINARY_TEXT (b);
3262 #else
3263 return "T";
3264 #endif
3266 case 'p':
3268 int pos = marker_position (w->start);
3269 int total = BUF_ZV (b) - BUF_BEGV (b);
3271 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
3273 if (pos <= BUF_BEGV (b))
3274 return "All";
3275 else
3276 return "Bottom";
3278 else if (pos <= BUF_BEGV (b))
3279 return "Top";
3280 else
3282 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
3283 /* We can't normally display a 3-digit number,
3284 so get us a 2-digit number that is close. */
3285 if (total == 100)
3286 total = 99;
3287 sprintf (decode_mode_spec_buf, "%2d%%", total);
3288 return decode_mode_spec_buf;
3292 /* Display percentage of size above the bottom of the screen. */
3293 case 'P':
3295 int toppos = marker_position (w->start);
3296 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
3297 int total = BUF_ZV (b) - BUF_BEGV (b);
3299 if (botpos >= BUF_ZV (b))
3301 if (toppos <= BUF_BEGV (b))
3302 return "All";
3303 else
3304 return "Bottom";
3306 else
3308 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
3309 /* We can't normally display a 3-digit number,
3310 so get us a 2-digit number that is close. */
3311 if (total == 100)
3312 total = 99;
3313 if (toppos <= BUF_BEGV (b))
3314 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
3315 else
3316 sprintf (decode_mode_spec_buf, "%2d%%", total);
3317 return decode_mode_spec_buf;
3321 case '%':
3322 return "%";
3324 case '[':
3326 int i;
3327 char *p;
3329 if (command_loop_level > 5)
3330 return "[[[... ";
3331 p = decode_mode_spec_buf;
3332 for (i = 0; i < command_loop_level; i++)
3333 *p++ = '[';
3334 *p = 0;
3335 return decode_mode_spec_buf;
3338 case ']':
3340 int i;
3341 char *p;
3343 if (command_loop_level > 5)
3344 return " ...]]]";
3345 p = decode_mode_spec_buf;
3346 for (i = 0; i < command_loop_level; i++)
3347 *p++ = ']';
3348 *p = 0;
3349 return decode_mode_spec_buf;
3352 case '-':
3354 register char *p;
3355 register int i;
3357 if (maxwidth < sizeof (lots_of_dashes))
3358 return lots_of_dashes;
3359 else
3361 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
3362 *p++ = '-';
3363 *p = '\0';
3365 return decode_mode_spec_buf;
3369 if (STRINGP (obj))
3370 return (char *) XSTRING (obj)->data;
3371 else
3372 return "";
3375 /* Search for COUNT instances of a line boundary, which means either a
3376 newline or (if selective display enabled) a carriage return.
3377 Start at START. If COUNT is negative, search backwards.
3379 If we find COUNT instances, set *SHORTAGE to zero, and return the
3380 position after the COUNTth match. Note that for reverse motion
3381 this is not the same as the usual convention for Emacs motion commands.
3383 If we don't find COUNT instances before reaching the end of the
3384 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3385 the number of line boundaries left unfound, and return the end of the
3386 buffer we bumped up against. */
3388 static int
3389 display_scan_buffer (start, count, shortage)
3390 int *shortage, start;
3391 register int count;
3393 int limit = ((count > 0) ? ZV - 1 : BEGV);
3394 int direction = ((count > 0) ? 1 : -1);
3396 register unsigned char *cursor;
3397 unsigned char *base;
3399 register int ceiling;
3400 register unsigned char *ceiling_addr;
3402 /* If we are not in selective display mode,
3403 check only for newlines. */
3404 if (! (!NILP (current_buffer->selective_display)
3405 && !INTEGERP (current_buffer->selective_display)))
3406 return scan_buffer ('\n', start, 0, count, shortage, 0);
3408 /* The code that follows is like scan_buffer
3409 but checks for either newline or carriage return. */
3411 if (shortage != 0)
3412 *shortage = 0;
3414 if (count > 0)
3415 while (start != limit + 1)
3417 ceiling = BUFFER_CEILING_OF (start);
3418 ceiling = min (limit, ceiling);
3419 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
3420 base = (cursor = &FETCH_CHAR (start));
3421 while (1)
3423 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
3425 if (cursor != ceiling_addr)
3427 if (--count == 0)
3429 immediate_quit = 0;
3430 return (start + cursor - base + 1);
3432 else
3433 if (++cursor == ceiling_addr)
3434 break;
3436 else
3437 break;
3439 start += cursor - base;
3441 else
3443 start--; /* first character we scan */
3444 while (start > limit - 1)
3445 { /* we WILL scan under start */
3446 ceiling = BUFFER_FLOOR_OF (start);
3447 ceiling = max (limit, ceiling);
3448 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
3449 base = (cursor = &FETCH_CHAR (start));
3450 cursor++;
3451 while (1)
3453 while (--cursor != ceiling_addr
3454 && *cursor != '\n' && *cursor != 015)
3456 if (cursor != ceiling_addr)
3458 if (++count == 0)
3460 immediate_quit = 0;
3461 return (start + cursor - base + 1);
3464 else
3465 break;
3467 start += cursor - base;
3471 if (shortage != 0)
3472 *shortage = count * direction;
3473 return (start + ((direction == 1 ? 0 : 1)));
3476 /* Count up to N lines starting from FROM.
3477 But don't go beyond LIMIT.
3478 Return the number of lines thus found (always positive).
3479 Store the position after what was found into *POS_PTR. */
3481 static int
3482 display_count_lines (from, limit, n, pos_ptr)
3483 int from, limit, n;
3484 int *pos_ptr;
3486 int oldbegv = BEGV;
3487 int oldzv = ZV;
3488 int shortage = 0;
3490 if (limit < from)
3491 BEGV = limit;
3492 else
3493 ZV = limit;
3495 *pos_ptr = display_scan_buffer (from, n, &shortage);
3497 ZV = oldzv;
3498 BEGV = oldbegv;
3500 if (n < 0)
3501 /* When scanning backwards, scan_buffer stops *after* the last newline
3502 it finds, but does count it. Compensate for that. */
3503 return - n - shortage - (*pos_ptr != limit);
3504 return n - shortage;
3507 /* Display STRING on one line of window W, starting at HPOS.
3508 Display at position VPOS. Caller should have done get_display_line.
3509 If VPOS == -1, display it as the current frame's title.
3510 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3512 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3514 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3515 MAXCOL is the last column ok to end at. Truncate here.
3516 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3517 Both count from the left edge of the frame, as does HPOS.
3518 The right edge of W is an implicit maximum.
3519 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3521 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3522 at the place where the current window ends in this line
3523 and not display anything beyond there. Otherwise, only MAXCOL
3524 controls where to stop output.
3526 Returns ending hpos. */
3528 static int
3529 display_string (w, vpos, string, length, hpos, truncate,
3530 obey_window_width, mincol, maxcol)
3531 struct window *w;
3532 unsigned char *string;
3533 int length;
3534 int vpos, hpos;
3535 GLYPH truncate;
3536 int obey_window_width;
3537 int mincol, maxcol;
3539 register int c;
3540 register GLYPH *p1;
3541 int hscroll = XINT (w->hscroll);
3542 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
3543 register GLYPH *start;
3544 register GLYPH *end;
3545 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3546 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
3547 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
3548 int window_width = XFASTINT (w->width);
3550 /* Use the standard display table, not the window's display table.
3551 We don't want the mode line in rot13. */
3552 register struct Lisp_Vector *dp = 0;
3553 int i;
3555 if (VECTORP (Vstandard_display_table)
3556 && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
3557 dp = XVECTOR (Vstandard_display_table);
3559 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
3561 p1 = p1start;
3562 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
3564 if (obey_window_width)
3566 end = start + window_width - (truncate != 0);
3568 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f))
3570 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3572 int i;
3574 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
3575 *end-- = ' ';
3577 else
3578 *end-- = '|';
3582 if (! obey_window_width
3583 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
3584 end = desired_glyphs->glyphs[vpos] + maxcol;
3586 /* Store 0 in charstart for these columns. */
3587 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
3588 desired_glyphs->charstarts[vpos][i] = 0;
3590 if (maxcol >= 0 && mincol > maxcol)
3591 mincol = maxcol;
3593 while (p1 < end)
3595 if (length == 0)
3596 break;
3597 c = *string++;
3598 /* Specified length. */
3599 if (length >= 0)
3600 length--;
3601 /* Unspecified length (null-terminated string). */
3602 else if (c == 0)
3603 break;
3605 if (c >= 040 && c < 0177
3606 && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
3608 if (p1 >= start)
3609 *p1 = c;
3610 p1++;
3612 else if (c == '\t')
3616 if (p1 >= start && p1 < end)
3617 *p1 = SPACEGLYPH;
3618 p1++;
3620 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
3622 else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
3624 p1 = copy_part_of_rope (f, p1, start,
3625 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
3626 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
3629 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
3631 if (p1 >= start)
3632 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
3633 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
3635 p1++;
3636 if (p1 >= start && p1 < end)
3637 *p1 = c ^ 0100;
3638 p1++;
3640 else
3642 if (p1 >= start)
3643 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
3644 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
3646 p1++;
3647 if (p1 >= start && p1 < end)
3648 *p1 = (c >> 6) + '0';
3649 p1++;
3650 if (p1 >= start && p1 < end)
3651 *p1 = (7 & (c >> 3)) + '0';
3652 p1++;
3653 if (p1 >= start && p1 < end)
3654 *p1 = (7 & c) + '0';
3655 p1++;
3659 if (c && length > 0)
3661 p1 = end;
3662 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
3664 else if (mincol >= 0)
3666 end = desired_glyphs->glyphs[vpos] + mincol;
3667 while (p1 < end)
3668 *p1++ = SPACEGLYPH;
3672 register int len = p1 - desired_glyphs->glyphs[vpos];
3674 if (len > desired_glyphs->used[vpos])
3675 desired_glyphs->used[vpos] = len;
3676 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3678 return len;
3682 void
3683 syms_of_xdisp ()
3685 staticpro (&Qmenu_bar_update_hook);
3686 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
3688 staticpro (&last_arrow_position);
3689 staticpro (&last_arrow_string);
3690 last_arrow_position = Qnil;
3691 last_arrow_string = Qnil;
3693 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
3694 "String (or mode line construct) included (normally) in `mode-line-format'.");
3695 Vglobal_mode_string = Qnil;
3697 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
3698 "Marker for where to display an arrow on top of the buffer text.\n\
3699 This must be the beginning of a line in order to work.\n\
3700 See also `overlay-arrow-string'.");
3701 Voverlay_arrow_position = Qnil;
3703 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
3704 "String to display as an arrow. See also `overlay-arrow-position'.");
3705 Voverlay_arrow_string = Qnil;
3707 DEFVAR_INT ("scroll-step", &scroll_step,
3708 "*The number of lines to try scrolling a window by when point moves out.\n\
3709 If that fails to bring point back on frame, point is centered instead.\n\
3710 If this is zero, point is always centered after it moves off frame.");
3712 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
3714 DEFVAR_BOOL ("truncate-partial-width-windows",
3715 &truncate_partial_width_windows,
3716 "*Non-nil means truncate lines in all windows less than full frame wide.");
3717 truncate_partial_width_windows = 1;
3719 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
3720 "*Non-nil means use inverse video for the mode line.");
3721 mode_line_inverse_video = 1;
3723 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
3724 "*Maximum buffer size for which line number should be displayed.");
3725 line_number_display_limit = 1000000;
3727 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
3728 "*Non-nil means highlight region even in nonselected windows.");
3729 highlight_nonselected_windows = 1;
3731 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3732 "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\
3733 Not guaranteed to be accurate except while parsing frame-title-format.");
3735 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
3736 "Template for displaying the titlebar of visible frames.\n\
3737 \(Assuming the window manager supports this feature.)\n\
3738 This variable has the same structure as `mode-line-format' (which see),\n\
3739 and is used only on frames for which no explicit name has been set\n\
3740 \(see `modify-frame-parameters').");
3741 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
3742 "Template for displaying the titlebar of an iconified frame.\n\
3743 \(Assuming the window manager supports this feature.)\n\
3744 This variable has the same structure as `mode-line-format' (which see),\n\
3745 and is used only on frames for which no explicit name has been set\n\
3746 \(see `modify-frame-parameters').");
3747 Vicon_title_format
3748 = Vframe_title_format
3749 = Fcons (intern ("multiple-frames"),
3750 Fcons (build_string ("%b"),
3751 Fcons (Fcons (build_string (""),
3752 Fcons (intern ("invocation-name"),
3753 Fcons (build_string ("@"),
3754 Fcons (intern ("system-name"),
3755 Qnil)))),
3756 Qnil)));
3758 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
3759 "Maximum number of lines to keep in the message log buffer.\n\
3760 If nil, disable message logging. If t, log messages but don't truncate\n\
3761 the buffer when it becomes large.");
3762 XSETFASTINT (Vmessage_log_max, 50);
3765 /* initialize the window system */
3766 init_xdisp ()
3768 Lisp_Object root_window;
3769 #ifndef COMPILER_REGISTER_BUG
3770 register
3771 #endif /* COMPILER_REGISTER_BUG */
3772 struct window *mini_w;
3774 this_line_bufpos = 0;
3776 mini_w = XWINDOW (minibuf_window);
3777 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
3779 echo_area_glyphs = 0;
3780 previous_echo_glyphs = 0;
3782 if (!noninteractive)
3784 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
3785 XSETFASTINT (XWINDOW (root_window)->top, 0);
3786 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
3787 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
3788 set_window_height (minibuf_window, 1, 0);
3790 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
3791 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));