(message2_nolog): Don't call fwrite will null string.
[emacs.git] / src / xdisp.c
bloba1fad6a504d130e46d6ea18a297c43281db8abff
1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 1997
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
23 #include <config.h>
24 #include <stdio.h>
25 /*#include <ctype.h>*/
26 #undef NULL
27 #include "lisp.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "termchar.h"
31 #include "dispextern.h"
32 #include "buffer.h"
33 #include "charset.h"
34 #include "indent.h"
35 #include "commands.h"
36 #include "macros.h"
37 #include "disptab.h"
38 #include "termhooks.h"
39 #include "intervals.h"
40 #include "keyboard.h"
41 #include "coding.h"
42 #include "process.h"
44 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
45 extern void set_frame_menubar ();
46 extern int pending_menu_activation;
47 #endif
49 extern int interrupt_input;
50 extern int command_loop_level;
52 extern int minibuffer_auto_raise;
54 extern Lisp_Object Qface;
56 extern Lisp_Object Voverriding_local_map;
57 extern Lisp_Object Voverriding_local_map_menu_flag;
59 Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
60 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
61 Lisp_Object Qredisplay_end_trigger_functions;
63 /* Nonzero means print newline to stdout before next minibuffer message. */
65 int noninteractive_need_newline;
67 /* Nonzero means print newline to message log before next message. */
69 static int message_log_need_newline;
71 #define min(a, b) ((a) < (b) ? (a) : (b))
72 #define max(a, b) ((a) > (b) ? (a) : (b))
73 #define minmax(floor, val, ceil) \
74 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
76 /* The buffer position of the first character appearing
77 entirely or partially on the current frame line.
78 Or zero, which disables the optimization for the current frame line. */
79 static int this_line_bufpos;
81 /* Number of characters past the end of this line,
82 including the terminating newline */
83 static int this_line_endpos;
85 /* The vertical position of this frame line. */
86 static int this_line_vpos;
88 /* Hpos value for start of display on this frame line.
89 Usually zero, but negative if first character really began
90 on previous line */
91 static int this_line_start_hpos;
93 /* Buffer that this_line variables are describing. */
94 static struct buffer *this_line_buffer;
96 /* Value of echo_area_glyphs when it was last acted on.
97 If this is nonzero, there is a message on the frame
98 in the minibuffer and it should be erased as soon
99 as it is no longer requested to appear. */
100 char *previous_echo_glyphs;
102 /* Nonzero means truncate lines in all windows less wide than the frame */
103 int truncate_partial_width_windows;
105 /* Nonzero means we have more than one non-minibuffer-only frame.
106 Not guaranteed to be accurate except while parsing frame-title-format. */
107 int multiple_frames;
109 Lisp_Object Vglobal_mode_string;
111 /* Marker for where to display an arrow on top of the buffer text. */
112 Lisp_Object Voverlay_arrow_position;
114 /* String to display for the arrow. */
115 Lisp_Object Voverlay_arrow_string;
117 /* Like mode-line-format, but for the titlebar on a visible frame. */
118 Lisp_Object Vframe_title_format;
120 /* Like mode-line-format, but for the titlebar on an iconified frame. */
121 Lisp_Object Vicon_title_format;
123 /* List of functions to call when a window's size changes. These
124 functions get one arg, a frame on which one or more windows' sizes
125 have changed. */
126 static Lisp_Object Vwindow_size_change_functions;
128 /* Values of those variables at last redisplay. */
129 static Lisp_Object last_arrow_position, last_arrow_string;
131 Lisp_Object Qmenu_bar_update_hook;
133 /* Nonzero if overlay arrow has been displayed once in this window. */
134 static int overlay_arrow_seen;
136 /* Nonzero if visible end of buffer has already been displayed once
137 in this window. (We need this variable in case there are overlay
138 strings that get displayed there.) */
139 static int zv_strings_seen;
141 /* Nonzero means highlight the region even in nonselected windows. */
142 static int highlight_nonselected_windows;
144 /* If cursor motion alone moves point off frame,
145 Try scrolling this many lines up or down if that will bring it back. */
146 static int scroll_step;
148 /* Non-0 means scroll just far enough to bring point back on the screen,
149 when appropriate. */
150 static int scroll_conservatively;
152 /* Recenter the window whenever point gets within this many lines
153 of the top or bottom of the window. */
154 int scroll_margin;
156 /* Nonzero if try_window_id has made blank lines at window bottom
157 since the last redisplay that paused */
158 static int blank_end_of_window;
160 /* Number of windows showing the buffer of the selected window
161 (or another buffer with the same base buffer).
162 keyboard.c refers to this. */
163 int buffer_shared;
165 /* display_text_line sets these to the frame position (origin 0) of point,
166 whether the window is selected or not.
167 Set one to -1 first to determine whether point was found afterwards. */
169 static int cursor_vpos;
170 static int cursor_hpos;
172 static int debug_end_pos;
174 /* Nonzero means display mode line highlighted */
175 int mode_line_inverse_video;
177 static void redisplay_internal ();
178 static int message_log_check_duplicate ();
179 static void echo_area_display ();
180 void mark_window_display_accurate ();
181 static void redisplay_windows ();
182 static void redisplay_window ();
183 static void update_menu_bar ();
184 static void try_window ();
185 static int try_window_id ();
186 static struct position *display_text_line ();
187 static void display_mode_line ();
188 static int display_mode_element ();
189 static char *decode_mode_spec ();
190 static int display_string ();
191 static void display_menu_bar ();
192 static int display_count_lines ();
194 /* Prompt to display in front of the minibuffer contents */
195 Lisp_Object minibuf_prompt;
197 /* Width in columns of current minibuffer prompt. */
198 int minibuf_prompt_width;
200 /* Message to display instead of minibuffer contents
201 This is what the functions error and message make,
202 and command echoing uses it as well.
203 It overrides the minibuf_prompt as well as the buffer. */
204 char *echo_area_glyphs;
206 /* This is the length of the message in echo_area_glyphs. */
207 int echo_area_glyphs_length;
209 /* This is the window where the echo area message was displayed.
210 It is always a minibuffer window, but it may not be the
211 same window currently active as a minibuffer. */
212 Lisp_Object echo_area_window;
214 /* true iff we should redraw the mode lines on the next redisplay */
215 int update_mode_lines;
217 /* Smallest number of characters before the gap
218 at any time since last redisplay that finished.
219 Valid for current buffer when try_window_id can be called. */
220 int beg_unchanged;
222 /* Smallest number of characters after the gap
223 at any time since last redisplay that finished.
224 Valid for current buffer when try_window_id can be called. */
225 int end_unchanged;
227 /* MODIFF as of last redisplay that finished;
228 if it matches MODIFF, and overlay_unchanged_modified
229 matches OVERLAY_MODIFF, that means beg_unchanged and end_unchanged
230 contain no useful information */
231 int unchanged_modified;
233 /* OVERLAY_MODIFF as of last redisplay that finished. */
234 int overlay_unchanged_modified;
236 /* Nonzero if window sizes or contents have changed
237 since last redisplay that finished */
238 int windows_or_buffers_changed;
240 /* Nonzero after display_mode_line if %l was used
241 and it displayed a line number. */
242 int line_number_displayed;
244 /* Maximum buffer size for which to display line numbers. */
245 static int line_number_display_limit;
247 /* Number of lines to keep in the message log buffer.
248 t means infinite. nil means don't log at all. */
249 Lisp_Object Vmessage_log_max;
251 /* Output a newline in the *Messages* buffer if "needs" one. */
253 void
254 message_log_maybe_newline ()
256 if (message_log_need_newline)
257 message_dolog ("", 0, 1);
261 /* Add a string to the message log, optionally terminated with a newline.
262 This function calls low-level routines in order to bypass text property
263 hooks, etc. which might not be safe to run. */
265 void
266 message_dolog (m, len, nlflag)
267 char *m;
268 int len, nlflag;
270 if (!NILP (Vmessage_log_max))
272 struct buffer *oldbuf;
273 int oldpoint, oldbegv, oldzv;
274 int old_windows_or_buffers_changed = windows_or_buffers_changed;
276 oldbuf = current_buffer;
277 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
278 current_buffer->undo_list = Qt;
279 oldpoint = PT;
280 oldbegv = BEGV;
281 oldzv = ZV;
282 BEGV = BEG;
283 ZV = Z;
284 if (oldpoint == Z)
285 oldpoint += len + nlflag;
286 if (oldzv == Z)
287 oldzv += len + nlflag;
288 TEMP_SET_PT (Z);
289 if (len)
290 insert_1 (m, len, 1, 0);
291 if (nlflag)
293 int this_bol, prev_bol, dup;
294 insert_1 ("\n", 1, 1, 0);
296 this_bol = scan_buffer ('\n', Z, 0, -2, 0, 0);
297 if (this_bol > BEG)
299 prev_bol = scan_buffer ('\n', this_bol, 0, -2, 0, 0);
300 dup = message_log_check_duplicate (prev_bol, this_bol);
301 if (dup)
303 if (oldpoint > prev_bol)
304 oldpoint -= min (this_bol, oldpoint) - prev_bol;
305 if (oldbegv > prev_bol)
306 oldbegv -= min (this_bol, oldbegv) - prev_bol;
307 if (oldzv > prev_bol)
308 oldzv -= min (this_bol, oldzv) - prev_bol;
309 del_range_1 (prev_bol, this_bol, 0);
310 if (dup > 1)
312 char dupstr[40];
313 int duplen;
315 /* If you change this format, don't forget to also
316 change message_log_check_duplicate. */
317 sprintf (dupstr, " [%d times]", dup);
318 duplen = strlen (dupstr);
319 TEMP_SET_PT (Z-1);
320 if (oldpoint == Z)
321 oldpoint += duplen;
322 if (oldzv == Z)
323 oldzv += duplen;
324 insert_1 (dupstr, duplen, 1, 0);
329 if (NATNUMP (Vmessage_log_max))
331 int pos = scan_buffer ('\n', Z, 0,
332 -XFASTINT (Vmessage_log_max) - 1, 0, 0);
333 oldpoint -= min (pos, oldpoint) - BEG;
334 oldbegv -= min (pos, oldbegv) - BEG;
335 oldzv -= min (pos, oldzv) - BEG;
336 del_range_1 (BEG, pos, 0);
339 BEGV = oldbegv;
340 ZV = oldzv;
341 TEMP_SET_PT (oldpoint);
342 set_buffer_internal (oldbuf);
343 windows_or_buffers_changed = old_windows_or_buffers_changed;
344 message_log_need_newline = !nlflag;
348 /* We are at the end of the buffer after just having inserted a newline.
349 (Note: We depend on the fact we won't be crossing the gap.)
350 Check to see if the most recent message looks a lot like the previous one.
351 Return 0 if different, 1 if the new one should just replace it, or a
352 value N > 1 if we should also append " [N times]". */
354 static int
355 message_log_check_duplicate (prev_bol, this_bol)
356 int prev_bol, this_bol;
358 int i;
359 int len = Z - 1 - this_bol;
360 int seen_dots = 0;
361 unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
362 unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
364 for (i = 0; i < len; i++)
366 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
367 && p1[i] != '\n')
368 seen_dots = 1;
369 if (p1[i] != p2[i])
370 return seen_dots;
372 p1 += len;
373 if (*p1 == '\n')
374 return 2;
375 if (*p1++ == ' ' && *p1++ == '[')
377 int n = 0;
378 while (*p1 >= '0' && *p1 <= '9')
379 n = n * 10 + *p1++ - '0';
380 if (strncmp (p1, " times]\n", 8) == 0)
381 return n+1;
383 return 0;
386 /* Display an echo area message M with a specified length of LEN chars.
387 The string may include null characters. If M is 0, clear out any
388 existing message, and let the minibuffer text show through.
390 The buffer M must continue to exist until after the echo area
391 gets cleared or some other message gets displayed there.
393 Do not pass text that is stored in a Lisp string.
394 Do not pass text in a buffer that was alloca'd. */
396 void
397 message2 (m, len)
398 char *m;
399 int len;
401 /* First flush out any partial line written with print. */
402 message_log_maybe_newline ();
403 if (m)
404 message_dolog (m, len, 1);
405 message2_nolog (m, len);
409 /* The non-logging counterpart of message2. */
411 void
412 message2_nolog (m, len)
413 char *m;
414 int len;
416 if (noninteractive)
418 if (noninteractive_need_newline)
419 putc ('\n', stderr);
420 noninteractive_need_newline = 0;
421 if (m)
422 fwrite (m, len, 1, stderr);
423 if (cursor_in_echo_area == 0)
424 fprintf (stderr, "\n");
425 fflush (stderr);
427 /* A null message buffer means that the frame hasn't really been
428 initialized yet. Error messages get reported properly by
429 cmd_error, so this must be just an informative message; toss it. */
430 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
432 Lisp_Object mini_window;
433 FRAME_PTR f;
435 /* Get the frame containing the minibuffer
436 that the selected frame is using. */
437 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
438 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
440 FRAME_SAMPLE_VISIBILITY (f);
441 if (FRAME_VISIBLE_P (selected_frame)
442 && ! FRAME_VISIBLE_P (f))
443 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
445 if (m)
447 echo_area_glyphs = m;
448 echo_area_glyphs_length = len;
450 if (minibuffer_auto_raise)
451 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
453 else
454 echo_area_glyphs = previous_echo_glyphs = 0;
456 do_pending_window_change ();
457 echo_area_display ();
458 update_frame (f, 1, 1);
459 do_pending_window_change ();
460 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
461 (*frame_up_to_date_hook) (f);
465 /* Display a null-terminated echo area message M. If M is 0, clear out any
466 existing message, and let the minibuffer text show through.
468 The buffer M must continue to exist until after the echo area
469 gets cleared or some other message gets displayed there.
471 Do not pass text that is stored in a Lisp string.
472 Do not pass text in a buffer that was alloca'd. */
474 void
475 message1 (m)
476 char *m;
478 message2 (m, (m ? strlen (m) : 0));
481 void
482 message1_nolog (m)
483 char *m;
485 message2_nolog (m, (m ? strlen (m) : 0));
488 /* Truncate what will be displayed in the echo area
489 the next time we display it--but don't redisplay it now. */
491 void
492 truncate_echo_area (len)
493 int len;
495 /* A null message buffer means that the frame hasn't really been
496 initialized yet. Error messages get reported properly by
497 cmd_error, so this must be just an informative message; toss it. */
498 if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
499 echo_area_glyphs_length = len;
502 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
503 zero if being used by message. */
504 int message_buf_print;
506 /* Dump an informative message to the minibuf. If M is 0, clear out
507 any existing message, and let the minibuffer text show through. */
509 /* VARARGS 1 */
510 void
511 message (m, a1, a2, a3)
512 char *m;
513 EMACS_INT a1, a2, a3;
515 if (noninteractive)
517 if (m)
519 if (noninteractive_need_newline)
520 putc ('\n', stderr);
521 noninteractive_need_newline = 0;
522 fprintf (stderr, m, a1, a2, a3);
523 if (cursor_in_echo_area == 0)
524 fprintf (stderr, "\n");
525 fflush (stderr);
528 else if (INTERACTIVE)
530 /* The frame whose minibuffer we're going to display the message on.
531 It may be larger than the selected frame, so we need
532 to use its buffer, not the selected frame's buffer. */
533 Lisp_Object mini_window;
534 FRAME_PTR f;
536 /* Get the frame containing the minibuffer
537 that the selected frame is using. */
538 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
539 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
541 /* A null message buffer means that the frame hasn't really been
542 initialized yet. Error messages get reported properly by
543 cmd_error, so this must be just an informative message; toss it. */
544 if (FRAME_MESSAGE_BUF (f))
546 if (m)
548 int len;
549 #ifdef NO_ARG_ARRAY
550 EMACS_INT a[3];
551 a[0] = a1;
552 a[1] = a2;
553 a[2] = a3;
555 len = doprnt (FRAME_MESSAGE_BUF (f),
556 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
557 #else
558 len = doprnt (FRAME_MESSAGE_BUF (f),
559 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, &a1);
560 #endif /* NO_ARG_ARRAY */
562 message2 (FRAME_MESSAGE_BUF (f), len);
564 else
565 message1 (0);
567 /* Print should start at the beginning of the message
568 buffer next time. */
569 message_buf_print = 0;
574 /* The non-logging version of message. */
575 void
576 message_nolog (m, a1, a2, a3)
577 char *m;
578 EMACS_INT a1, a2, a3;
580 Lisp_Object old_log_max;
581 old_log_max = Vmessage_log_max;
582 Vmessage_log_max = Qnil;
583 message (m, a1, a2, a3);
584 Vmessage_log_max = old_log_max;
587 void
588 update_echo_area ()
590 message2 (echo_area_glyphs, echo_area_glyphs_length);
593 static void
594 echo_area_display ()
596 register int vpos;
597 FRAME_PTR f;
598 Lisp_Object mini_window;
600 /* Choose the minibuffer window for this display.
601 It is the minibuffer window used by the selected frame. */
602 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
603 /* This is the frame that window is in. */
604 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
606 if (! FRAME_VISIBLE_P (f))
607 return;
609 if (frame_garbaged)
611 redraw_garbaged_frames ();
612 frame_garbaged = 0;
615 if (echo_area_glyphs || minibuf_level == 0)
617 int i;
619 echo_area_window = mini_window;
621 vpos = XFASTINT (XWINDOW (mini_window)->top);
622 get_display_line (f, vpos, 0);
624 /* Make sure the columns that overlap a left-hand scroll bar
625 are always clear. */
626 for (i = 0; i < FRAME_LEFT_SCROLL_BAR_WIDTH (f); i++)
627 f->desired_glyphs->glyphs[vpos][i] = SPACEGLYPH;
629 display_string (XWINDOW (mini_window), vpos,
630 echo_area_glyphs ? echo_area_glyphs : "",
631 echo_area_glyphs ? echo_area_glyphs_length : -1,
632 FRAME_LEFT_SCROLL_BAR_WIDTH (f),
633 0, 0, 0,
634 FRAME_WIDTH (f) + FRAME_LEFT_SCROLL_BAR_WIDTH (f));
636 #if 0 /* This just gets in the way. update_frame does the job. */
637 /* If desired cursor location is on this line, put it at end of text */
638 if (cursor_in_echo_area)
639 FRAME_CURSOR_Y (f) = vpos;
640 if (FRAME_CURSOR_Y (f) == vpos)
641 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
642 #endif
644 /* Fill the rest of the minibuffer window with blank lines. */
646 int i;
648 for (i = vpos + 1;
649 i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
651 get_display_line (f, i, 0);
652 /* We don't use FRAME_SCROLL_BAR_WIDTH (f) as the starting
653 hpos, because it is good to clear whatever is behind the
654 scroll bar. This does not affect the scroll bar itself. */
655 display_string (XWINDOW (mini_window), i,
656 "", 0,
657 0, 0, 0,
658 0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f));
662 else if (!EQ (mini_window, selected_window))
663 windows_or_buffers_changed++;
665 if (EQ (mini_window, selected_window))
666 this_line_bufpos = 0;
668 previous_echo_glyphs = echo_area_glyphs;
671 /* Update frame titles. */
673 #ifdef HAVE_WINDOW_SYSTEM
674 static char frame_title_buf[512];
675 static char *frame_title_ptr;
677 static int
678 store_frame_title (str, mincol, maxcol)
679 char *str;
680 int mincol, maxcol;
682 char *limit;
683 if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
684 maxcol = sizeof (frame_title_buf);
685 limit = &frame_title_buf[maxcol];
686 while (*str != '\0' && frame_title_ptr < limit)
687 *frame_title_ptr++ = *str++;
688 while (frame_title_ptr < &frame_title_buf[mincol])
689 *frame_title_ptr++ = ' ';
690 return frame_title_ptr - frame_title_buf;
693 static void
694 x_consider_frame_title (frame)
695 Lisp_Object frame;
697 Lisp_Object fmt;
698 struct buffer *obuf;
699 int len;
700 FRAME_PTR f = XFRAME (frame);
702 if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
703 return;
705 /* Do we have more than one visible frame on this X display? */
707 Lisp_Object tail;
709 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
711 FRAME_PTR tf = XFRAME (XCONS (tail)->car);
713 if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
714 && !FRAME_MINIBUF_ONLY_P (tf)
715 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
716 break;
719 multiple_frames = CONSP (tail);
722 obuf = current_buffer;
723 Fset_buffer (XWINDOW (f->selected_window)->buffer);
724 fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
725 frame_title_ptr = frame_title_buf;
726 len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
727 0, sizeof (frame_title_buf), fmt);
728 frame_title_ptr = 0;
729 set_buffer_internal (obuf);
730 /* Set the name only if it's changed. This avoids consing
731 in the common case where it hasn't. (If it turns out that we've
732 already wasted too much time by walking through the list with
733 display_mode_element, then we might need to optimize at a higher
734 level than this.) */
735 if (! STRINGP (f->name) || XSTRING (f->name)->size != len
736 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
737 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
739 #else
740 #define frame_title_ptr ((char *)0)
741 #define store_frame_title(str, mincol, maxcol) 0
742 #endif
744 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
745 This can call eval. */
747 void
748 prepare_menu_bars ()
750 register struct window *w = XWINDOW (selected_window);
751 int all_windows;
752 struct gcpro gcpro1, gcpro2;
754 all_windows = (update_mode_lines || buffer_shared > 1
755 || windows_or_buffers_changed);
757 /* Update all frame titles based on their buffer names, etc.
758 We do this before the menu bars so that the buffer-menu
759 will show the up-to-date frame titles.
761 This used to be done after the menu bars, for a reason that
762 was stated as follows but which I do not understand:
763 "We do this after the menu bars so that the frame will first
764 create its menu bar using the name `emacs' if no other name
765 has yet been specified."
766 I think that is no longer a concern. */
767 #ifdef HAVE_WINDOW_SYSTEM
768 if (windows_or_buffers_changed || update_mode_lines)
770 Lisp_Object tail, frame;
772 FOR_EACH_FRAME (tail, frame)
773 if (FRAME_VISIBLE_P (XFRAME (frame))
774 || FRAME_ICONIFIED_P (XFRAME (frame)))
775 x_consider_frame_title (frame);
777 #endif
779 /* Update the menu bar item lists, if appropriate.
780 This has to be done before any actual redisplay
781 or generation of display lines. */
782 if (all_windows)
784 Lisp_Object tail, frame;
785 int count = specpdl_ptr - specpdl;
787 record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
789 FOR_EACH_FRAME (tail, frame)
791 /* If a window on this frame changed size,
792 report that to the user and clear the size-change flag. */
793 if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
795 Lisp_Object functions;
796 /* Clear flag first in case we get error below. */
797 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
798 functions = Vwindow_size_change_functions;
799 GCPRO2 (tail, functions);
800 while (CONSP (functions))
802 call1 (XCONS (functions)->car, frame);
803 functions = XCONS (functions)->cdr;
805 UNGCPRO;
807 GCPRO1 (tail);
808 update_menu_bar (XFRAME (frame), 0);
809 UNGCPRO;
812 unbind_to (count, Qnil);
814 else
815 update_menu_bar (selected_frame, 1);
817 /* Motif needs this. See comment in xmenu.c.
818 Turn it off when pending_menu_activation is not defined. */
819 #ifdef USE_X_TOOLKIT
820 pending_menu_activation = 0;
821 #endif
824 /* Do a frame update, taking possible shortcuts into account.
825 This is the main external entry point for redisplay.
827 If the last redisplay displayed an echo area message and that
828 message is no longer requested, we clear the echo area
829 or bring back the minibuffer if that is in use.
831 Do not call eval from within this function.
832 Calls to eval after the call to echo_area_display would confuse
833 the display_line mechanism and would cause a crash.
834 Calls to eval before that point will work most of the time,
835 but can still lose, because this function
836 can be called from signal handlers; with alarms set up;
837 or with synchronous processes running.
839 See Fcall_process; if you called it from here, it could be
840 entered recursively. */
842 static int do_verify_charstarts;
844 /* Counter is used to clear the face cache
845 no more than once ever 1000 redisplays. */
846 static int clear_face_cache_count;
848 /* Record the previous terminal frame we displayed. */
849 static FRAME_PTR previous_terminal_frame;
851 void
852 redisplay ()
854 redisplay_internal (0);
857 /* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay
858 is not in response to any user action; therefore, we should
859 preserve the echo area. (Actually, our caller does that job.)
860 Perhaps in the future avoid recentering windows
861 if it is not necessary; currently that causes some problems. */
863 static void
864 redisplay_internal (preserve_echo_area)
865 int preserve_echo_area;
867 register struct window *w = XWINDOW (selected_window);
868 register int pause;
869 int must_finish = 0;
870 int all_windows;
871 register int tlbufpos, tlendpos;
872 struct position pos;
873 int number_of_frames_redisplayed;
875 if (noninteractive)
876 return;
878 #ifdef USE_X_TOOLKIT
879 if (popup_activated ())
880 return;
881 #endif
883 retry:
885 if (! FRAME_WINDOW_P (selected_frame)
886 && previous_terminal_frame != selected_frame)
888 /* Since frames on an ASCII terminal share the same display area,
889 displaying a different frame means redisplay the whole thing. */
890 windows_or_buffers_changed++;
891 SET_FRAME_GARBAGED (selected_frame);
892 XSETFRAME (Vterminal_frame, selected_frame);
894 previous_terminal_frame = selected_frame;
896 /* Set the visible flags for all frames.
897 Do this before checking for resized or garbaged frames; they want
898 to know if their frames are visible.
899 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
901 Lisp_Object tail, frame;
903 FOR_EACH_FRAME (tail, frame)
905 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
907 /* Clear out all the display lines in which we will generate the
908 glyphs to display. */
909 init_desired_glyphs (XFRAME (frame));
913 /* Notice any pending interrupt request to change frame size. */
914 do_pending_window_change ();
916 if (frame_garbaged)
918 redraw_garbaged_frames ();
919 frame_garbaged = 0;
922 prepare_menu_bars ();
924 if (windows_or_buffers_changed)
925 update_mode_lines++;
927 /* Detect case that we need to write or remove a star in the mode line. */
928 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
930 w->update_mode_line = Qt;
931 if (buffer_shared > 1)
932 update_mode_lines++;
935 /* If %c is in use, update it if needed. */
936 if (!NILP (w->column_number_displayed)
937 /* This alternative quickly identifies a common case
938 where no change is needed. */
939 && !(PT == XFASTINT (w->last_point)
940 && XFASTINT (w->last_modified) >= MODIFF
941 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
942 && XFASTINT (w->column_number_displayed) != current_column ())
943 w->update_mode_line = Qt;
945 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
947 all_windows = update_mode_lines || buffer_shared > 1;
949 /* If specs for an arrow have changed, do thorough redisplay
950 to ensure we remove any arrow that should no longer exist. */
951 if (! EQ (Voverlay_arrow_position, last_arrow_position)
952 || ! EQ (Voverlay_arrow_string, last_arrow_string))
953 all_windows = 1;
955 /* Normally the message* functions will have already displayed and
956 updated the echo area, but the frame may have been trashed, or
957 the update may have been preempted, so display the echo area
958 again here. */
959 if (echo_area_glyphs || previous_echo_glyphs)
961 echo_area_display ();
962 must_finish = 1;
965 /* If showing region, and mark has changed, must redisplay whole window. */
966 if (((!NILP (Vtransient_mark_mode)
967 && !NILP (XBUFFER (w->buffer)->mark_active))
968 != !NILP (w->region_showing))
969 || (!NILP (w->region_showing)
970 && !EQ (w->region_showing,
971 Fmarker_position (XBUFFER (w->buffer)->mark))))
972 this_line_bufpos = -1;
974 /* This is in case we goto update, below. */
975 number_of_frames_redisplayed = 1;
977 tlbufpos = this_line_bufpos;
978 tlendpos = this_line_endpos;
979 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
980 && !current_buffer->clip_changed
981 && FRAME_VISIBLE_P (XFRAME (w->frame))
982 /* Make sure recorded data applies to current buffer, etc */
983 && this_line_buffer == current_buffer
984 && current_buffer == XBUFFER (w->buffer)
985 && NILP (w->force_start)
986 /* Point must be on the line that we have info recorded about */
987 && PT >= tlbufpos
988 && PT <= Z - tlendpos
989 /* All text outside that line, including its final newline,
990 must be unchanged */
991 && ((XFASTINT (w->last_modified) >= MODIFF
992 && (XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF))
993 || (beg_unchanged >= tlbufpos - 1
994 && GPT >= tlbufpos
995 /* If selective display, can't optimize
996 if the changes start at the beginning of the line. */
997 && ((INTEGERP (current_buffer->selective_display)
998 && XINT (current_buffer->selective_display) > 0
999 ? (beg_unchanged >= tlbufpos
1000 && GPT > tlbufpos)
1001 : 1))
1002 && end_unchanged >= tlendpos
1003 && Z - GPT >= tlendpos)))
1005 if (tlbufpos > BEGV && FETCH_BYTE (tlbufpos - 1) != '\n'
1006 && (tlbufpos == ZV
1007 || FETCH_BYTE (tlbufpos) == '\n'))
1008 /* Former continuation line has disappeared by becoming empty */
1009 goto cancel;
1010 else if (XFASTINT (w->last_modified) < MODIFF
1011 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
1012 || MINI_WINDOW_P (w))
1014 /* We have to handle the case of continuation around a
1015 wide-column character (See the comment in indent.c around
1016 line 885).
1018 For instance, in the following case:
1020 -------- Insert --------
1021 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
1022 J_I_ ==> J_I_ `^^' are cursors.
1023 ^^ ^^
1024 -------- --------
1026 As we have to redraw the line above, we should goto cancel. */
1028 struct position val;
1029 int prevline;
1031 prevline = find_next_newline (tlbufpos, -1);
1032 val = *compute_motion (prevline, 0,
1033 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
1035 tlbufpos,
1036 1 << (BITS_PER_SHORT - 1),
1037 1 << (BITS_PER_SHORT - 1),
1038 window_internal_width (w) - 1,
1039 XINT (w->hscroll), 0, w);
1040 if (val.hpos != this_line_start_hpos)
1041 goto cancel;
1043 cursor_vpos = -1;
1044 overlay_arrow_seen = 0;
1045 zv_strings_seen = 0;
1046 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
1047 pos_tab_offset (w, tlbufpos), 0);
1048 /* If line contains point, is not continued,
1049 and ends at same distance from eob as before, we win */
1050 if (cursor_vpos >= 0 && this_line_bufpos
1051 && this_line_endpos == tlendpos)
1053 /* If this is not the window's last line,
1054 we must adjust the charstarts of the lines below. */
1055 if (this_line_vpos + 1
1056 < XFASTINT (w->top) + window_internal_height (w))
1058 int left = WINDOW_LEFT_MARGIN (w);
1059 int *charstart_next_line
1060 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
1061 int adjust;
1063 if (Z - tlendpos == ZV)
1064 /* This line ends at end of (accessible part of) buffer.
1065 There is no newline to count. */
1066 adjust = Z - tlendpos - charstart_next_line[left];
1067 else
1068 /* This line ends in a newline.
1069 Must take account of the newline and the rest of the
1070 text that follows. */
1071 adjust = Z - tlendpos + 1 - charstart_next_line[left];
1073 adjust_window_charstarts (w, this_line_vpos, adjust);
1076 if (!WINDOW_FULL_WIDTH_P (w))
1077 preserve_other_columns (w);
1078 goto update;
1080 else
1081 goto cancel;
1083 else if (PT == XFASTINT (w->last_point)
1084 /* Make sure the cursor was last displayed
1085 in this window. Otherwise we have to reposition it. */
1086 && XINT (w->top) <= FRAME_CURSOR_Y (selected_frame)
1087 && (XINT (w->top) + XINT (w->height)
1088 > FRAME_CURSOR_Y (selected_frame)))
1090 if (!must_finish)
1092 do_pending_window_change ();
1093 return;
1095 goto update;
1097 /* If highlighting the region, or if the cursor is in the echo area,
1098 then we can't just move the cursor. */
1099 else if (! (!NILP (Vtransient_mark_mode)
1100 && !NILP (current_buffer->mark_active))
1101 && (w == XWINDOW (current_buffer->last_selected_window)
1102 || highlight_nonselected_windows)
1103 && NILP (w->region_showing)
1104 && !cursor_in_echo_area)
1106 pos = *compute_motion (tlbufpos, 0,
1107 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
1109 PT, 2, - (1 << (BITS_PER_SHORT - 1)),
1110 window_internal_width (w) - 1,
1111 XINT (w->hscroll),
1112 pos_tab_offset (w, tlbufpos), w);
1113 if (pos.vpos < 1)
1115 int width = window_internal_width (w) - 1;
1116 FRAME_CURSOR_X (selected_frame)
1117 = WINDOW_LEFT_MARGIN (w) + minmax (0, pos.hpos, width);
1118 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
1119 goto update;
1121 else
1122 goto cancel;
1124 cancel:
1125 /* Text changed drastically or point moved off of line */
1126 cancel_line (this_line_vpos, selected_frame);
1129 this_line_bufpos = 0;
1130 all_windows |= buffer_shared > 1;
1132 clear_face_cache_count++;
1134 if (all_windows)
1136 Lisp_Object tail, frame;
1138 #ifdef HAVE_FACES
1139 /* Clear the face cache, only when we do a full redisplay
1140 and not too often either. */
1141 if (clear_face_cache_count > 1000)
1143 clear_face_cache ();
1144 clear_face_cache_count = 0;
1146 #endif
1148 /* Recompute # windows showing selected buffer.
1149 This will be incremented each time such a window is displayed. */
1150 buffer_shared = 0;
1151 number_of_frames_redisplayed = 0;
1153 FOR_EACH_FRAME (tail, frame)
1155 FRAME_PTR f = XFRAME (frame);
1156 if (FRAME_WINDOW_P (f) || f == selected_frame)
1159 /* Mark all the scroll bars to be removed; we'll redeem the ones
1160 we want when we redisplay their windows. */
1161 if (condemn_scroll_bars_hook)
1162 (*condemn_scroll_bars_hook) (f);
1164 if (FRAME_VISIBLE_P (f))
1166 redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
1167 number_of_frames_redisplayed++;
1170 /* Any scroll bars which redisplay_windows should have nuked
1171 should now go away. */
1172 if (judge_scroll_bars_hook)
1173 (*judge_scroll_bars_hook) (f);
1177 else if (FRAME_VISIBLE_P (selected_frame))
1179 redisplay_window (selected_window, 1, preserve_echo_area);
1180 if (!WINDOW_FULL_WIDTH_P (w))
1181 preserve_other_columns (w);
1182 number_of_frames_redisplayed = 1;
1185 update:
1186 /* Prevent various kinds of signals during display update.
1187 stdio is not robust about handling signals,
1188 which can cause an apparent I/O error. */
1189 if (interrupt_input)
1190 unrequest_sigio ();
1191 stop_polling ();
1193 if (all_windows)
1195 Lisp_Object tail;
1197 pause = 0;
1199 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1201 FRAME_PTR f;
1203 if (!FRAMEP (XCONS (tail)->car))
1204 continue;
1206 f = XFRAME (XCONS (tail)->car);
1208 if ((FRAME_WINDOW_P (f) || f == selected_frame)
1209 && FRAME_VISIBLE_P (f))
1211 pause |= update_frame (f, 0, 0);
1212 if (!pause)
1214 mark_window_display_accurate (f->root_window, 1);
1215 if (frame_up_to_date_hook != 0)
1216 (*frame_up_to_date_hook) (f);
1221 else
1223 if (FRAME_VISIBLE_P (selected_frame))
1224 pause = update_frame (selected_frame, 0, 0);
1225 else
1226 pause = 0;
1228 /* We may have called echo_area_display at the top of this
1229 function. If the echo area is on another frame, that may
1230 have put text on a frame other than the selected one, so the
1231 above call to update_frame would not have caught it. Catch
1232 it here. */
1234 Lisp_Object mini_window;
1235 FRAME_PTR mini_frame;
1237 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
1238 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
1240 if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
1241 pause |= update_frame (mini_frame, 0, 0);
1245 /* If frame does not match, prevent doing single-line-update next time.
1246 Also, don't forget to check every line to update the arrow. */
1247 if (pause)
1249 this_line_bufpos = 0;
1250 if (!NILP (last_arrow_position))
1252 last_arrow_position = Qt;
1253 last_arrow_string = Qt;
1255 /* If we pause after scrolling, some lines in current_frame
1256 may be null, so preserve_other_columns won't be able to
1257 preserve all the vertical-bar separators. So, avoid using it
1258 in that case. */
1259 if (!WINDOW_FULL_WIDTH_P (w))
1260 update_mode_lines = 1;
1263 /* Now text on frame agrees with windows, so
1264 put info into the windows for partial redisplay to follow */
1266 if (!pause)
1268 register struct buffer *b = XBUFFER (w->buffer);
1270 blank_end_of_window = 0;
1271 unchanged_modified = BUF_MODIFF (b);
1272 overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b);
1273 beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
1274 end_unchanged = BUF_Z (b) - BUF_GPT (b);
1276 XSETFASTINT (w->last_point, BUF_PT (b));
1277 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
1278 XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
1280 if (all_windows)
1281 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
1282 else
1284 b->clip_changed = 0;
1285 w->update_mode_line = Qnil;
1286 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
1287 XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
1288 w->last_had_star
1289 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
1290 ? Qt : Qnil);
1292 /* Record if we are showing a region, so can make sure to
1293 update it fully at next redisplay. */
1294 w->region_showing = (!NILP (Vtransient_mark_mode)
1295 && (w == XWINDOW (current_buffer->last_selected_window)
1296 || highlight_nonselected_windows)
1297 && !NILP (XBUFFER (w->buffer)->mark_active)
1298 ? Fmarker_position (XBUFFER (w->buffer)->mark)
1299 : Qnil);
1301 w->window_end_valid = w->buffer;
1302 last_arrow_position = Voverlay_arrow_position;
1303 last_arrow_string = Voverlay_arrow_string;
1304 if (do_verify_charstarts)
1305 verify_charstarts (w);
1306 if (frame_up_to_date_hook != 0)
1307 (*frame_up_to_date_hook) (selected_frame);
1309 update_mode_lines = 0;
1310 windows_or_buffers_changed = 0;
1313 /* Start SIGIO interrupts coming again.
1314 Having them off during the code above
1315 makes it less likely one will discard output,
1316 but not impossible, since there might be stuff
1317 in the system buffer here.
1318 But it is much hairier to try to do anything about that. */
1320 if (interrupt_input)
1321 request_sigio ();
1322 start_polling ();
1324 /* If something has become visible now which was not before,
1325 redisplay again, so that we get them. */
1326 if (!pause)
1328 Lisp_Object tail, frame;
1329 int new_count = 0;
1331 FOR_EACH_FRAME (tail, frame)
1333 int this_is_visible = 0;
1334 if (XFRAME (frame)->visible)
1335 this_is_visible = 1;
1336 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1337 if (XFRAME (frame)->visible)
1338 this_is_visible = 1;
1340 if (this_is_visible)
1341 new_count++;
1344 if (new_count != number_of_frames_redisplayed)
1345 windows_or_buffers_changed++;
1348 /* Change frame size now if a change is pending. */
1349 do_pending_window_change ();
1351 /* If we just did a pending size change, or have additional
1352 visible frames, redisplay again. */
1353 if (windows_or_buffers_changed && !pause)
1354 goto retry;
1357 /* Redisplay, but leave alone any recent echo area message
1358 unless another message has been requested in its place.
1360 This is useful in situations where you need to redisplay but no
1361 user action has occurred, making it inappropriate for the message
1362 area to be cleared. See tracking_off and
1363 wait_reading_process_input for examples of these situations. */
1365 redisplay_preserve_echo_area ()
1367 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
1369 echo_area_glyphs = previous_echo_glyphs;
1370 redisplay_internal (1);
1371 echo_area_glyphs = 0;
1373 else
1374 redisplay_internal (1);
1377 void
1378 mark_window_display_accurate (window, flag)
1379 Lisp_Object window;
1380 int flag;
1382 register struct window *w;
1384 for (;!NILP (window); window = w->next)
1386 if (!WINDOWP (window)) abort ();
1387 w = XWINDOW (window);
1389 if (!NILP (w->buffer))
1391 XSETFASTINT (w->last_modified,
1392 !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
1393 XSETFASTINT (w->last_overlay_modified,
1394 !flag ? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)));
1395 w->last_had_star
1396 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
1397 ? Qt : Qnil);
1399 /* Record if we are showing a region, so can make sure to
1400 update it fully at next redisplay. */
1401 w->region_showing = (!NILP (Vtransient_mark_mode)
1402 && (w == XWINDOW (current_buffer->last_selected_window)
1403 || highlight_nonselected_windows)
1404 && !NILP (XBUFFER (w->buffer)->mark_active)
1405 ? Fmarker_position (XBUFFER (w->buffer)->mark)
1406 : Qnil);
1409 w->window_end_valid = w->buffer;
1410 w->update_mode_line = Qnil;
1411 if (!NILP (w->buffer) && flag)
1412 XBUFFER (w->buffer)->clip_changed = 0;
1414 if (!NILP (w->vchild))
1415 mark_window_display_accurate (w->vchild, flag);
1416 if (!NILP (w->hchild))
1417 mark_window_display_accurate (w->hchild, flag);
1420 if (flag)
1422 last_arrow_position = Voverlay_arrow_position;
1423 last_arrow_string = Voverlay_arrow_string;
1425 else
1427 /* t is unequal to any useful value of Voverlay_arrow_... */
1428 last_arrow_position = Qt;
1429 last_arrow_string = Qt;
1433 /* Update the menu bar item list for frame F.
1434 This has to be done before we start to fill in any display lines,
1435 because it can call eval.
1437 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1439 static void
1440 update_menu_bar (f, save_match_data)
1441 FRAME_PTR f;
1442 int save_match_data;
1444 struct buffer *old = current_buffer;
1445 Lisp_Object window;
1446 register struct window *w;
1448 window = FRAME_SELECTED_WINDOW (f);
1449 w = XWINDOW (window);
1451 if (update_mode_lines)
1452 w->update_mode_line = Qt;
1454 if (FRAME_WINDOW_P (f)
1456 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1457 FRAME_EXTERNAL_MENU_BAR (f)
1458 #else
1459 FRAME_MENU_BAR_LINES (f) > 0
1460 #endif
1461 : FRAME_MENU_BAR_LINES (f) > 0)
1463 /* If the user has switched buffers or windows, we need to
1464 recompute to reflect the new bindings. But we'll
1465 recompute when update_mode_lines is set too; that means
1466 that people can use force-mode-line-update to request
1467 that the menu bar be recomputed. The adverse effect on
1468 the rest of the redisplay algorithm is about the same as
1469 windows_or_buffers_changed anyway. */
1470 if (windows_or_buffers_changed
1471 || !NILP (w->update_mode_line)
1472 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
1473 < BUF_MODIFF (XBUFFER (w->buffer)))
1474 != !NILP (w->last_had_star))
1475 || ((!NILP (Vtransient_mark_mode)
1476 && !NILP (XBUFFER (w->buffer)->mark_active))
1477 != !NILP (w->region_showing)))
1479 struct buffer *prev = current_buffer;
1480 int count = specpdl_ptr - specpdl;
1482 set_buffer_internal_1 (XBUFFER (w->buffer));
1483 if (save_match_data)
1484 record_unwind_protect (Fstore_match_data, Fmatch_data (Qnil, Qnil));
1485 if (NILP (Voverriding_local_map_menu_flag))
1487 specbind (Qoverriding_terminal_local_map, Qnil);
1488 specbind (Qoverriding_local_map, Qnil);
1491 /* Run the Lucid hook. */
1492 call1 (Vrun_hooks, Qactivate_menubar_hook);
1493 /* If it has changed current-menubar from previous value,
1494 really recompute the menubar from the value. */
1495 if (! NILP (Vlucid_menu_bar_dirty_flag))
1496 call0 (Qrecompute_lucid_menubar);
1497 safe_run_hooks (Qmenu_bar_update_hook);
1498 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1499 /* Redisplay the menu bar in case we changed it. */
1500 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1501 if (FRAME_WINDOW_P (f))
1502 set_frame_menubar (f, 0, 0);
1503 else
1504 /* On a terminal screen, the menu bar is an ordinary screen
1505 line, and this makes it get updated. */
1506 w->update_mode_line = Qt;
1507 #else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
1508 /* In the non-toolkit version, the menu bar is an ordinary screen
1509 line, and this makes it get updated. */
1510 w->update_mode_line = Qt;
1511 #endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
1513 unbind_to (count, Qnil);
1514 set_buffer_internal_1 (prev);
1519 int do_id = 1;
1521 /* Redisplay WINDOW and its subwindows and siblings. */
1523 static void
1524 redisplay_windows (window, preserve_echo_area)
1525 Lisp_Object window;
1526 int preserve_echo_area;
1528 for (; !NILP (window); window = XWINDOW (window)->next)
1529 redisplay_window (window, 0, preserve_echo_area);
1532 /* Return value in display table DP (Lisp_Char_Table *) for character
1533 C. Since a display table doesn't have any parent, we don't have to
1534 follow parent. Do not call this function directly but use the
1535 macro DISP_CHAR_VECTOR. */
1536 Lisp_Object
1537 disp_char_vector (dp, c)
1538 struct Lisp_Char_Table *dp;
1539 int c;
1541 int code[4], i;
1542 Lisp_Object val;
1544 if (SINGLE_BYTE_CHAR_P (c)) return (dp->contents[c]);
1546 SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
1547 if (code[0] != CHARSET_COMPOSITION)
1549 if (code[1] < 32) code[1] = -1;
1550 else if (code[2] < 32) code[2] = -1;
1552 /* Here, the possible range of CODE[0] (== charset ID) is
1553 128..MAX_CHARSET. Since the top level char table contains data
1554 for multibyte characters after 256th element, we must increment
1555 CODE[0] by 128 to get a correct index. */
1556 code[0] += 128;
1557 code[3] = -1; /* anchor */
1559 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
1561 val = dp->contents[code[i]];
1562 if (!SUB_CHAR_TABLE_P (val))
1563 return (NILP (val) ? dp->defalt : val);
1565 /* Here, VAL is a sub char table. We return the default value of it. */
1566 return (dp->defalt);
1569 /* Redisplay window WINDOW and its subwindows. */
1571 static void
1572 redisplay_window (window, just_this_one, preserve_echo_area)
1573 Lisp_Object window;
1574 int just_this_one, preserve_echo_area;
1576 register struct window *w = XWINDOW (window);
1577 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1578 int height;
1579 register int lpoint = PT;
1580 struct buffer *old = current_buffer;
1581 register int width = window_internal_width (w) - 1;
1582 register int startp;
1583 register int hscroll = XINT (w->hscroll);
1584 struct position pos;
1585 int opoint = PT;
1586 int tem;
1587 int update_mode_line;
1588 struct Lisp_Char_Table *dp = window_display_table (w);
1590 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1592 /* If this is a combination window, do its children; that's all. */
1594 if (!NILP (w->vchild))
1596 redisplay_windows (w->vchild, preserve_echo_area);
1597 return;
1599 if (!NILP (w->hchild))
1601 redisplay_windows (w->hchild, preserve_echo_area);
1602 return;
1604 if (NILP (w->buffer))
1605 abort ();
1607 height = window_internal_height (w);
1608 update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
1609 if (XBUFFER (w->buffer)->clip_changed)
1610 update_mode_line = 1;
1612 if (MINI_WINDOW_P (w))
1614 if (w == XWINDOW (echo_area_window) && echo_area_glyphs)
1615 /* We've already displayed the echo area glyphs in this window. */
1616 goto finish_scroll_bars;
1617 else if (w != XWINDOW (minibuf_window))
1619 /* This is a minibuffer, but it's not the currently active one,
1620 so clear it. */
1621 int vpos = XFASTINT (w->top);
1622 int i;
1624 for (i = 0; i < height; i++)
1626 get_display_line (f, vpos + i, 0);
1627 display_string (w, vpos + i, "", 0,
1628 FRAME_LEFT_SCROLL_BAR_WIDTH (f),
1629 0, 1, 0, width);
1632 goto finish_scroll_bars;
1636 /* Otherwise set up data on this window; select its buffer and point value */
1638 if (update_mode_line)
1639 set_buffer_internal_1 (XBUFFER (w->buffer));
1640 else
1641 set_buffer_temp (XBUFFER (w->buffer));
1643 opoint = PT;
1645 /* If %c is in mode line, update it if needed. */
1646 if (!NILP (w->column_number_displayed)
1647 /* This alternative quickly identifies a common case
1648 where no change is needed. */
1649 && !(PT == XFASTINT (w->last_point)
1650 && XFASTINT (w->last_modified) >= MODIFF
1651 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
1652 && XFASTINT (w->column_number_displayed) != current_column ())
1653 update_mode_line = 1;
1655 /* Count number of windows showing the selected buffer.
1656 An indirect buffer counts as its base buffer. */
1658 if (!just_this_one)
1660 struct buffer *current_base, *window_base;
1661 current_base = current_buffer;
1662 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
1663 if (current_base->base_buffer)
1664 current_base = current_base->base_buffer;
1665 if (window_base->base_buffer)
1666 window_base = window_base->base_buffer;
1667 if (current_base == window_base)
1668 buffer_shared++;
1671 /* POINT refers normally to the selected window.
1672 For any other window, set up appropriate value. */
1674 if (!EQ (window, selected_window))
1676 int new_pt = marker_position (w->pointm);
1677 if (new_pt < BEGV)
1679 new_pt = BEGV;
1680 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1682 else if (new_pt > (ZV - 1))
1684 new_pt = ZV;
1685 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1687 /* We don't use SET_PT so that the point-motion hooks don't run. */
1688 BUF_PT (current_buffer) = new_pt;
1691 /* If any of the character widths specified in the display table
1692 have changed, invalidate the width run cache. It's true that this
1693 may be a bit late to catch such changes, but the rest of
1694 redisplay goes (non-fatally) haywire when the display table is
1695 changed, so why should we worry about doing any better? */
1696 if (current_buffer->width_run_cache)
1698 struct Lisp_Char_Table *disptab = buffer_display_table ();
1700 if (! disptab_matches_widthtab (disptab,
1701 XVECTOR (current_buffer->width_table)))
1703 invalidate_region_cache (current_buffer,
1704 current_buffer->width_run_cache,
1705 BEG, Z);
1706 recompute_width_table (current_buffer, disptab);
1710 /* If window-start is screwed up, choose a new one. */
1711 if (XMARKER (w->start)->buffer != current_buffer)
1712 goto recenter;
1714 startp = marker_position (w->start);
1716 /* If someone specified a new starting point but did not insist,
1717 check whether it can be used. */
1718 if (!NILP (w->optional_new_start))
1720 w->optional_new_start = Qnil;
1721 /* Check whether this start pos is usable given where point is. */
1723 pos = *compute_motion (startp, 0,
1724 (((EQ (window, minibuf_window)
1725 && startp == BEG)
1726 ? minibuf_prompt_width : 0)
1727 + (hscroll ? 1 - hscroll : 0)),
1729 PT, height,
1730 /* BUG FIX: See the comment of
1731 Fpos_visible_in_window_p (window.c). */
1732 - (1 << (BITS_PER_SHORT - 1)),
1733 width, hscroll, pos_tab_offset (w, startp), w);
1734 /* If PT does fit on the screen, we will use this start pos,
1735 so do so by setting force_start. */
1736 if (pos.bufpos == PT)
1737 w->force_start = Qt;
1740 /* Handle case where place to start displaying has been specified,
1741 unless the specified location is outside the accessible range. */
1742 if (!NILP (w->force_start))
1744 w->force_start = Qnil;
1745 /* Forget any recorded base line for line number display. */
1746 w->base_line_number = Qnil;
1747 /* Redisplay the mode line. Select the buffer properly for that.
1748 Also, run the hook window-scroll-functions
1749 because we have scrolled. */
1750 /* Note, we do this after clearing force_start because
1751 if there's an error, it is better to forget about force_start
1752 than to get into an infinite loop calling the hook functions
1753 and having them get more errors. */
1754 if (!update_mode_line
1755 || ! NILP (Vwindow_scroll_functions))
1757 Lisp_Object temp[3];
1759 set_buffer_temp (old);
1760 set_buffer_internal_1 (XBUFFER (w->buffer));
1761 update_mode_line = 1;
1762 w->update_mode_line = Qt;
1763 if (! NILP (Vwindow_scroll_functions))
1765 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1766 make_number (startp));
1767 startp = marker_position (w->start);
1770 XSETFASTINT (w->last_modified, 0);
1771 XSETFASTINT (w->last_overlay_modified, 0);
1772 if (startp < BEGV) startp = BEGV;
1773 if (startp > ZV) startp = ZV;
1774 try_window (window, startp);
1775 if (cursor_vpos < 0)
1777 /* If point does not appear, move point so it does appear */
1778 pos = *compute_motion (startp, 0,
1779 (((EQ (window, minibuf_window)
1780 && startp == BEG)
1781 ? minibuf_prompt_width : 0)
1782 + (hscroll ? 1 - hscroll : 0)),
1784 ZV, height / 2,
1785 - (1 << (BITS_PER_SHORT - 1)),
1786 width, hscroll, pos_tab_offset (w, startp), w);
1787 BUF_PT (current_buffer) = pos.bufpos;
1788 if (w != XWINDOW (selected_window))
1789 Fset_marker (w->pointm, make_number (PT), Qnil);
1790 else
1792 if (current_buffer == old)
1793 lpoint = PT;
1794 FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
1795 + minmax (0, pos.hpos, width));
1796 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1798 /* If we are highlighting the region,
1799 then we just changed the region, so redisplay to show it. */
1800 if (!NILP (Vtransient_mark_mode)
1801 && !NILP (current_buffer->mark_active))
1803 cancel_my_columns (XWINDOW (window));
1804 try_window (window, startp);
1807 goto done;
1810 /* Handle case where text has not changed, only point,
1811 and it has not moved off the frame. */
1813 /* This code is not used for minibuffer for the sake of
1814 the case of redisplaying to replace an echo area message;
1815 since in that case the minibuffer contents per se are usually unchanged.
1816 This code is of no real use in the minibuffer since
1817 the handling of this_line_bufpos, etc.,
1818 in redisplay handles the same cases. */
1820 if (XFASTINT (w->last_modified) >= MODIFF
1821 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF
1822 && PT >= startp && !current_buffer->clip_changed
1823 && (just_this_one || WINDOW_FULL_WIDTH_P (w))
1824 /* If force-mode-line-update was called, really redisplay;
1825 that's how redisplay is forced after e.g. changing
1826 buffer-invisibility-spec. */
1827 && NILP (w->update_mode_line)
1828 /* Can't use this case if highlighting a region. */
1829 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1830 && NILP (w->region_showing)
1831 /* If end pos is out of date, scroll bar and percentage will be wrong */
1832 && INTEGERP (w->window_end_vpos)
1833 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
1834 && !EQ (window, minibuf_window))
1836 int this_scroll_margin = scroll_margin;
1838 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
1839 PT, height,
1840 /* BUG FIX: See the comment of
1841 Fpos_visible_in_window_p (window.c). */
1842 - (1 << (BITS_PER_SHORT - 1)),
1843 width, hscroll,
1844 pos_tab_offset (w, startp), w);
1846 /* Don't use a scroll margin that is negative or too large. */
1847 if (this_scroll_margin < 0)
1848 this_scroll_margin = 0;
1850 if (XINT (w->height) < 4 * scroll_margin)
1851 this_scroll_margin = XINT (w->height) / 4;
1853 /* If point fits on the screen, and not within the scroll margin,
1854 we are ok. */
1855 if (pos.vpos < height - this_scroll_margin
1856 && (pos.vpos >= this_scroll_margin || startp == BEGV))
1858 /* Ok, point is still on frame */
1859 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1861 /* These variables are supposed to be origin 1 */
1862 FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
1863 + minmax (0, pos.hpos, width));
1864 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1866 /* This doesn't do the trick, because if a window to the right of
1867 this one must be redisplayed, this does nothing because there
1868 is nothing in DesiredFrame yet, and then the other window is
1869 redisplayed, making likes that are empty in this window's columns.
1870 if (WINDOW_FULL_WIDTH_P (w))
1871 preserve_my_columns (w);
1873 goto done;
1875 /* Don't bother trying redisplay with same start;
1876 we already know it will lose */
1878 /* If current starting point was originally the beginning of a line
1879 but no longer is, find a new starting point. */
1880 else if (!NILP (w->start_at_line_beg)
1881 && !(startp <= BEGV
1882 || FETCH_BYTE (startp - 1) == '\n'))
1884 goto recenter;
1886 else if (just_this_one && !MINI_WINDOW_P (w)
1887 && PT >= startp
1888 && XFASTINT (w->last_modified)
1889 /* or else vmotion on first line won't work. */
1890 && ! NILP (w->start_at_line_beg)
1891 && ! EQ (w->window_end_valid, Qnil)
1892 && do_id && !current_buffer->clip_changed
1893 && !blank_end_of_window
1894 && WINDOW_FULL_WIDTH_P (w)
1895 /* Can't use this case if highlighting a region. */
1896 && !(!NILP (Vtransient_mark_mode)
1897 && !NILP (current_buffer->mark_active))
1898 /* Don't use try_window_id if newline
1899 doesn't display as the end of a line. */
1900 && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
1901 && NILP (w->region_showing)
1902 && EQ (last_arrow_position, Voverlay_arrow_position)
1903 && EQ (last_arrow_string, Voverlay_arrow_string)
1904 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
1905 && tem != -2)
1907 /* tem > 0 means success. tem == -1 means choose new start.
1908 tem == -2 means try again with same start,
1909 and nothing but whitespace follows the changed stuff.
1910 tem == 0 means try again with same start. */
1911 if (tem > 0)
1912 goto done;
1914 else if (startp >= BEGV && startp <= ZV
1915 && (startp < ZV
1916 /* Avoid starting at end of buffer. */
1917 #if 0 /* This change causes trouble for M-! finger & RET.
1918 It will have to be considered later. */
1919 || ! EQ (window, selected_window)
1920 /* Don't do the recentering if redisplay
1921 is not for no user action. */
1922 || preserve_echo_area
1923 #endif
1924 || startp == BEGV
1925 || (XFASTINT (w->last_modified) >= MODIFF
1926 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
1928 /* Try to redisplay starting at same place as before */
1929 /* If point has not moved off frame, accept the results */
1930 try_window (window, startp);
1931 if (cursor_vpos >= 0)
1933 if (!just_this_one || current_buffer->clip_changed
1934 || beg_unchanged < startp)
1935 /* Forget any recorded base line for line number display. */
1936 w->base_line_number = Qnil;
1937 goto done;
1939 else
1940 cancel_my_columns (w);
1943 XSETFASTINT (w->last_modified, 0);
1944 XSETFASTINT (w->last_overlay_modified, 0);
1945 /* Redisplay the mode line. Select the buffer properly for that. */
1946 if (!update_mode_line)
1948 set_buffer_temp (old);
1949 set_buffer_internal_1 (XBUFFER (w->buffer));
1950 update_mode_line = 1;
1951 w->update_mode_line = Qt;
1954 /* Try to scroll by specified few lines */
1956 if (scroll_conservatively && !current_buffer->clip_changed
1957 && startp >= BEGV && startp <= ZV)
1959 int this_scroll_margin = scroll_margin;
1961 /* Don't use a scroll margin that is negative or too large. */
1962 if (this_scroll_margin < 0)
1963 this_scroll_margin = 0;
1965 if (XINT (w->height) < 4 * scroll_margin)
1966 this_scroll_margin = XINT (w->height) / 4;
1968 if (PT >= Z - XFASTINT (w->window_end_pos))
1970 struct position pos;
1971 pos = *compute_motion (Z - XFASTINT (w->window_end_pos), 0, 0, 0,
1972 PT, XFASTINT (w->height), 0,
1973 XFASTINT (w->width), XFASTINT (w->hscroll),
1974 pos_tab_offset (w, startp), w);
1975 if (pos.vpos > scroll_conservatively)
1976 goto scroll_fail_1;
1978 pos = *vmotion (startp, pos.vpos + 1 + this_scroll_margin, w);
1980 if (! NILP (Vwindow_scroll_functions))
1982 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
1983 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1984 make_number (pos.bufpos));
1985 pos.bufpos = marker_position (w->start);
1987 try_window (window, pos.bufpos);
1988 if (cursor_vpos >= 0)
1990 if (!just_this_one || current_buffer->clip_changed
1991 || beg_unchanged < startp)
1992 /* Forget any recorded base line for line number display. */
1993 w->base_line_number = Qnil;
1994 goto done;
1996 else
1997 cancel_my_columns (w);
1999 if (PT < startp)
2001 struct position pos;
2002 pos = *compute_motion (PT, 0, 0, 0,
2003 startp, XFASTINT (w->height), 0,
2004 XFASTINT (w->width), XFASTINT (w->hscroll),
2005 pos_tab_offset (w, startp), w);
2006 if (pos.vpos >= scroll_conservatively)
2007 goto scroll_fail_1;
2009 pos = *vmotion (startp, - pos.vpos - this_scroll_margin, w);
2011 if (! NILP (Vwindow_scroll_functions))
2013 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
2014 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2015 make_number (pos.bufpos));
2016 pos.bufpos = marker_position (w->start);
2018 try_window (window, pos.bufpos);
2019 if (cursor_vpos >= 0)
2021 if (!just_this_one || current_buffer->clip_changed
2022 || beg_unchanged < startp)
2023 /* Forget any recorded base line for line number display. */
2024 w->base_line_number = Qnil;
2025 goto done;
2027 else
2028 cancel_my_columns (w);
2030 scroll_fail_1: ;
2033 if (scroll_step && !current_buffer->clip_changed
2034 && startp >= BEGV && startp <= ZV)
2036 if (PT > startp)
2038 pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
2039 if (pos.vpos >= height)
2040 goto scroll_fail;
2043 pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
2045 if (PT >= pos.bufpos)
2047 if (! NILP (Vwindow_scroll_functions))
2049 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
2050 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2051 make_number (pos.bufpos));
2052 pos.bufpos = marker_position (w->start);
2054 try_window (window, pos.bufpos);
2055 if (cursor_vpos >= 0)
2057 if (!just_this_one || current_buffer->clip_changed
2058 || beg_unchanged < startp)
2059 /* Forget any recorded base line for line number display. */
2060 w->base_line_number = Qnil;
2061 goto done;
2063 else
2064 cancel_my_columns (w);
2066 scroll_fail: ;
2069 /* Finally, just choose place to start which centers point */
2071 recenter:
2072 /* Forget any previously recorded base line for line number display. */
2073 w->base_line_number = Qnil;
2075 pos = *vmotion (PT, - (height / 2), w);
2076 /* Set startp here explicitly in case that helps avoid an infinite loop
2077 in case the window-scroll-functions functions get errors. */
2078 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
2079 if (! NILP (Vwindow_scroll_functions))
2081 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2082 make_number (pos.bufpos));
2083 pos.bufpos = marker_position (w->start);
2085 try_window (window, pos.bufpos);
2087 startp = marker_position (w->start);
2088 w->start_at_line_beg
2089 = (startp == BEGV || FETCH_BYTE (startp - 1) == '\n') ? Qt : Qnil;
2091 done:
2092 if ((update_mode_line
2093 /* If window not full width, must redo its mode line
2094 if the window to its side is being redone */
2095 || (!just_this_one && !WINDOW_FULL_WIDTH_P (w))
2096 || INTEGERP (w->base_line_pos)
2097 || (!NILP (w->column_number_displayed)
2098 && XFASTINT (w->column_number_displayed) != current_column ()))
2099 && height != XFASTINT (w->height))
2100 display_mode_line (w);
2101 if (! line_number_displayed
2102 && ! BUFFERP (w->base_line_pos))
2104 w->base_line_pos = Qnil;
2105 w->base_line_number = Qnil;
2108 /* When we reach a frame's selected window, redo the frame's menu bar. */
2109 if (update_mode_line
2110 && (FRAME_WINDOW_P (f)
2112 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
2113 FRAME_EXTERNAL_MENU_BAR (f)
2114 #else
2115 FRAME_MENU_BAR_LINES (f) > 0
2116 #endif
2117 : FRAME_MENU_BAR_LINES (f) > 0)
2118 && EQ (FRAME_SELECTED_WINDOW (f), window))
2119 display_menu_bar (w);
2121 finish_scroll_bars:
2122 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2124 int start, end, whole;
2126 /* Calculate the start and end positions for the current window.
2127 At some point, it would be nice to choose between scrollbars
2128 which reflect the whole buffer size, with special markers
2129 indicating narrowing, and scrollbars which reflect only the
2130 visible region.
2132 Note that minibuffers sometimes aren't displaying any text. */
2133 if (! MINI_WINDOW_P (w)
2134 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
2136 whole = ZV - BEGV;
2137 start = marker_position (w->start) - BEGV;
2138 /* I don't think this is guaranteed to be right. For the
2139 moment, we'll pretend it is. */
2140 end = (Z - XINT (w->window_end_pos)) - BEGV;
2142 if (end < start) end = start;
2143 if (whole < (end - start)) whole = end - start;
2145 else
2146 start = end = whole = 0;
2148 /* Indicate what this scroll bar ought to be displaying now. */
2149 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
2151 /* Note that we actually used the scroll bar attached to this window,
2152 so it shouldn't be deleted at the end of redisplay. */
2153 (*redeem_scroll_bar_hook) (w);
2156 BUF_PT (current_buffer) = opoint;
2157 if (update_mode_line)
2158 set_buffer_internal_1 (old);
2159 else
2160 set_buffer_temp (old);
2161 BUF_PT (current_buffer) = lpoint;
2164 /* Do full redisplay on one window, starting at position `pos'. */
2166 static void
2167 try_window (window, pos)
2168 Lisp_Object window;
2169 register int pos;
2171 register struct window *w = XWINDOW (window);
2172 register int height = window_internal_height (w);
2173 register int vpos = XFASTINT (w->top);
2174 register int last_text_vpos = vpos;
2175 FRAME_PTR f = XFRAME (w->frame);
2176 int width = window_internal_width (w) - 1;
2177 struct position val;
2179 /* POS should never be out of range! */
2180 if (pos < XBUFFER (w->buffer)->begv
2181 || pos > XBUFFER (w->buffer)->zv)
2182 abort ();
2184 Fset_marker (w->start, make_number (pos), Qnil);
2185 cursor_vpos = -1;
2186 overlay_arrow_seen = 0;
2187 zv_strings_seen = 0;
2188 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
2189 val.ovstring_chars_done = 0;
2190 val.tab_offset = pos_tab_offset (w, pos);
2192 while (--height >= 0)
2194 val = *display_text_line (w, pos, vpos, val.hpos, val.tab_offset,
2195 val.ovstring_chars_done);
2196 /* The following code is omitted because we maintain tab_offset
2197 in VAL. */
2198 #if 0
2199 tab_offset += width;
2200 if (val.vpos) tab_offset = 0;
2201 #endif /* 0 */
2202 vpos++;
2203 if (pos != val.bufpos)
2205 int invis = 0;
2206 #ifdef USE_TEXT_PROPERTIES
2207 Lisp_Object invis_prop;
2208 invis_prop = Fget_char_property (val.bufpos-1, Qinvisible, window);
2209 invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
2210 #endif
2212 last_text_vpos
2213 /* Next line, unless prev line ended in end of buffer with no cr */
2214 = vpos - (val.vpos
2215 && (FETCH_BYTE (val.bufpos - 1) != '\n' || invis));
2217 pos = val.bufpos;
2220 /* If last line is continued in middle of character,
2221 include the split character in the text considered on the frame */
2222 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
2223 pos++;
2225 /* If bottom just moved off end of frame, change mode line percentage. */
2226 if (XFASTINT (w->window_end_pos) == 0
2227 && Z != pos)
2228 w->update_mode_line = Qt;
2230 /* Say where last char on frame will be, once redisplay is finished. */
2231 XSETFASTINT (w->window_end_pos, Z - pos);
2232 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
2233 /* But that is not valid info until redisplay finishes. */
2234 w->window_end_valid = Qnil;
2237 /* Try to redisplay when buffer is modified locally,
2238 computing insert/delete line to preserve text outside
2239 the bounds of the changes.
2240 Return 1 if successful, 0 if if cannot tell what to do,
2241 or -1 to tell caller to find a new window start,
2242 or -2 to tell caller to do normal redisplay with same window start. */
2244 static int
2245 try_window_id (window)
2246 Lisp_Object window;
2248 int pos;
2249 register struct window *w = XWINDOW (window);
2250 register int height = window_internal_height (w);
2251 FRAME_PTR f = XFRAME (w->frame);
2252 int top = XFASTINT (w->top);
2253 int start = marker_position (w->start);
2254 int width = window_internal_width (w) - 1;
2255 int hscroll = XINT (w->hscroll);
2256 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
2257 int did_motion;
2258 register int vpos;
2259 register int i, tem;
2260 int last_text_vpos = 0;
2261 int stop_vpos;
2262 int selective = (INTEGERP (current_buffer->selective_display)
2263 ? XINT (current_buffer->selective_display)
2264 : !NILP (current_buffer->selective_display) ? -1 : 0);
2266 struct position val, bp, ep, xp, pp;
2267 int scroll_amount = 0;
2268 int delta;
2269 int epto, old_tick;
2271 if (GPT - BEG < beg_unchanged)
2272 beg_unchanged = GPT - BEG;
2273 if (Z - GPT < end_unchanged)
2274 end_unchanged = Z - GPT;
2276 if (beg_unchanged + BEG < start)
2277 return 0; /* Give up if changes go above top of window */
2279 /* Find position before which nothing is changed. */
2280 bp = *compute_motion (start, 0, lmargin, 0,
2281 min (ZV, beg_unchanged + BEG), height,
2282 /* BUG FIX: See the comment of
2283 Fpos_visible_in_window_p() (window.c). */
2284 - (1 << (BITS_PER_SHORT - 1)),
2285 width, hscroll, pos_tab_offset (w, start), w);
2286 if (bp.vpos >= height)
2288 if (PT < bp.bufpos)
2290 /* All changes are beyond the window end, and point is on the screen.
2291 We don't need to change the text at all.
2292 But we need to update window_end_pos to account for
2293 any change in buffer size. */
2294 bp = *compute_motion (start, 0, lmargin, 0,
2295 ZV, height,
2296 /* BUG FIX: See the comment of
2297 Fpos_visible_in_window_p() (window.c). */
2298 - (1 << (BITS_PER_SHORT - 1)),
2299 width, hscroll, pos_tab_offset (w, start), w);
2300 XSETFASTINT (w->window_end_vpos, height);
2301 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
2302 goto findpoint;
2304 return 0;
2307 vpos = bp.vpos;
2309 /* Find beginning of that frame line. Must display from there. */
2310 bp = *vmotion (bp.bufpos, 0, w);
2312 pos = bp.bufpos;
2313 val.hpos = lmargin;
2314 if (pos < start)
2315 return -1;
2317 did_motion = 0;
2318 /* If about to start displaying at the beginning of a continuation line,
2319 really start with previous frame line, in case it was not
2320 continued when last redisplayed */
2321 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
2323 /* Likewise if we have to worry about selective display. */
2324 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
2326 bp = *vmotion (bp.bufpos, -1, w);
2327 --vpos;
2328 pos = bp.bufpos;
2330 val.tab_offset = bp.tab_offset; /* Update tab offset. */
2332 if (bp.contin && bp.hpos != lmargin)
2334 val.hpos = bp.prevhpos - width + lmargin;
2335 val.tab_offset = bp.tab_offset + bp.prevhpos - width;
2336 did_motion = 1;
2337 DEC_POS (pos);
2340 bp.vpos = vpos;
2342 /* Find first visible newline after which no more is changed. */
2343 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
2344 if (selective > 0)
2345 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
2346 tem = find_next_newline (tem, 1);
2348 /* Compute the cursor position after that newline. */
2349 ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
2350 height, - (1 << (BITS_PER_SHORT - 1)),
2351 width, hscroll,
2352 /* We have tab offset in VAL, use it. */
2353 val.tab_offset, w);
2355 /* If changes reach past the text available on the frame,
2356 just display rest of frame. */
2357 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
2358 stop_vpos = height;
2359 else
2360 stop_vpos = ep.vpos;
2362 /* If no newline before ep, the line ep is on includes some changes
2363 that must be displayed. Make sure we don't stop before it. */
2364 /* Also, if changes reach all the way until ep.bufpos,
2365 it is possible that something was deleted after the
2366 newline before it, so the following line must be redrawn. */
2367 if (stop_vpos == ep.vpos
2368 && (ep.bufpos == BEGV
2369 || FETCH_BYTE (ep.bufpos - 1) != '\n'
2370 || ep.bufpos == Z - end_unchanged))
2371 stop_vpos = ep.vpos + 1;
2373 cursor_vpos = -1;
2374 overlay_arrow_seen = 0;
2375 zv_strings_seen = 0;
2377 /* If changes do not reach to bottom of window,
2378 figure out how much to scroll the rest of the window */
2379 if (stop_vpos < height)
2381 /* Now determine how far up or down the rest of the window has moved */
2382 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
2383 Z - XFASTINT (w->window_end_pos),
2384 /* Don't care for VPOS... */
2385 1 << (BITS_PER_SHORT - 1),
2386 /* ... nor HPOS. */
2387 1 << (BITS_PER_SHORT - 1),
2388 width, hscroll, ep.tab_offset, w);
2389 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
2391 /* Is everything on frame below the changes whitespace?
2392 If so, no scrolling is really necessary. */
2393 for (i = ep.bufpos; i < xp.bufpos; i++)
2395 tem = FETCH_BYTE (i);
2396 if (tem != ' ' && tem != '\n' && tem != '\t')
2397 break;
2399 if (i == xp.bufpos)
2400 return -2;
2402 XSETFASTINT (w->window_end_vpos,
2403 XFASTINT (w->window_end_vpos) + scroll_amount);
2405 /* Before doing any scrolling, verify that point will be on frame. */
2406 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.vpos < height))
2408 if (PT <= xp.bufpos)
2410 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
2411 PT, height, - (1 << (BITS_PER_SHORT - 1)),
2412 width, hscroll,
2413 /* We have tab offset in EP, use it. */
2414 ep.tab_offset, w);
2416 else
2418 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
2419 PT, height, - (1 << (BITS_PER_SHORT - 1)),
2420 width, hscroll,
2421 /* We have tab offset in XP, use it. */
2422 xp.tab_offset, w);
2424 if (pp.bufpos < PT || pp.vpos == height)
2425 return 0;
2426 cursor_vpos = pp.vpos + top;
2427 cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, pp.hpos, width);
2430 if (stop_vpos - scroll_amount >= height
2431 || ep.bufpos == xp.bufpos)
2433 if (scroll_amount < 0)
2434 stop_vpos -= scroll_amount;
2435 scroll_amount = 0;
2436 /* In this path, we have altered window_end_vpos
2437 and not left it negative.
2438 We must make sure that, in case display is preempted
2439 before the frame changes to reflect what we do here,
2440 further updates will not come to try_window_id
2441 and assume the frame and window_end_vpos match. */
2442 blank_end_of_window = 1;
2444 else if (!scroll_amount)
2446 /* Even if we don't need to scroll, we must adjust the
2447 charstarts of subsequent lines (that we won't redisplay)
2448 according to the amount of text inserted or deleted. */
2449 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2450 int adjust = ep.bufpos - oldpos;
2451 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
2453 else if (bp.bufpos == Z - end_unchanged)
2455 /* If reprinting everything is nearly as fast as scrolling,
2456 don't bother scrolling. Can happen if lines are short. */
2457 if (scroll_cost (f, bp.vpos + top - scroll_amount,
2458 top + height - max (0, scroll_amount),
2459 scroll_amount)
2460 > xp.bufpos - bp.bufpos - 20)
2461 /* Return "try normal display with same window-start."
2462 Too bad we can't prevent further scroll-thinking. */
2463 return -2;
2464 /* If pure deletion, scroll up as many lines as possible.
2465 In common case of killing a line, this can save the
2466 following line from being overwritten by scrolling
2467 and therefore having to be redrawn. */
2468 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
2469 top + height - max (0, scroll_amount),
2470 scroll_amount, bp.bufpos);
2471 if (!tem)
2472 stop_vpos = height;
2473 else
2475 /* scroll_frame_lines did not properly adjust subsequent
2476 lines' charstarts in the case where the text of the
2477 screen line at bp.vpos has changed.
2478 (This can happen in a deletion that ends in mid-line.)
2479 To adjust properly, we need to make things consistent
2480 at the position ep.
2481 So do a second adjust to make that happen.
2482 Note that stop_vpos >= ep.vpos, so it is sufficient
2483 to update the charstarts for lines at ep.vpos and below. */
2484 int oldstart
2485 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2486 adjust_window_charstarts (w, ep.vpos + top - 1,
2487 ep.bufpos - oldstart);
2490 else if (scroll_amount)
2492 /* If reprinting everything is nearly as fast as scrolling,
2493 don't bother scrolling. Can happen if lines are short. */
2494 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2495 overestimate of cost of reprinting, since xp.bufpos
2496 would end up below the bottom of the window. */
2497 if (scroll_cost (f, ep.vpos + top - scroll_amount,
2498 top + height - max (0, scroll_amount),
2499 scroll_amount)
2500 > xp.bufpos - ep.bufpos - 20)
2501 /* Return "try normal display with same window-start."
2502 Too bad we can't prevent further scroll-thinking. */
2503 return -2;
2504 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
2505 top + height - max (0, scroll_amount),
2506 scroll_amount, ep.bufpos);
2507 if (!tem) stop_vpos = height;
2511 /* In any case, do not display past bottom of window */
2512 if (stop_vpos >= height)
2514 stop_vpos = height;
2515 scroll_amount = 0;
2518 /* Handle case where pos is before w->start --
2519 can happen if part of line had been clipped and is not clipped now */
2520 if (vpos == 0 && pos < marker_position (w->start))
2521 Fset_marker (w->start, make_number (pos), Qnil);
2523 /* Redisplay the lines where the text was changed */
2524 last_text_vpos = vpos;
2525 /* The following code is omitted because we maintain tab offset in
2526 val.tab_offset. */
2527 #if 0
2528 tab_offset = pos_tab_offset (w, pos);
2529 /* If we are starting display in mid-character, correct tab_offset
2530 to account for passing the line that that character really starts in. */
2531 if (val.hpos < lmargin)
2532 tab_offset += width;
2533 #endif /* 0 */
2534 old_tick = MODIFF;
2535 while (vpos < stop_vpos)
2537 val = *display_text_line (w, pos, top + vpos++, val.hpos, val.tab_offset,
2538 val.ovstring_chars_done);
2539 /* If display_text_line ran a hook and changed some text,
2540 redisplay all the way to bottom of buffer
2541 So that we show the changes. */
2542 if (old_tick != MODIFF)
2543 stop_vpos = height;
2544 /* The following code is omitted because we maintain tab offset
2545 in val.tab_offset. */
2546 #if 0
2547 tab_offset += width;
2548 if (val.vpos) tab_offset = 0;
2549 #endif
2550 if (pos != val.bufpos)
2551 last_text_vpos
2552 /* Next line, unless prev line ended in end of buffer with no cr */
2553 = vpos - (val.vpos && FETCH_BYTE (val.bufpos - 1) != '\n');
2554 pos = val.bufpos;
2557 /* There are two cases:
2558 1) we have displayed down to the bottom of the window
2559 2) we have scrolled lines below stop_vpos by scroll_amount */
2561 if (vpos == height)
2563 /* If last line is continued in middle of character,
2564 include the split character in the text considered on the frame */
2565 if (val.hpos < lmargin)
2566 val.bufpos++;
2567 XSETFASTINT (w->window_end_vpos, last_text_vpos);
2568 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
2571 /* If scrolling made blank lines at window bottom,
2572 redisplay to fill those lines */
2573 if (scroll_amount < 0)
2575 /* Don't consider these lines for general-purpose scrolling.
2576 That will save time in the scrolling computation. */
2577 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
2578 vpos = xp.vpos;
2579 pos = xp.bufpos;
2580 val.hpos = xp.hpos;
2581 val.tab_offset = xp.tab_offset;
2582 if (pos == ZV)
2583 { /* Display from next line */
2584 vpos = height + scroll_amount;
2585 val.hpos = lmargin;
2586 val.tab_offset = 0;
2588 else if (xp.contin && xp.hpos != lmargin)
2590 val.hpos = xp.prevhpos - width + lmargin;
2591 val.tab_offset = xp.tab_offset + bp.prevhpos - width;
2592 DEC_POS (pos);
2595 blank_end_of_window = 1;
2596 /* The following code is omitted because we maintain tab offset
2597 in val.tab_offset. */
2598 #if 0
2599 tab_offset = pos_tab_offset (w, pos);
2600 /* If we are starting display in mid-character, correct tab_offset
2601 to account for passing the line that that character starts in. */
2602 if (val.hpos < lmargin)
2603 tab_offset += width;
2604 #endif
2605 while (vpos < height)
2607 val = *display_text_line (w, pos, top + vpos++, val.hpos,
2608 val.tab_offset, val.ovstring_chars_done);
2609 /* The following code is omitted because we maintain tab
2610 offset in val.tab_offset. */
2611 #if 0
2612 tab_offset += width;
2613 if (val.vpos) tab_offset = 0;
2614 #endif /* 0 */
2615 pos = val.bufpos;
2618 /* Here is a case where display_text_line sets cursor_vpos wrong.
2619 Make it be fixed up, below. */
2620 if (xp.bufpos == ZV
2621 && xp.bufpos == PT)
2622 cursor_vpos = -1;
2625 /* If bottom just moved off end of frame, change mode line percentage. */
2626 if (XFASTINT (w->window_end_pos) == 0
2627 && Z != val.bufpos)
2628 w->update_mode_line = Qt;
2630 /* Attempt to adjust end-of-text positions to new bottom line */
2631 if (scroll_amount)
2633 delta = height - xp.vpos;
2634 if (delta < 0
2635 || (delta > 0 && xp.bufpos <= ZV)
2636 || (delta == 0 && xp.hpos))
2638 val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
2639 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
2640 XSETFASTINT (w->window_end_vpos,
2641 XFASTINT (w->window_end_vpos) + val.vpos);
2645 w->window_end_valid = Qnil;
2647 /* If point was not in a line that was displayed, find it */
2648 if (cursor_vpos < 0)
2650 findpoint:
2651 val = *compute_motion (start, 0, lmargin, 0, PT,
2652 /* Don't care for VPOS... */
2653 1 << (BITS_PER_SHORT - 1),
2654 /* ... nor HPOS. */
2655 1 << (BITS_PER_SHORT - 1),
2656 width, hscroll, pos_tab_offset (w, start), w);
2657 /* Admit failure if point is off frame now */
2658 if (val.vpos >= height)
2660 for (vpos = 0; vpos < height; vpos++)
2661 cancel_line (vpos + top, f);
2662 return 0;
2664 cursor_vpos = val.vpos + top;
2665 cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width);
2668 FRAME_CURSOR_X (f) = cursor_hpos;
2669 FRAME_CURSOR_Y (f) = cursor_vpos;
2671 if (debug_end_pos)
2673 val = *compute_motion (start, 0, lmargin, 0, ZV,
2674 height, - (1 << (BITS_PER_SHORT - 1)),
2675 width, hscroll, pos_tab_offset (w, start), w);
2676 if (val.vpos != XFASTINT (w->window_end_vpos))
2677 abort ();
2678 if (XFASTINT (w->window_end_pos)
2679 != Z - val.bufpos)
2680 abort ();
2683 return 1;
2686 /* Copy LEN glyphs starting address FROM to the rope TO.
2687 But don't actually copy the parts that would come in before S.
2688 Value is TO, advanced past the copied data.
2689 F is the frame we are displaying in. */
2691 static GLYPH *
2692 copy_part_of_rope (f, to, s, from, len, face)
2693 FRAME_PTR f;
2694 register GLYPH *to; /* Copy to here. */
2695 register GLYPH *s; /* Starting point. */
2696 Lisp_Object *from; /* Data to copy. */
2697 int len;
2698 int face; /* Face to apply to glyphs which don't specify one. */
2700 int n = len;
2701 register Lisp_Object *fp = from;
2702 /* These cache the results of the last call to compute_glyph_face. */
2703 int last_code = -1;
2704 int last_merged = 0;
2706 #ifdef HAVE_FACES
2707 if (! FRAME_TERMCAP_P (f))
2708 while (n--)
2710 GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2711 int facecode;
2712 unsigned int c = FAST_GLYPH_CHAR (glyph);
2714 if (c > MAX_CHAR)
2715 /* For an invalid character code, use space. */
2716 c = ' ';
2718 if (FAST_GLYPH_FACE (glyph) == 0)
2719 /* If GLYPH has no face code, use FACE. */
2720 facecode = face;
2721 else if (FAST_GLYPH_FACE (glyph) == last_code)
2722 /* If it's same as previous glyph, use same result. */
2723 facecode = last_merged;
2724 else
2726 /* Merge this glyph's face and remember the result. */
2727 last_code = FAST_GLYPH_FACE (glyph);
2728 last_merged = facecode = compute_glyph_face (f, last_code, face);
2731 if (to >= s)
2732 *to = FAST_MAKE_GLYPH (c, facecode);
2733 ++to;
2734 ++fp;
2736 else
2737 #endif
2738 while (n--)
2740 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2741 ++to;
2742 ++fp;
2744 return to;
2747 /* Correct a glyph by replacing its specified user-level face code
2748 with a displayable computed face code. */
2750 static GLYPH
2751 fix_glyph (f, glyph, cface)
2752 FRAME_PTR f;
2753 GLYPH glyph;
2754 int cface;
2756 #ifdef HAVE_FACES
2757 if (! FRAME_TERMCAP_P (f))
2759 if (FAST_GLYPH_FACE (glyph) != 0)
2760 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
2761 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
2763 #endif
2764 return glyph;
2767 /* Display one line of window W, starting at position START in W's buffer.
2769 Display starting at horizontal position HPOS, expressed relative to
2770 W's left edge. In situations where the text at START shouldn't
2771 start at the left margin (i.e. when the window is hscrolled, or
2772 we're continuing a line which left off in the midst of a
2773 multi-column character), HPOS should be negative; we throw away
2774 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2775 account.
2777 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2779 OVSTR_DONE is the number of chars of overlay before/after strings
2780 at this position which have already been processed.
2782 Display on position VPOS on the frame. It is origin 0, relative to
2783 the top of the frame, not W.
2785 Returns a STRUCT POSITION giving character to start next line with
2786 and where to display it, including a zero or negative hpos.
2787 The vpos field is not really a vpos; it is 1 unless the line is continued */
2789 struct position val_display_text_line;
2791 static struct position *
2792 display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
2793 struct window *w;
2794 int start;
2795 int vpos;
2796 int hpos;
2797 int taboffset;
2798 int ovstr_done;
2800 register int pos = start;
2801 register int c;
2802 register GLYPH *p1;
2803 register int pause;
2804 register unsigned char *p;
2805 GLYPH *endp;
2806 register GLYPH *leftmargin;
2807 register GLYPH *p1prev;
2808 register GLYPH *p1start;
2809 int prevpos;
2810 int *charstart;
2811 FRAME_PTR f = XFRAME (w->frame);
2812 int tab_width = XINT (current_buffer->tab_width);
2813 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
2814 int width = window_internal_width (w) - 1;
2815 struct position val;
2816 int lastpos;
2817 int invis;
2818 int last_invis_skip = 0;
2819 Lisp_Object last_invis_prop;
2820 int hscroll = XINT (w->hscroll);
2821 int truncate = (hscroll
2822 || (truncate_partial_width_windows
2823 && !WINDOW_FULL_WIDTH_P (w))
2824 || !NILP (current_buffer->truncate_lines));
2826 /* 1 if we should highlight the region. */
2827 int highlight_region
2828 = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)
2829 && (XWINDOW (current_buffer->last_selected_window) == w
2830 || highlight_nonselected_windows));
2831 int region_beg, region_end;
2833 int selective = (INTEGERP (current_buffer->selective_display)
2834 ? XINT (current_buffer->selective_display)
2835 : !NILP (current_buffer->selective_display) ? -1 : 0);
2836 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
2837 register struct Lisp_Char_Table *dp = window_display_table (w);
2839 Lisp_Object default_invis_vector[3];
2840 /* Number of characters of ellipsis to display after an invisible line
2841 if it calls for an ellipsis.
2842 Note that this value can be nonzero regardless of whether
2843 selective display is enabled--you must check that separately. */
2844 int selective_rlen
2845 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2846 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
2847 : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
2848 /* This is the sequence of Lisp objects to display
2849 when there are invisible lines. */
2850 Lisp_Object *invis_vector_contents
2851 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2852 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2853 : default_invis_vector);
2855 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
2856 || !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp)))
2857 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
2858 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
2859 || !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp)))
2860 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
2862 /* If 1, we must handle multibyte characters. */
2863 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
2864 /* Length of multibyte form of each character. */
2865 int len;
2866 /* Glyphs generated should be set this bit mask if text must be
2867 displayed from right to left. */
2868 GLYPH rev_dir_bit = (NILP (current_buffer->direction_reversed)
2869 ? 0 : GLYPH_MASK_REV_DIR);
2871 /* The next buffer location at which the face should change, due
2872 to overlays or text property changes. */
2873 int next_face_change;
2875 /* The next location where the `invisible' property changes, or an
2876 overlay starts or ends. */
2877 int next_boundary;
2879 /* The face we're currently using. */
2880 int current_face = 0;
2881 int i;
2883 XSETFASTINT (default_invis_vector[2], '.');
2884 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2886 hpos += WINDOW_LEFT_MARGIN (w);
2887 get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
2888 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
2890 /* Show where to highlight the region. */
2891 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
2892 /* Maybe highlight only in selected window. */
2893 && (highlight_nonselected_windows
2894 || w == XWINDOW (selected_window)))
2896 region_beg = marker_position (current_buffer->mark);
2897 if (PT < region_beg)
2899 region_end = region_beg;
2900 region_beg = PT;
2902 else
2903 region_end = PT;
2904 w->region_showing = Qt;
2906 else
2908 region_beg = region_end = -1;
2909 w->region_showing = Qnil;
2912 if (MINI_WINDOW_P (w)
2913 && start == BEG
2914 && vpos == XFASTINT (w->top))
2916 if (! NILP (minibuf_prompt))
2918 minibuf_prompt_width
2919 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2920 XSTRING (minibuf_prompt)->size, hpos,
2921 /* Display a space if we truncate. */
2922 ' ',
2923 1, -1,
2924 /* Truncate the prompt a little before the
2925 margin, so user input can at least start
2926 on the first line. */
2927 (XFASTINT (w->width) > 10
2928 ? XFASTINT (w->width) - 4 : -1))
2929 - hpos);
2930 hpos += minibuf_prompt_width;
2931 taboffset -= minibuf_prompt_width;
2933 else
2934 minibuf_prompt_width = 0;
2937 /* If we're hscrolled at all, use compute_motion to skip over any
2938 text off the left edge of the window. compute_motion may know
2939 tricks to do this faster than we can. */
2940 if (hpos < 0)
2942 struct position *left_edge
2943 = compute_motion (pos, vpos, hpos, 0,
2944 ZV, vpos, 0,
2945 width, hscroll, taboffset, w);
2947 /* Retrieve the buffer position and column provided by
2948 compute_motion. We can't assume that the column will be
2949 zero, because you may have multi-column characters crossing
2950 the left margin.
2952 compute_motion may have moved us past the screen position we
2953 requested, if we hit a multi-column character, or the end of
2954 the line. If so, back up. */
2955 if (left_edge->vpos > vpos
2956 || left_edge->hpos > 0)
2958 pos = left_edge->bufpos;
2959 /* Since this should not be a valid multibyte character, we
2960 can decrease POS by 1. */
2961 pos--;
2962 hpos = left_edge->prevhpos;
2964 else
2966 pos = left_edge->bufpos;
2967 hpos = left_edge->hpos;
2971 desired_glyphs->bufp[vpos] = start;
2972 p1 = desired_glyphs->glyphs[vpos] + hpos;
2973 p1start = p1;
2974 charstart = desired_glyphs->charstarts[vpos] + hpos;
2975 /* In case we don't ever write anything into it... */
2976 desired_glyphs->charstarts[vpos][WINDOW_LEFT_MARGIN (w)] = -1;
2977 leftmargin = desired_glyphs->glyphs[vpos] + WINDOW_LEFT_MARGIN (w);
2978 endp = leftmargin + width;
2980 /* Arrange the overlays nicely for our purposes. Usually, we call
2981 display_text_line on only one line at a time, in which case this
2982 can't really hurt too much, or we call it on lines which appear
2983 one after another in the buffer, in which case all calls to
2984 recenter_overlay_lists but the first will be pretty cheap. */
2985 recenter_overlay_lists (current_buffer, pos);
2987 /* Loop generating characters.
2988 Stop at end of buffer, before newline,
2989 if reach or pass continuation column,
2990 or at face change. */
2991 pause = pos;
2992 next_face_change = pos;
2993 next_boundary = pos;
2994 p1prev = p1;
2995 prevpos = pos;
2996 while (p1 < endp)
2998 if (pos >= pause)
3000 int e_t_h;
3002 while (pos == next_boundary)
3004 Lisp_Object position, limit, prop, ww;
3006 /* Display the overlay strings here, unless we're at ZV
3007 and have already displayed the appropriate strings
3008 on an earlier line. */
3009 if (pos < ZV || !zv_strings_seen++)
3011 int ovlen;
3012 unsigned char *ovstr;
3013 ovlen = overlay_strings (pos, w, &ovstr);
3015 if (ovlen > 0)
3017 /* Skip the ones we did in a previous line. */
3018 ovstr += ovstr_done;
3019 ovlen -= ovstr_done;
3021 while (ovlen > 0)
3023 int charset, cols;
3024 GLYPH g;
3026 if (multibyte)
3028 c = STRING_CHAR_AND_LENGTH (ovstr, ovlen, len);
3029 ovstr += len, ovlen -= len, ovstr_done += len;
3030 charset = CHAR_CHARSET (c);
3031 cols = (charset == CHARSET_COMPOSITION
3032 ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
3033 : CHARSET_WIDTH (charset));
3035 else
3037 c = *ovstr++, ovlen--, ovstr_done++;
3038 cols = 1;
3040 g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
3041 while (cols-- > 0)
3043 if (p1 >= leftmargin && p1 < endp)
3044 *p1 = g, g |= GLYPH_MASK_PADDING;
3045 p1++;
3048 /* If we did all the overlay strings
3049 and we have room for text, clear ovstr_done
3050 just for neatness' sake. */
3051 if (ovlen == 0 && p1 < endp)
3052 ovstr_done = 0;
3056 /* Did we reach point? Record the cursor location. */
3057 if (pos == PT && cursor_vpos < 0)
3059 cursor_vpos = vpos;
3060 cursor_hpos = p1 - leftmargin;
3063 if (pos >= ZV)
3064 break;
3066 XSETFASTINT (position, pos);
3067 limit = Fnext_overlay_change (position);
3068 #ifdef USE_TEXT_PROPERTIES
3069 /* This is just an estimate to give reasonable
3070 performance; nothing should go wrong if it is too small. */
3071 if (XFASTINT (limit) > pos + 50)
3073 int limitpos = pos + 50;
3074 if (limitpos < Z)
3075 INC_POS (limitpos); /* Adjust to character boundary. */
3076 XSETFASTINT (limit, limitpos);
3078 limit = Fnext_single_property_change (position, Qinvisible,
3079 Fcurrent_buffer (), limit);
3080 #endif
3081 next_boundary = XFASTINT (limit);
3082 /* if the `invisible' property is set, we can skip to
3083 the next property change. */
3084 XSETWINDOW (ww, w);
3085 prop = Fget_char_property (position, Qinvisible, ww);
3086 if (TEXT_PROP_MEANS_INVISIBLE (prop))
3088 if (pos < PT && next_boundary >= PT)
3090 cursor_vpos = vpos;
3091 cursor_hpos = p1 - leftmargin;
3093 pos = next_boundary;
3094 last_invis_skip = pos;
3095 last_invis_prop = prop;
3099 /* Did we reach point? Record the cursor location. */
3100 if (pos == PT && cursor_vpos < 0)
3102 cursor_vpos = vpos;
3103 cursor_hpos = p1 - leftmargin;
3106 /* Did we hit the end of the visible region of the buffer?
3107 Stop here. */
3108 if (pos >= ZV)
3110 /* Update charstarts for the end of this line. */
3111 /* Do nothing if off the left edge or at the right edge. */
3112 if (p1 >= leftmargin && p1 + 1 != endp)
3114 int *p2x = &charstart[(p1 < leftmargin
3115 ? leftmargin : p1)
3116 - p1start];
3117 *p2x++ = pos;
3119 break;
3122 /* Figure out where (if at all) the
3123 redisplay_end_trigger-hook should run. */
3124 if (MARKERP (w->redisplay_end_trigger)
3125 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
3126 e_t_h = marker_position (w->redisplay_end_trigger);
3127 else if (INTEGERP (w->redisplay_end_trigger))
3128 e_t_h = XINT (w->redisplay_end_trigger);
3129 else
3130 e_t_h = ZV;
3132 /* If we've gone past the place to run a hook,
3133 run the hook. */
3134 if (pos >= e_t_h && e_t_h != ZV)
3136 Lisp_Object args[3];
3138 args[0] = Qredisplay_end_trigger_functions;
3139 XSETWINDOW (args[1], w);
3140 XSETINT (args[2], e_t_h);
3142 /* Since we are *trying* to run these functions,
3143 don't try to run them again, even if they get an error. */
3144 w->redisplay_end_trigger = Qnil;
3145 Frun_hook_with_args (3, args);
3147 e_t_h = ZV;
3148 /* Notice if it changed the face of this character. */
3149 next_face_change = pos;
3152 #ifdef HAVE_FACES
3153 /* Did we hit a face change? Figure out what face we should
3154 use now. We also hit this the first time through the
3155 loop, to see what face we should start with. */
3156 if (pos >= next_face_change
3157 && (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f)))
3159 int limit = pos + 50;
3161 if (limit < Z && !CHAR_HEAD_P (POS_ADDR (limit)))
3162 INC_POS (limit); /* Adjust to character boundary. */
3163 current_face = compute_char_face (f, w, pos,
3164 region_beg, region_end,
3165 &next_face_change, limit, 0);
3167 #endif
3169 /* Compute the next place we need to stop
3170 and do something special; set PAUSE. */
3172 pause = ZV;
3174 if (pos < next_boundary && next_boundary < pause)
3175 pause = next_boundary;
3176 if (pos < next_face_change && next_face_change < pause)
3177 pause = next_face_change;
3179 if (e_t_h < pause)
3180 pause = e_t_h;
3182 /* Wouldn't you hate to read the next line to someone over
3183 the phone? */
3184 if (pos < PT && PT < pause)
3185 pause = PT;
3186 if (pos < GPT && GPT < pause)
3187 pause = GPT;
3189 p = POS_ADDR (pos);
3192 if (p1 >= endp)
3193 break;
3195 p1prev = p1;
3197 if (multibyte)
3198 /* PAUSE is surely at character boundary. */
3199 c = STRING_CHAR_AND_LENGTH (p, pause - pos, len), p += len;
3200 else
3201 c = *p++, len = 1;
3202 /* Let a display table override all standard display methods. */
3203 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
3205 p1 = copy_part_of_rope (f, p1, leftmargin,
3206 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
3207 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
3208 current_face, rev_dir_bit);
3210 else if (c >= 040 && c < 0177)
3212 if (p1 >= leftmargin)
3213 *p1 = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
3214 p1++;
3216 else if (c == '\n')
3218 #if 0
3219 /* Same as p1prev, but after the invis_vector_contents text
3220 (if we have that on this line). */
3221 GLYPH *p1prev_modified;
3222 #endif
3224 invis = 0;
3225 if (last_invis_skip == pos
3226 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
3227 invis = 1;
3228 while (pos + 1 < ZV
3229 && selective > 0
3230 && indented_beyond_p (pos + 1, selective))
3232 invis = 1;
3233 pos = find_next_newline (pos + 1, 1);
3234 if (FETCH_BYTE (pos - 1) == '\n')
3235 pos--;
3237 if (invis && selective_rlen > 0 && p1 >= leftmargin)
3239 #if 0
3240 GLYPH *cs, *csend;
3242 cs = charstart + (p1 - p1start);
3243 #endif
3245 p1 += selective_rlen;
3246 if (p1 - leftmargin > width)
3247 p1 = endp;
3249 #if 0 /* This needs more work; charstarts needs to record
3250 both whether a position ho;ds an ellipsis character
3251 and what buffer position it corresponds to. */
3252 csend = charstart + (p1 - p1start);
3253 while (cs != csend)
3254 *cs++ = -2;
3255 /* The idea is to use p1prev_modified instead of p1prev
3256 in the loop below over p2x. */
3257 p1prev_modified = p1;
3258 #endif
3260 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
3261 (p1 - p1prev), current_face, rev_dir_bit);
3264 /* Update charstarts for the newline that ended this line. */
3265 /* Do nothing here for a char that's entirely off the left edge
3266 or if it starts at the right edge. */
3267 if (p1 >= leftmargin && p1prev != endp)
3269 /* Store the newline's position into charstarts
3270 for the column where the newline starts.
3271 Store -1 for the rest of the glyphs it occupies. */
3272 int *p2x = &charstart[(p1prev < leftmargin
3273 ? leftmargin : p1prev)
3274 - p1start];
3275 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3277 *p2x++ = pos;
3278 while (p2x < p2)
3279 *p2x++ = -1;
3281 #ifdef HAVE_FACES
3282 /* Draw the face of the newline character as extending all the
3283 way to the end of the frame line. */
3284 if (current_face)
3286 if (p1 < leftmargin)
3287 p1 = leftmargin;
3288 while (p1 < endp)
3289 *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
3291 #endif
3293 break;
3295 else if (c == '\t')
3299 if (p1 >= leftmargin && p1 < endp)
3300 *p1 = MAKE_GLYPH (f, ' ', current_face) | rev_dir_bit;
3301 p1++;
3303 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
3304 % tab_width);
3306 else if (c == Ctl ('M') && selective == -1)
3308 pos = find_next_newline (pos, 1);
3309 if (FETCH_BYTE (pos - 1) == '\n')
3310 pos--;
3311 if (selective_rlen > 0)
3313 p1 += selective_rlen;
3314 if (p1 - leftmargin > width)
3315 p1 = endp;
3316 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
3317 (p1 - p1prev), current_face, rev_dir_bit);
3319 #ifdef HAVE_FACES
3320 /* Draw the face of the newline character as extending all the
3321 way to the end of the frame line. */
3322 if (current_face)
3324 if (p1 < leftmargin)
3325 p1 = leftmargin;
3326 while (p1 < endp)
3327 *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
3329 #endif
3331 /* Update charstarts for the ^M that ended this line. */
3332 /* Do nothing here for a char that's entirely off the left edge
3333 or if it starts at the right edge. */
3334 if (p1 >= leftmargin && p1prev != endp)
3336 /* Store the newline's position into charstarts
3337 for the column where the newline starts.
3338 Store -1 for the rest of the glyphs it occupies. */
3339 int *p2x = &charstart[(p1prev < leftmargin
3340 ? leftmargin : p1prev)
3341 - p1start];
3342 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3344 *p2x++ = pos;
3345 while (p2x < p2)
3346 *p2x++ = -1;
3348 break;
3350 else if (c < 0200 && ctl_arrow)
3352 if (p1 >= leftmargin)
3353 *p1 = (fix_glyph
3354 (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
3355 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
3356 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
3357 current_face)
3358 | rev_dir_bit);
3359 p1++;
3360 if (p1 >= leftmargin && p1 < endp)
3361 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face) | rev_dir_bit;
3362 p1++;
3364 else if (len == 1)
3366 /* C is not a multibyte character. */
3367 if (p1 >= leftmargin)
3368 *p1 = (fix_glyph
3369 (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
3370 && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
3371 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
3372 current_face)
3373 | rev_dir_bit);
3374 p1++;
3375 if (p1 >= leftmargin && p1 < endp)
3376 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face) | rev_dir_bit;
3377 p1++;
3378 if (p1 >= leftmargin && p1 < endp)
3379 *p1 = (MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face)
3380 | rev_dir_bit);
3381 p1++;
3382 if (p1 >= leftmargin && p1 < endp)
3383 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face) | rev_dir_bit;
3384 p1++;
3386 else
3388 /* C is a multibyte character. */
3389 int charset = CHAR_CHARSET (c);
3390 int columns = (charset == CHARSET_COMPOSITION
3391 ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
3392 : CHARSET_WIDTH (charset));
3393 GLYPH g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
3395 while (columns--)
3397 if (p1 >= leftmargin && p1 < endp)
3398 *p1 = g, g |= GLYPH_MASK_PADDING;
3399 p1++;
3403 prevpos = pos;
3404 pos += len;
3406 /* Update charstarts for the character just output. */
3408 /* Do nothing here for a char that's entirely off the left edge. */
3409 if (p1 >= leftmargin)
3411 /* Store the char's position into charstarts
3412 for the first glyph occupied by this char.
3413 Store -1 for the rest of the glyphs it occupies. */
3414 if (p1 != p1prev)
3416 int *p2x = &charstart[(p1prev < leftmargin
3417 ? leftmargin : p1prev)
3418 - p1start];
3419 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3421 if (p2x < p2)
3422 *p2x++ = prevpos;
3423 while (p2x < p2)
3424 *p2x++ = -1;
3429 val.hpos = - XINT (w->hscroll);
3430 if (val.hpos)
3431 val.hpos++;
3433 val.vpos = 1;
3435 lastpos = pos;
3437 /* Store 0 in this charstart line for the positions where
3438 there is no character. But do leave what was recorded
3439 for the character that ended the line. */
3440 /* Add 1 in the endtest to compensate for the fact that ENDP was
3441 made from WIDTH, which is 1 less than the window's actual
3442 internal width. */
3443 i = p1 - p1start + 1;
3444 if (p1 < leftmargin)
3445 i += leftmargin - p1;
3446 for (; i < endp - p1start + 1; i++)
3447 charstart[i] = 0;
3449 /* Handle continuation in middle of a character */
3450 /* by backing up over it */
3451 if (p1 > endp)
3453 /* Don't back up if we never actually displayed any text.
3454 This occurs when the minibuffer prompt takes up the whole line. */
3455 if (p1prev)
3457 /* Start the next line with that same character whose
3458 character code is C and the length of multi-byte form is
3459 LEN. */
3460 pos = prevpos;
3462 if (len == 1)
3463 /* C is not a multi-byte character. We can break it and
3464 start from the middle column in the next line. So,
3465 adjust VAL.HPOS to skip the columns output on this
3466 line. */
3467 val.hpos += p1prev - endp;
3468 else
3470 /* C is a multibyte character. Since we can't broke it
3471 in the middle, the whole character should be driven
3472 into the next line. */
3473 /* As the result, the actual columns occupied by the
3474 text on this line is less than WIDTH. VAL.TAB_OFFSET
3475 must be adjusted. */
3476 taboffset = taboffset + (p1prev - endp);
3477 /* Let's fill unused columns with TRUNCATOR or CONTINUER. */
3479 GLYPH g = fix_glyph (f, truncate ? truncator : continuer, 0);
3480 while (p1prev < endp)
3481 *p1prev++ = g;
3483 /* If POINT is at POS, cursor should not on this line. */
3484 lastpos = pos;
3485 if (PT == pos)
3486 cursor_vpos = -1;
3490 /* Keep in this line everything up to the continuation column. */
3491 p1 = endp;
3494 /* Finish deciding which character to start the next line on,
3495 and what hpos to start it at.
3496 Also set `lastpos' to the last position which counts as "on this line"
3497 for cursor-positioning. */
3499 if (pos < ZV)
3501 if (FETCH_BYTE (pos) == '\n')
3503 /* If stopped due to a newline, start next line after it */
3504 pos++;
3505 val.tab_offset = 0;
3506 /* Check again for hidden lines, in case the newline occurred exactly
3507 at the right margin. */
3508 while (pos < ZV && selective > 0
3509 && indented_beyond_p (pos, selective))
3510 pos = find_next_newline (pos, 1);
3512 else
3513 /* Stopped due to right margin of window */
3515 if (truncate)
3517 *p1++ = fix_glyph (f, truncator, 0);
3518 /* Truncating => start next line after next newline,
3519 and point is on this line if it is before the newline,
3520 and skip none of first char of next line */
3522 pos = find_next_newline (pos, 1);
3523 while (pos < ZV && selective > 0
3524 && indented_beyond_p (pos, selective));
3525 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
3527 lastpos = pos - (FETCH_BYTE (pos - 1) == '\n');
3528 val.tab_offset = 0;
3530 else
3532 *p1++ = fix_glyph (f, continuer, 0);
3533 val.vpos = 0;
3534 lastpos--;
3535 val.tab_offset = taboffset + width;
3539 else
3540 val.tab_offset = 0;
3542 /* If point is at eol or in invisible text at eol,
3543 record its frame location now. */
3545 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
3547 cursor_vpos = vpos;
3548 cursor_hpos = p1 - leftmargin;
3551 if (cursor_vpos == vpos)
3553 if (cursor_hpos < 0) cursor_hpos = 0;
3554 if (cursor_hpos > width) cursor_hpos = width;
3555 cursor_hpos += WINDOW_LEFT_MARGIN (w);
3556 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
3558 if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
3559 && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
3561 FRAME_CURSOR_Y (f) = cursor_vpos;
3562 FRAME_CURSOR_X (f) = cursor_hpos;
3565 if (w == XWINDOW (selected_window))
3567 /* Line is not continued and did not start
3568 in middle of character */
3569 if ((hpos - WINDOW_LEFT_MARGIN (w)
3570 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
3571 && val.vpos)
3573 this_line_bufpos = start;
3574 this_line_buffer = current_buffer;
3575 this_line_vpos = cursor_vpos;
3576 this_line_start_hpos = hpos;
3577 this_line_endpos = Z - lastpos;
3579 else
3580 this_line_bufpos = 0;
3585 /* If hscroll and line not empty, insert truncation-at-left marker */
3586 if (hscroll && lastpos != start)
3588 GLYPH g = fix_glyph (f, truncator, 0);
3589 *leftmargin = g;
3590 if (p1 <= leftmargin)
3591 p1 = leftmargin + 1;
3592 else /* MULE: it may be a wide-column character */
3594 p1prev = leftmargin + 1;
3595 while (p1prev < p1 && *p1prev & GLYPH_MASK_PADDING)
3596 *p1prev++ = g;
3600 if (!WINDOW_RIGHTMOST_P (w))
3602 endp++;
3603 if (p1 < leftmargin) p1 = leftmargin;
3604 while (p1 < endp) *p1++ = SPACEGLYPH;
3606 /* Don't draw vertical bars if we're using scroll bars. They're
3607 covered up by the scroll bars, and it's distracting to see
3608 them when the scroll bar windows are flickering around to be
3609 reconfigured. */
3610 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3612 int i;
3613 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
3614 *p1++ = SPACEGLYPH;
3616 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3617 *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
3618 ? XINT (DISP_BORDER_GLYPH (dp))
3619 : '|');
3621 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
3622 p1 - desired_glyphs->glyphs[vpos]);
3623 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3625 /* If the start of this line is the overlay arrow-position,
3626 then put the arrow string into the display-line. */
3628 if (MARKERP (Voverlay_arrow_position)
3629 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
3630 && start == marker_position (Voverlay_arrow_position)
3631 && STRINGP (Voverlay_arrow_string)
3632 && ! overlay_arrow_seen)
3634 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
3635 int i;
3636 int len = XSTRING (Voverlay_arrow_string)->size;
3637 int arrow_end;
3639 if (len > width)
3640 len = width;
3641 #ifdef HAVE_FACES
3642 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
3644 /* If the arrow string has text props, obey them when displaying. */
3645 for (i = 0; i < len; i++)
3647 int c = p[i];
3648 Lisp_Object face, ilisp;
3649 int newface;
3651 XSETFASTINT (ilisp, i);
3652 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
3653 newface = compute_glyph_face_1 (f, face, 0);
3654 leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
3657 else
3658 #endif /* HAVE_FACES */
3660 for (i = 0; i < len; i++)
3661 leftmargin[i] = p[i];
3664 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
3665 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
3666 if (desired_glyphs->used[vpos] < arrow_end)
3667 desired_glyphs->used[vpos] = arrow_end;
3669 overlay_arrow_seen = 1;
3672 val.bufpos = pos;
3673 val.ovstring_chars_done = ovstr_done;
3674 val_display_text_line = val;
3675 return &val_display_text_line;
3678 /* Redisplay the menu bar in the frame for window W. */
3680 static void
3681 display_menu_bar (w)
3682 struct window *w;
3684 Lisp_Object items, tail;
3685 register int vpos = 0;
3686 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3687 int maxendcol = FRAME_WIDTH (f);
3688 int hpos = 0;
3689 int i;
3691 #ifdef HAVE_NTGUI
3692 if (!NILP (Vwindow_system))
3693 return;
3694 #endif
3696 #ifdef USE_X_TOOLKIT
3697 if (FRAME_X_P (f))
3698 return;
3699 #endif /* USE_X_TOOLKIT */
3701 get_display_line (f, vpos, 0);
3703 items = FRAME_MENU_BAR_ITEMS (f);
3704 for (i = 0; i < XVECTOR (items)->size; i += 4)
3706 Lisp_Object pos, string;
3707 string = XVECTOR (items)->contents[i + 1];
3708 if (NILP (string))
3709 break;
3711 XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
3713 if (hpos < maxendcol)
3714 hpos = display_string (w, vpos,
3715 XSTRING (string)->data,
3716 XSTRING (string)->size,
3717 hpos, 0, 0, hpos, maxendcol);
3718 /* Put a space between items. */
3719 if (hpos < maxendcol)
3721 int hpos1 = hpos + 1;
3722 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
3723 min (hpos1, maxendcol), maxendcol);
3727 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3728 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
3730 /* Fill out the line with spaces. */
3731 if (maxendcol > hpos)
3732 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
3734 /* Clear the rest of the lines allocated to the menu bar. */
3735 vpos++;
3736 while (vpos < FRAME_MENU_BAR_LINES (f))
3737 get_display_line (f, vpos++, 0);
3740 /* Display the mode line for window w */
3742 static void
3743 display_mode_line (w)
3744 struct window *w;
3746 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
3747 register int left = WINDOW_LEFT_MARGIN (w);
3748 register int right = WINDOW_RIGHT_MARGIN (w);
3749 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3751 line_number_displayed = 0;
3752 w->column_number_displayed = Qnil;
3754 get_display_line (f, vpos, left);
3756 /* Temporarily make frame F's kboard the current kboard
3757 so that kboard-local variables in the mode_line_format
3758 will get the right values. */
3759 push_frame_kboard (f);
3761 display_mode_element (w, vpos, left, 0, right, right,
3762 current_buffer->mode_line_format);
3764 pop_frame_kboard ();
3766 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3768 /* Put the mode line in inverse video.
3769 Use faces if possible, since that lets us handle
3770 partial-width windows and avoid inverting the scroll bar columns. */
3771 #ifdef HAVE_FACES
3772 if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
3774 /* For a partial width window, explicitly set face of each glyph. */
3775 int i;
3776 unsigned int padding;
3777 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
3778 for (i = left; i < right; ++i)
3780 padding = ptr[i] & GLYPH_MASK_PADDING;
3781 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1) | padding;
3784 else
3785 #endif
3787 /* Make the mode line inverse video if the entire line
3788 is made of mode lines.
3789 I.e. if this window is full width,
3790 or if it is the child of a full width window
3791 (which implies that that window is split side-by-side
3792 and the rest of this line is mode lines of the sibling windows). */
3793 if (WINDOW_FULL_WIDTH_P (w)
3794 || WINDOW_FULL_WIDTH_P (XWINDOW (w->parent)))
3795 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
3798 /* Contribute ELT to the mode line for window W.
3799 How it translates into text depends on its data type.
3801 VPOS is the position of the mode line being displayed.
3803 HPOS is the position (absolute on frame) where this element's text
3804 should start. The output is truncated automatically at the right
3805 edge of window W.
3807 DEPTH is the depth in recursion. It is used to prevent
3808 infinite recursion here.
3810 MINENDCOL is the hpos before which the element may not end.
3811 The element is padded at the right with spaces if nec
3812 to reach this column.
3814 MAXENDCOL is the hpos past which this element may not extend.
3815 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3816 (This is necessary to make nested padding and truncation work.)
3818 Returns the hpos of the end of the text generated by ELT.
3819 The next element will receive that value as its HPOS arg,
3820 so as to concatenate the elements. */
3822 static int
3823 display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
3824 struct window *w;
3825 register int vpos, hpos;
3826 int depth;
3827 int minendcol;
3828 register int maxendcol;
3829 register Lisp_Object elt;
3831 tail_recurse:
3832 if (depth > 10)
3833 goto invalid;
3835 depth++;
3837 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
3839 case Lisp_String:
3841 /* A string: output it and check for %-constructs within it. */
3842 register unsigned char c;
3843 register unsigned char *this = XSTRING (elt)->data;
3845 while (hpos < maxendcol && *this)
3847 unsigned char *last = this;
3848 while ((c = *this++) != '\0' && c != '%')
3850 if (this - 1 != last)
3852 register int lim = --this - last + hpos;
3853 if (frame_title_ptr)
3854 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
3855 else
3856 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
3857 hpos, min (lim, maxendcol));
3859 else /* c == '%' */
3861 register int minendcol;
3862 register int spec_width = 0;
3864 /* We can't allow -ve args due to the "%-" construct */
3865 /* Argument specifies minwidth but not maxwidth
3866 (maxwidth can be specified by
3867 (<negative-number> . <stuff>) mode-line elements) */
3869 while ((c = *this++) >= '0' && c <= '9')
3871 spec_width = spec_width * 10 + (c - '0');
3874 minendcol = hpos + spec_width;
3875 if (minendcol > maxendcol)
3877 spec_width = maxendcol - hpos;
3878 minendcol = maxendcol;
3881 if (c == 'M')
3882 hpos = display_mode_element (w, vpos, hpos, depth,
3883 spec_width, maxendcol,
3884 Vglobal_mode_string);
3885 else if (c != 0)
3887 char *spec = decode_mode_spec (w, c, spec_width,
3888 maxendcol - hpos);
3889 if (frame_title_ptr)
3890 hpos = store_frame_title (spec, minendcol, maxendcol);
3891 else
3892 hpos = display_string (w, vpos, spec, -1,
3893 hpos, 0, 1,
3894 minendcol, maxendcol);
3899 break;
3901 case Lisp_Symbol:
3902 /* A symbol: process the value of the symbol recursively
3903 as if it appeared here directly. Avoid error if symbol void.
3904 Special case: if value of symbol is a string, output the string
3905 literally. */
3907 register Lisp_Object tem;
3908 tem = Fboundp (elt);
3909 if (!NILP (tem))
3911 tem = Fsymbol_value (elt);
3912 /* If value is a string, output that string literally:
3913 don't check for % within it. */
3914 if (STRINGP (tem))
3916 if (frame_title_ptr)
3917 hpos = store_frame_title (XSTRING (tem)->data,
3918 minendcol, maxendcol);
3919 else
3920 hpos = display_string (w, vpos, XSTRING (tem)->data,
3921 XSTRING (tem)->size,
3922 hpos, 0, 1, minendcol, maxendcol);
3924 /* Give up right away for nil or t. */
3925 else if (!EQ (tem, elt))
3926 { elt = tem; goto tail_recurse; }
3929 break;
3931 case Lisp_Cons:
3933 register Lisp_Object car, tem;
3935 /* A cons cell: three distinct cases.
3936 If first element is a string or a cons, process all the elements
3937 and effectively concatenate them.
3938 If first element is a negative number, truncate displaying cdr to
3939 at most that many characters. If positive, pad (with spaces)
3940 to at least that many characters.
3941 If first element is a symbol, process the cadr or caddr recursively
3942 according to whether the symbol's value is non-nil or nil. */
3943 car = XCONS (elt)->car;
3944 if (SYMBOLP (car))
3946 tem = Fboundp (car);
3947 elt = XCONS (elt)->cdr;
3948 if (!CONSP (elt))
3949 goto invalid;
3950 /* elt is now the cdr, and we know it is a cons cell.
3951 Use its car if CAR has a non-nil value. */
3952 if (!NILP (tem))
3954 tem = Fsymbol_value (car);
3955 if (!NILP (tem))
3956 { elt = XCONS (elt)->car; goto tail_recurse; }
3958 /* Symbol's value is nil (or symbol is unbound)
3959 Get the cddr of the original list
3960 and if possible find the caddr and use that. */
3961 elt = XCONS (elt)->cdr;
3962 if (NILP (elt))
3963 break;
3964 else if (!CONSP (elt))
3965 goto invalid;
3966 elt = XCONS (elt)->car;
3967 goto tail_recurse;
3969 else if (INTEGERP (car))
3971 register int lim = XINT (car);
3972 elt = XCONS (elt)->cdr;
3973 if (lim < 0)
3974 /* Negative int means reduce maximum width.
3975 DO NOT change MINENDCOL here!
3976 (20 -10 . foo) should truncate foo to 10 col
3977 and then pad to 20. */
3978 maxendcol = min (maxendcol, hpos - lim);
3979 else if (lim > 0)
3981 /* Padding specified. Don't let it be more than
3982 current maximum. */
3983 lim += hpos;
3984 if (lim > maxendcol)
3985 lim = maxendcol;
3986 /* If that's more padding than already wanted, queue it.
3987 But don't reduce padding already specified even if
3988 that is beyond the current truncation point. */
3989 if (lim > minendcol)
3990 minendcol = lim;
3992 goto tail_recurse;
3994 else if (STRINGP (car) || CONSP (car))
3996 register int limit = 50;
3997 /* LIMIT is to protect against circular lists. */
3998 while (CONSP (elt) && --limit > 0
3999 && hpos < maxendcol)
4001 hpos = display_mode_element (w, vpos, hpos, depth,
4002 hpos, maxendcol,
4003 XCONS (elt)->car);
4004 elt = XCONS (elt)->cdr;
4008 break;
4010 default:
4011 invalid:
4012 if (frame_title_ptr)
4013 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
4014 else
4015 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
4016 minendcol, maxendcol);
4017 return hpos;
4020 if (minendcol > hpos)
4021 if (frame_title_ptr)
4022 hpos = store_frame_title ("", minendcol, maxendcol);
4023 else
4024 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
4025 return hpos;
4028 /* Write a null-terminated, right justified decimal representation of
4029 the positive integer D to BUF using a minimal field width WIDTH. */
4031 static void
4032 pint2str (buf, width, d)
4033 register char *buf;
4034 register int width;
4035 register int d;
4037 register char *p = buf;
4039 if (d <= 0)
4040 *p++ = '0';
4041 else
4042 while (d > 0)
4044 *p++ = d % 10 + '0';
4045 d /= 10;
4047 for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
4048 *p-- = '\0';
4049 while (p > buf)
4051 d = *buf;
4052 *buf++ = *p;
4053 *p-- = d;
4057 /* Set a mnemonic character for CODING_SYSTEM (Lisp symbol) in BUF.
4058 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
4059 type of CODING_SYSTEM. Return updated pointer into BUF. */
4061 static char *
4062 decode_mode_spec_coding (coding_system, buf, eol_flag)
4063 Lisp_Object coding_system;
4064 register char *buf;
4065 int eol_flag;
4067 Lisp_Object val;
4069 val = coding_system;
4071 if (NILP (val)) /* Not yet decided. */
4073 *buf++ = '-';
4074 if (eol_flag)
4075 *buf++ = eol_mnemonic_undecided;
4076 /* Don't mention EOL conversion if it isn't decided. */
4078 else
4080 Lisp_Object eolvalue;
4082 eolvalue = Fget (coding_system, Qeol_type);
4084 while (!NILP (val) && SYMBOLP (val))
4086 val = Fget (val, Qcoding_system);
4087 if (NILP (eolvalue))
4088 eolvalue = Fget (coding_system, Qeol_type);
4091 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
4092 if (eol_flag)
4094 /* The EOL conversion we are using. */
4095 int eoltype;
4096 /* The EOL conversion that is normal on this system. */
4098 if (NILP (eolvalue)) /* Not yet decided. */
4099 eoltype = eol_mnemonic_undecided;
4100 else if (VECTORP (eolvalue)) /* Not yet decided. */
4101 eoltype = eol_mnemonic_undecided;
4102 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
4103 eoltype = (XFASTINT (eolvalue) == 0
4104 ? eol_mnemonic_unix
4105 : (XFASTINT (eolvalue) == 1
4106 ? eol_mnemonic_dos : eol_mnemonic_mac));
4108 /* Mention the EOL conversion if it is not the usual one. */
4109 *buf++ = eoltype;
4112 return buf;
4115 /* Return a string for the output of a mode line %-spec for window W,
4116 generated by character C. SPEC_WIDTH is the field width when
4117 padding to the left (%c, %l). The value returned from this
4118 function will later be truncated to width MAXWIDTH. */
4120 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
4122 static char *
4123 decode_mode_spec (w, c, spec_width, maxwidth)
4124 struct window *w;
4125 register char c;
4126 register int spec_width;
4127 register int maxwidth;
4129 Lisp_Object obj;
4130 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
4131 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
4132 struct buffer *b = XBUFFER (w->buffer);
4134 obj = Qnil;
4135 if (maxwidth > FRAME_WIDTH (f))
4136 maxwidth = FRAME_WIDTH (f);
4138 switch (c)
4140 case '*':
4141 if (!NILP (b->read_only))
4142 return "%";
4143 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4144 return "*";
4145 return "-";
4147 case '+':
4148 /* This differs from %* only for a modified read-only buffer. */
4149 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4150 return "*";
4151 if (!NILP (b->read_only))
4152 return "%";
4153 return "-";
4155 case '&':
4156 /* This differs from %* in ignoring read-only-ness. */
4157 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4158 return "*";
4159 return "-";
4161 case '%':
4162 return "%";
4164 case '[':
4166 int i;
4167 char *p;
4169 if (command_loop_level > 5)
4170 return "[[[... ";
4171 p = decode_mode_spec_buf;
4172 for (i = 0; i < command_loop_level; i++)
4173 *p++ = '[';
4174 *p = 0;
4175 return decode_mode_spec_buf;
4178 case ']':
4180 int i;
4181 char *p;
4183 if (command_loop_level > 5)
4184 return " ...]]]";
4185 p = decode_mode_spec_buf;
4186 for (i = 0; i < command_loop_level; i++)
4187 *p++ = ']';
4188 *p = 0;
4189 return decode_mode_spec_buf;
4192 case '-':
4194 register char *p;
4195 register int i;
4197 if (maxwidth < sizeof (lots_of_dashes))
4198 return lots_of_dashes;
4199 else
4201 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
4202 *p++ = '-';
4203 *p = '\0';
4205 return decode_mode_spec_buf;
4208 case 'b':
4209 obj = b->name;
4210 #if 0
4211 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
4213 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
4214 decode_mode_spec_buf[maxwidth - 1] = '\\';
4215 decode_mode_spec_buf[maxwidth] = '\0';
4216 return decode_mode_spec_buf;
4218 #endif
4219 break;
4221 case 'c':
4223 int col = current_column ();
4224 XSETFASTINT (w->column_number_displayed, col);
4225 pint2str (decode_mode_spec_buf, spec_width, col);
4226 return decode_mode_spec_buf;
4229 case 'F':
4230 /* %F displays the frame name. */
4231 if (!NILP (f->title))
4232 return (char *) XSTRING (f->title)->data;
4233 if (f->explicit_name || ! FRAME_WINDOW_P (f))
4234 return (char *) XSTRING (f->name)->data;
4235 return "Emacs";
4237 case 'f':
4238 obj = b->filename;
4239 #if 0
4240 if (NILP (obj))
4241 return "[none]";
4242 else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
4244 bcopy ("...", decode_mode_spec_buf, 3);
4245 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
4246 decode_mode_spec_buf + 3, maxwidth - 3);
4247 return decode_mode_spec_buf;
4249 #endif
4250 break;
4252 case 'l':
4254 int startpos = marker_position (w->start);
4255 int line, linepos, topline;
4256 int nlines, junk;
4257 Lisp_Object tem;
4258 int height = XFASTINT (w->height);
4260 /* If we decided that this buffer isn't suitable for line numbers,
4261 don't forget that too fast. */
4262 if (EQ (w->base_line_pos, w->buffer))
4263 goto no_value;
4264 /* But do forget it, if the window shows a different buffer now. */
4265 else if (BUFFERP (w->base_line_pos))
4266 w->base_line_pos = Qnil;
4268 /* If the buffer is very big, don't waste time. */
4269 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
4271 w->base_line_pos = Qnil;
4272 w->base_line_number = Qnil;
4273 goto no_value;
4276 if (!NILP (w->base_line_number)
4277 && !NILP (w->base_line_pos)
4278 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
4280 line = XFASTINT (w->base_line_number);
4281 linepos = XFASTINT (w->base_line_pos);
4283 else
4285 line = 1;
4286 linepos = BUF_BEGV (b);
4289 /* Count lines from base line to window start position. */
4290 nlines = display_count_lines (linepos, startpos, startpos, &junk);
4292 topline = nlines + line;
4294 /* Determine a new base line, if the old one is too close
4295 or too far away, or if we did not have one.
4296 "Too close" means it's plausible a scroll-down would
4297 go back past it. */
4298 if (startpos == BUF_BEGV (b))
4300 XSETFASTINT (w->base_line_number, topline);
4301 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
4303 else if (nlines < height + 25 || nlines > height * 3 + 50
4304 || linepos == BUF_BEGV (b))
4306 int limit = BUF_BEGV (b);
4307 int position;
4308 int distance = (height * 2 + 30) * 200;
4310 if (startpos - distance > limit)
4311 limit = startpos - distance;
4313 nlines = display_count_lines (startpos, limit,
4314 -(height * 2 + 30),
4315 &position);
4316 /* If we couldn't find the lines we wanted within
4317 200 chars per line,
4318 give up on line numbers for this window. */
4319 if (position == startpos - distance)
4321 w->base_line_pos = w->buffer;
4322 w->base_line_number = Qnil;
4323 goto no_value;
4326 XSETFASTINT (w->base_line_number, topline - nlines);
4327 XSETFASTINT (w->base_line_pos, position);
4330 /* Now count lines from the start pos to point. */
4331 nlines = display_count_lines (startpos, PT, PT, &junk);
4333 /* Record that we did display the line number. */
4334 line_number_displayed = 1;
4336 /* Make the string to show. */
4337 pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
4338 return decode_mode_spec_buf;
4339 no_value:
4341 char* p = decode_mode_spec_buf;
4342 for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
4343 strcpy (p, "??");
4344 return decode_mode_spec_buf;
4347 break;
4349 case 'm':
4350 obj = b->mode_name;
4351 break;
4353 case 'n':
4354 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
4355 return " Narrow";
4356 break;
4358 case 'p':
4360 int pos = marker_position (w->start);
4361 int total = BUF_ZV (b) - BUF_BEGV (b);
4363 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
4365 if (pos <= BUF_BEGV (b))
4366 return "All";
4367 else
4368 return "Bottom";
4370 else if (pos <= BUF_BEGV (b))
4371 return "Top";
4372 else
4374 if (total > 1000000)
4375 /* Do it differently for a large value, to avoid overflow. */
4376 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
4377 else
4378 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
4379 /* We can't normally display a 3-digit number,
4380 so get us a 2-digit number that is close. */
4381 if (total == 100)
4382 total = 99;
4383 sprintf (decode_mode_spec_buf, "%2d%%", total);
4384 return decode_mode_spec_buf;
4388 /* Display percentage of size above the bottom of the screen. */
4389 case 'P':
4391 int toppos = marker_position (w->start);
4392 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
4393 int total = BUF_ZV (b) - BUF_BEGV (b);
4395 if (botpos >= BUF_ZV (b))
4397 if (toppos <= BUF_BEGV (b))
4398 return "All";
4399 else
4400 return "Bottom";
4402 else
4404 if (total > 1000000)
4405 /* Do it differently for a large value, to avoid overflow. */
4406 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
4407 else
4408 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
4409 /* We can't normally display a 3-digit number,
4410 so get us a 2-digit number that is close. */
4411 if (total == 100)
4412 total = 99;
4413 if (toppos <= BUF_BEGV (b))
4414 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
4415 else
4416 sprintf (decode_mode_spec_buf, "%2d%%", total);
4417 return decode_mode_spec_buf;
4421 case 's':
4422 /* status of process */
4423 obj = Fget_buffer_process (w->buffer);
4424 if (NILP (obj))
4425 return "no process";
4426 #ifdef subprocesses
4427 obj = Fsymbol_name (Fprocess_status (obj));
4428 #endif
4429 break;
4431 case 't': /* indicate TEXT or BINARY */
4432 #ifdef MODE_LINE_BINARY_TEXT
4433 return MODE_LINE_BINARY_TEXT (b);
4434 #else
4435 return "T";
4436 #endif
4438 case 'z':
4439 /* coding-system (not including end-of-line format) */
4440 case 'Z':
4441 /* coding-system (including end-of-line type) */
4443 int eol_flag = (c == 'Z');
4444 char *p;
4446 if (FRAME_TERMCAP_P (f))
4448 /* No need to mention EOL here--the terminal never needs
4449 to do EOL conversion. */
4450 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
4451 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
4453 p = decode_mode_spec_coding (b->buffer_file_coding_system,
4454 decode_mode_spec_buf, eol_flag);
4456 #if 0 /* This proves to be annoying; I think we can do without. -- rms. */
4457 #ifdef subprocesses
4458 obj = Fget_buffer_process (Fcurrent_buffer ());
4459 if (PROCESSP (obj))
4461 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
4462 p, eol_flag);
4463 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
4464 p, eol_flag);
4466 #endif /* subprocesses */
4467 #endif /* 0 */
4468 *p = 0;
4469 return decode_mode_spec_buf;
4473 if (STRINGP (obj))
4474 return (char *) XSTRING (obj)->data;
4475 else
4476 return "";
4479 /* Search for COUNT instances of a line boundary, which means either a
4480 newline or (if selective display enabled) a carriage return.
4481 Start at START. If COUNT is negative, search backwards.
4483 If we find COUNT instances, set *SHORTAGE to zero, and return the
4484 position after the COUNTth match. Note that for reverse motion
4485 this is not the same as the usual convention for Emacs motion commands.
4487 If we don't find COUNT instances before reaching the end of the
4488 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
4489 the number of line boundaries left unfound, and return the end of the
4490 buffer we bumped up against. */
4492 static int
4493 display_scan_buffer (start, count, shortage)
4494 int *shortage, start;
4495 register int count;
4497 int limit = ((count > 0) ? ZV - 1 : BEGV);
4498 int direction = ((count > 0) ? 1 : -1);
4500 register unsigned char *cursor;
4501 unsigned char *base;
4503 register int ceiling;
4504 register unsigned char *ceiling_addr;
4506 /* If we are not in selective display mode,
4507 check only for newlines. */
4508 if (! (!NILP (current_buffer->selective_display)
4509 && !INTEGERP (current_buffer->selective_display)))
4510 return scan_buffer ('\n', start, 0, count, shortage, 0);
4512 /* The code that follows is like scan_buffer
4513 but checks for either newline or carriage return. */
4515 if (shortage != 0)
4516 *shortage = 0;
4518 if (count > 0)
4519 while (start != limit + 1)
4521 ceiling = BUFFER_CEILING_OF (start);
4522 ceiling = min (limit, ceiling);
4523 ceiling_addr = POS_ADDR (ceiling) + 1;
4524 base = (cursor = POS_ADDR (start));
4525 while (1)
4527 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
4529 if (cursor != ceiling_addr)
4531 if (--count == 0)
4533 immediate_quit = 0;
4534 return (start + cursor - base + 1);
4536 else
4537 if (++cursor == ceiling_addr)
4538 break;
4540 else
4541 break;
4543 start += cursor - base;
4545 else
4547 start--; /* first character we scan */
4548 while (start > limit - 1)
4549 { /* we WILL scan under start */
4550 ceiling = BUFFER_FLOOR_OF (start);
4551 ceiling = max (limit, ceiling);
4552 ceiling_addr = POS_ADDR (ceiling) - 1;
4553 base = (cursor = POS_ADDR (start));
4554 cursor++;
4555 while (1)
4557 while (--cursor != ceiling_addr
4558 && *cursor != '\n' && *cursor != 015)
4560 if (cursor != ceiling_addr)
4562 if (++count == 0)
4564 immediate_quit = 0;
4565 return (start + cursor - base + 1);
4568 else
4569 break;
4571 start += cursor - base;
4575 if (shortage != 0)
4576 *shortage = count * direction;
4577 return (start + ((direction == 1 ? 0 : 1)));
4580 /* Count up to N lines starting from FROM.
4581 But don't go beyond LIMIT.
4582 Return the number of lines thus found (always positive).
4583 Store the position after what was found into *POS_PTR. */
4585 static int
4586 display_count_lines (from, limit, n, pos_ptr)
4587 int from, limit, n;
4588 int *pos_ptr;
4590 int oldbegv = BEGV;
4591 int oldzv = ZV;
4592 int shortage = 0;
4594 if (limit < from)
4595 BEGV = limit;
4596 else
4597 ZV = limit;
4599 *pos_ptr = display_scan_buffer (from, n, &shortage);
4601 ZV = oldzv;
4602 BEGV = oldbegv;
4604 if (n < 0)
4605 /* When scanning backwards, scan_buffer stops *after* the last newline
4606 it finds, but does count it. Compensate for that. */
4607 return - n - shortage - (*pos_ptr != limit);
4608 return n - shortage;
4611 /* Display STRING on one line of window W, starting at HPOS.
4612 Display at position VPOS. Caller should have done get_display_line.
4613 If VPOS == -1, display it as the current frame's title.
4614 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
4616 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
4618 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
4619 MAXCOL is the last column ok to end at. Truncate here.
4620 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
4621 Both count from the left edge of the frame, as does HPOS.
4622 The right edge of W is an implicit maximum.
4623 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
4625 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
4626 at the place where the current window ends in this line
4627 and not display anything beyond there. Otherwise, only MAXCOL
4628 controls where to stop output.
4630 Returns ending hpos. */
4632 static int
4633 display_string (w, vpos, string, length, hpos, truncate,
4634 obey_window_width, mincol, maxcol)
4635 struct window *w;
4636 unsigned char *string;
4637 int length;
4638 int vpos, hpos;
4639 GLYPH truncate;
4640 int obey_window_width;
4641 int mincol, maxcol;
4643 register int c;
4644 int truncated;
4645 register GLYPH *p1;
4646 int hscroll = XINT (w->hscroll);
4647 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
4648 register GLYPH *start;
4649 register GLYPH *end;
4650 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
4651 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
4652 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
4653 int window_width = XFASTINT (w->width);
4654 /* If 1, we must display multibyte characters. */
4655 int multibyte = !NILP (XBUFFER (w->buffer)->enable_multibyte_characters);
4657 /* Use the standard display table, not the window's display table.
4658 We don't want the mode line in rot13. */
4659 register struct Lisp_Char_Table *dp = 0;
4660 int i;
4662 if (DISP_TABLE_P (Vstandard_display_table))
4663 dp = XCHAR_TABLE (Vstandard_display_table);
4665 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
4667 p1 = p1start;
4668 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
4670 if (obey_window_width)
4672 end = start + window_width - (truncate != 0);
4674 if (!WINDOW_RIGHTMOST_P (w))
4676 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4678 int i;
4680 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
4681 *end-- = ' ';
4683 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4684 *end-- = '|';
4688 if (! obey_window_width
4689 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
4690 end = desired_glyphs->glyphs[vpos] + maxcol;
4692 /* Store 0 in charstart for these columns. */
4693 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
4694 desired_glyphs->charstarts[vpos][i] = 0;
4696 if (maxcol >= 0 && mincol > maxcol)
4697 mincol = maxcol;
4699 if (length < 0)
4700 /* We need this value for multibyte characters. */
4701 length = strlen (string);
4703 /* We set truncated to 1 if we get stopped by trying to pass END
4704 (that is, trying to pass MAXCOL.) */
4705 truncated = 0;
4706 while (1)
4708 int len;
4710 if (length <= 0)
4711 break;
4712 if (multibyte)
4713 c = STRING_CHAR_AND_LENGTH (string, length, len);
4714 else
4715 c = *string, len = 1;
4717 string += len, length -= len;
4719 if (p1 >= end)
4721 truncated = 1;
4722 break;
4725 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
4727 p1 = copy_part_of_rope (f, p1, start,
4728 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
4729 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
4732 else if (c >= 040 && c < 0177)
4734 if (p1 >= start)
4735 *p1 = c;
4736 p1++;
4738 else if (c == '\t')
4742 if (p1 >= start && p1 < end)
4743 *p1 = SPACEGLYPH;
4744 p1++;
4746 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
4748 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
4750 if (p1 >= start)
4751 *p1 = (fix_glyph
4752 (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
4753 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
4754 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
4755 0));
4756 p1++;
4757 if (p1 >= start && p1 < end)
4758 *p1 = c ^ 0100;
4759 p1++;
4761 else if (len == 1)
4763 /* C is a control character or a binary byte data. */
4764 if (p1 >= start)
4765 *p1 = (fix_glyph
4766 (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
4767 && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
4768 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
4769 0));
4770 p1++;
4771 if (p1 >= start && p1 < end)
4772 *p1 = (c >> 6) + '0';
4773 p1++;
4774 if (p1 >= start && p1 < end)
4775 *p1 = (7 & (c >> 3)) + '0';
4776 p1++;
4777 if (p1 >= start && p1 < end)
4778 *p1 = (7 & c) + '0';
4779 p1++;
4781 else
4783 /* C is a multibyte character. */
4784 int charset = CHAR_CHARSET (c);
4785 int columns = (charset == CHARSET_COMPOSITION
4786 ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
4787 : CHARSET_WIDTH (charset));
4789 if (p1 < start)
4791 /* Since we can't show the left part of C, fill all
4792 columns with spaces. */
4793 columns -= start - p1;
4794 p1 = start;
4795 while (columns--)
4797 if (p1 < end)
4798 *p1 = SPACEGLYPH;
4799 p1++;
4802 else if (p1 + columns > end)
4804 /* Since we can't show the right part of C, fill all
4805 columns with TRUNCATE if TRUNCATE is specified. */
4806 if (truncate)
4808 while (p1 < end)
4809 *p1++ = fix_glyph (f, truncate, 0);
4810 /* And tell the line is truncated. */
4811 truncated = 1;
4813 break;
4815 else
4817 /* We can show the whole glyph of C. */
4818 *p1++ = c;
4819 while (--columns)
4820 *p1++ = c | GLYPH_MASK_PADDING;
4825 if (truncated)
4827 p1 = end;
4828 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
4830 else if (mincol >= 0)
4832 end = desired_glyphs->glyphs[vpos] + mincol;
4833 while (p1 < end)
4834 *p1++ = SPACEGLYPH;
4838 register int len = p1 - desired_glyphs->glyphs[vpos];
4840 if (len > desired_glyphs->used[vpos])
4841 desired_glyphs->used[vpos] = len;
4842 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
4844 return len;
4848 /* This is like a combination of memq and assq.
4849 Return 1 if PROPVAL appears as an element of LIST
4850 or as the car of an element of LIST.
4851 If PROPVAL is a list, compare each element against LIST
4852 in that way, and return 1 if any element of PROPVAL is found in LIST.
4853 Otherwise return 0.
4854 This function cannot quit. */
4857 invisible_p (propval, list)
4858 register Lisp_Object propval;
4859 Lisp_Object list;
4861 register Lisp_Object tail, proptail;
4862 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4864 register Lisp_Object tem;
4865 tem = XCONS (tail)->car;
4866 if (EQ (propval, tem))
4867 return 1;
4868 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4869 return 1;
4871 if (CONSP (propval))
4872 for (proptail = propval; CONSP (proptail);
4873 proptail = XCONS (proptail)->cdr)
4875 Lisp_Object propelt;
4876 propelt = XCONS (proptail)->car;
4877 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4879 register Lisp_Object tem;
4880 tem = XCONS (tail)->car;
4881 if (EQ (propelt, tem))
4882 return 1;
4883 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4884 return 1;
4887 return 0;
4890 /* Return 1 if PROPVAL appears as the car of an element of LIST
4891 and the cdr of that element is non-nil.
4892 If PROPVAL is a list, check each element of PROPVAL in that way,
4893 and the first time some element is found,
4894 return 1 if the cdr of that element is non-nil.
4895 Otherwise return 0.
4896 This function cannot quit. */
4899 invisible_ellipsis_p (propval, list)
4900 register Lisp_Object propval;
4901 Lisp_Object list;
4903 register Lisp_Object tail, proptail;
4904 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4906 register Lisp_Object tem;
4907 tem = XCONS (tail)->car;
4908 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4909 return ! NILP (XCONS (tem)->cdr);
4911 if (CONSP (propval))
4912 for (proptail = propval; CONSP (proptail);
4913 proptail = XCONS (proptail)->cdr)
4915 Lisp_Object propelt;
4916 propelt = XCONS (proptail)->car;
4917 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4919 register Lisp_Object tem;
4920 tem = XCONS (tail)->car;
4921 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4922 return ! NILP (XCONS (tem)->cdr);
4925 return 0;
4928 void
4929 syms_of_xdisp ()
4931 staticpro (&Qmenu_bar_update_hook);
4932 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
4934 staticpro (&Qoverriding_terminal_local_map);
4935 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
4937 staticpro (&Qoverriding_local_map);
4938 Qoverriding_local_map = intern ("overriding-local-map");
4940 staticpro (&Qwindow_scroll_functions);
4941 Qwindow_scroll_functions = intern ("window-scroll-functions");
4943 staticpro (&Qredisplay_end_trigger_functions);
4944 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
4946 staticpro (&last_arrow_position);
4947 staticpro (&last_arrow_string);
4948 last_arrow_position = Qnil;
4949 last_arrow_string = Qnil;
4951 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
4952 "String (or mode line construct) included (normally) in `mode-line-format'.");
4953 Vglobal_mode_string = Qnil;
4955 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
4956 "Marker for where to display an arrow on top of the buffer text.\n\
4957 This must be the beginning of a line in order to work.\n\
4958 See also `overlay-arrow-string'.");
4959 Voverlay_arrow_position = Qnil;
4961 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
4962 "String to display as an arrow. See also `overlay-arrow-position'.");
4963 Voverlay_arrow_string = Qnil;
4965 DEFVAR_INT ("scroll-step", &scroll_step,
4966 "*The number of lines to try scrolling a window by when point moves out.\n\
4967 If that fails to bring point back on frame, point is centered instead.\n\
4968 If this is zero, point is always centered after it moves off frame.");
4970 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
4971 "*Scroll up to this many lines, to bring point back on screen.");
4972 scroll_conservatively = 0;
4974 DEFVAR_INT ("scroll-margin", &scroll_margin,
4975 "*Number of lines of margin at the top and bottom of a window.\n\
4976 Recenter the window whenever point gets within this many lines\n\
4977 of the top or bottom of the window.");
4978 scroll_margin = 0;
4980 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
4982 DEFVAR_BOOL ("truncate-partial-width-windows",
4983 &truncate_partial_width_windows,
4984 "*Non-nil means truncate lines in all windows less than full frame wide.");
4985 truncate_partial_width_windows = 1;
4987 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
4988 "*Non-nil means use inverse video for the mode line.");
4989 mode_line_inverse_video = 1;
4991 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
4992 "*Maximum buffer size for which line number should be displayed.");
4993 line_number_display_limit = 1000000;
4995 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
4996 "*Non-nil means highlight region even in nonselected windows.");
4997 highlight_nonselected_windows = 0;
4999 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
5000 "Non-nil if more than one frame is visible on this display.\n\
5001 Minibuffer-only frames don't count, but iconified frames do.\n\
5002 This variable is not guaranteed to be accurate except while processing\n\
5003 `frame-title-format' and `icon-title-format'.");
5005 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
5006 "Template for displaying the titlebar of visible frames.\n\
5007 \(Assuming the window manager supports this feature.)\n\
5008 This variable has the same structure as `mode-line-format' (which see),\n\
5009 and is used only on frames for which no explicit name has been set\n\
5010 \(see `modify-frame-parameters').");
5011 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
5012 "Template for displaying the titlebar of an iconified frame.\n\
5013 \(Assuming the window manager supports this feature.)\n\
5014 This variable has the same structure as `mode-line-format' (which see),\n\
5015 and is used only on frames for which no explicit name has been set\n\
5016 \(see `modify-frame-parameters').");
5017 Vicon_title_format
5018 = Vframe_title_format
5019 = Fcons (intern ("multiple-frames"),
5020 Fcons (build_string ("%b"),
5021 Fcons (Fcons (build_string (""),
5022 Fcons (intern ("invocation-name"),
5023 Fcons (build_string ("@"),
5024 Fcons (intern ("system-name"),
5025 Qnil)))),
5026 Qnil)));
5028 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
5029 "Maximum number of lines to keep in the message log buffer.\n\
5030 If nil, disable message logging. If t, log messages but don't truncate\n\
5031 the buffer when it becomes large.");
5032 XSETFASTINT (Vmessage_log_max, 50);
5034 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
5035 "Functions called before redisplay, if window sizes have changed.\n\
5036 The value should be a list of functions that take one argument.\n\
5037 Just before redisplay, for each frame, if any of its windows have changed\n\
5038 size since the last redisplay, or have been split or deleted,\n\
5039 all the functions in the list are called, with the frame as argument.");
5040 Vwindow_size_change_functions = Qnil;
5042 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
5043 "List of Functions to call before redisplaying a window with scrolling.\n\
5044 Each function is called with two arguments, the window\n\
5045 and its new display-start position. Note that the value of `window-end'\n\
5046 is not valid when these functions are called.");
5047 Vwindow_scroll_functions = Qnil;
5050 /* initialize the window system */
5051 init_xdisp ()
5053 Lisp_Object root_window;
5054 #ifndef COMPILER_REGISTER_BUG
5055 register
5056 #endif /* COMPILER_REGISTER_BUG */
5057 struct window *mini_w;
5059 this_line_bufpos = 0;
5061 mini_w = XWINDOW (minibuf_window);
5062 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
5064 echo_area_glyphs = 0;
5065 previous_echo_glyphs = 0;
5067 if (!noninteractive)
5069 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
5070 XSETFASTINT (XWINDOW (root_window)->top, FRAME_MENU_BAR_LINES (f));
5071 set_window_height (root_window,
5072 FRAME_HEIGHT (f) - 1 - FRAME_MENU_BAR_LINES (f),
5074 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
5075 set_window_height (minibuf_window, 1, 0);
5077 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
5078 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));