1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
24 /*#include <ctype.h>*/
30 #include "dispextern.h"
36 #include "termhooks.h"
37 #include "intervals.h"
40 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
41 extern void set_frame_menubar ();
42 extern int pending_menu_activation
;
45 extern int interrupt_input
;
46 extern int command_loop_level
;
48 extern int minibuffer_auto_raise
;
50 extern Lisp_Object Qface
;
52 extern Lisp_Object Voverriding_local_map
;
53 extern Lisp_Object Voverriding_local_map_menu_flag
;
55 Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
56 Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
57 Lisp_Object Qredisplay_end_trigger_functions
;
59 /* Nonzero means print newline to stdout before next minibuffer message. */
61 int noninteractive_need_newline
;
63 /* Nonzero means print newline to message log before next message. */
65 static int message_log_need_newline
;
67 #define min(a, b) ((a) < (b) ? (a) : (b))
68 #define max(a, b) ((a) > (b) ? (a) : (b))
69 #define minmax(floor, val, ceil) \
70 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
72 /* The buffer position of the first character appearing
73 entirely or partially on the current frame line.
74 Or zero, which disables the optimization for the current frame line. */
75 static int this_line_bufpos
;
77 /* Number of characters past the end of this line,
78 including the terminating newline */
79 static int this_line_endpos
;
81 /* The vertical position of this frame line. */
82 static int this_line_vpos
;
84 /* Hpos value for start of display on this frame line.
85 Usually zero, but negative if first character really began
87 static int this_line_start_hpos
;
89 /* Buffer that this_line variables are describing. */
90 static struct buffer
*this_line_buffer
;
92 /* Value of echo_area_glyphs when it was last acted on.
93 If this is nonzero, there is a message on the frame
94 in the minibuffer and it should be erased as soon
95 as it is no longer requested to appear. */
96 char *previous_echo_glyphs
;
98 /* Nonzero means truncate lines in all windows less wide than the frame */
99 int truncate_partial_width_windows
;
101 /* Nonzero means we have more than one non-minibuffer-only frame.
102 Not guaranteed to be accurate except while parsing frame-title-format. */
105 Lisp_Object Vglobal_mode_string
;
107 /* Marker for where to display an arrow on top of the buffer text. */
108 Lisp_Object Voverlay_arrow_position
;
110 /* String to display for the arrow. */
111 Lisp_Object Voverlay_arrow_string
;
113 /* Like mode-line-format, but for the titlebar on a visible frame. */
114 Lisp_Object Vframe_title_format
;
116 /* Like mode-line-format, but for the titlebar on an iconified frame. */
117 Lisp_Object Vicon_title_format
;
119 /* List of functions to call when a window's size changes. These
120 functions get one arg, a frame on which one or more windows' sizes
122 static Lisp_Object Vwindow_size_change_functions
;
124 /* Values of those variables at last redisplay. */
125 static Lisp_Object last_arrow_position
, last_arrow_string
;
127 Lisp_Object Qmenu_bar_update_hook
;
129 /* Nonzero if overlay arrow has been displayed once in this window. */
130 static int overlay_arrow_seen
;
132 /* Nonzero if visible end of buffer has already been displayed once
133 in this window. (We need this variable in case there are overlay
134 strings that get displayed there.) */
135 static int zv_strings_seen
;
137 /* Nonzero means highlight the region even in nonselected windows. */
138 static int highlight_nonselected_windows
;
140 /* If cursor motion alone moves point off frame,
141 Try scrolling this many lines up or down if that will bring it back. */
142 static int scroll_step
;
144 /* Non-0 means scroll just far enough to bring point back on the screen,
146 static int scroll_conservatively
;
148 /* Recenter the window whenever point gets within this many lines
149 of the top or bottom of the window. */
152 /* Nonzero if try_window_id has made blank lines at window bottom
153 since the last redisplay that paused */
154 static int blank_end_of_window
;
156 /* Number of windows showing the buffer of the selected window
157 (or another buffer with the same base buffer).
158 keyboard.c refers to this. */
161 /* display_text_line sets these to the frame position (origin 0) of point,
162 whether the window is selected or not.
163 Set one to -1 first to determine whether point was found afterwards. */
165 static int cursor_vpos
;
166 static int cursor_hpos
;
168 static int debug_end_pos
;
170 /* Nonzero means display mode line highlighted */
171 int mode_line_inverse_video
;
173 static void redisplay_internal ();
174 static int message_log_check_duplicate ();
175 static void echo_area_display ();
176 void mark_window_display_accurate ();
177 static void redisplay_windows ();
178 static void redisplay_window ();
179 static void update_menu_bar ();
180 static void try_window ();
181 static int try_window_id ();
182 static struct position
*display_text_line ();
183 static void display_mode_line ();
184 static int display_mode_element ();
185 static char *decode_mode_spec ();
186 static int display_string ();
187 static void display_menu_bar ();
188 static int display_count_lines ();
190 /* Prompt to display in front of the minibuffer contents */
191 Lisp_Object minibuf_prompt
;
193 /* Width in columns of current minibuffer prompt. */
194 int minibuf_prompt_width
;
196 /* Message to display instead of minibuffer contents
197 This is what the functions error and message make,
198 and command echoing uses it as well.
199 It overrides the minibuf_prompt as well as the buffer. */
200 char *echo_area_glyphs
;
202 /* This is the length of the message in echo_area_glyphs. */
203 int echo_area_glyphs_length
;
205 /* This is the window where the echo area message was displayed.
206 It is always a minibuffer window, but it may not be the
207 same window currently active as a minibuffer. */
208 Lisp_Object echo_area_window
;
210 /* true iff we should redraw the mode lines on the next redisplay */
211 int update_mode_lines
;
213 /* Smallest number of characters before the gap
214 at any time since last redisplay that finished.
215 Valid for current buffer when try_window_id can be called. */
218 /* Smallest number of characters after the gap
219 at any time since last redisplay that finished.
220 Valid for current buffer when try_window_id can be called. */
223 /* MODIFF as of last redisplay that finished;
224 if it matches MODIFF, and overlay_unchanged_modified
225 matches OVERLAY_MODIFF, that means beg_unchanged and end_unchanged
226 contain no useful information */
227 int unchanged_modified
;
229 /* OVERLAY_MODIFF as of last redisplay that finished. */
230 int overlay_unchanged_modified
;
232 /* Nonzero if window sizes or contents have changed
233 since last redisplay that finished */
234 int windows_or_buffers_changed
;
236 /* Nonzero after display_mode_line if %l was used
237 and it displayed a line number. */
238 int line_number_displayed
;
240 /* Maximum buffer size for which to display line numbers. */
241 static int line_number_display_limit
;
243 /* Number of lines to keep in the message log buffer.
244 t means infinite. nil means don't log at all. */
245 Lisp_Object Vmessage_log_max
;
247 /* Output a newline in the *Messages* buffer if "needs" one. */
250 message_log_maybe_newline ()
252 if (message_log_need_newline
)
253 message_dolog ("", 0, 1);
257 /* Add a string to the message log, optionally terminated with a newline.
258 This function calls low-level routines in order to bypass text property
259 hooks, etc. which might not be safe to run. */
262 message_dolog (m
, len
, nlflag
)
266 if (!NILP (Vmessage_log_max
))
268 struct buffer
*oldbuf
;
269 int oldpoint
, oldbegv
, oldzv
;
270 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
272 oldbuf
= current_buffer
;
273 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
274 current_buffer
->undo_list
= Qt
;
281 oldpoint
+= len
+ nlflag
;
283 oldzv
+= len
+ nlflag
;
286 insert_1 (m
, len
, 1, 0);
289 int this_bol
, prev_bol
, dup
;
290 insert_1 ("\n", 1, 1, 0);
292 this_bol
= scan_buffer ('\n', Z
, 0, -2, 0, 0);
295 prev_bol
= scan_buffer ('\n', this_bol
, 0, -2, 0, 0);
296 dup
= message_log_check_duplicate (prev_bol
, this_bol
);
299 if (oldpoint
> prev_bol
)
300 oldpoint
-= min (this_bol
, oldpoint
) - prev_bol
;
301 if (oldbegv
> prev_bol
)
302 oldbegv
-= min (this_bol
, oldbegv
) - prev_bol
;
303 if (oldzv
> prev_bol
)
304 oldzv
-= min (this_bol
, oldzv
) - prev_bol
;
305 del_range_1 (prev_bol
, this_bol
, 0);
311 /* If you change this format, don't forget to also
312 change message_log_check_duplicate. */
313 sprintf (dupstr
, " [%d times]", dup
);
314 duplen
= strlen (dupstr
);
320 insert_1 (dupstr
, duplen
, 1, 0);
325 if (NATNUMP (Vmessage_log_max
))
327 int pos
= scan_buffer ('\n', Z
, 0,
328 -XFASTINT (Vmessage_log_max
) - 1, 0, 0);
329 oldpoint
-= min (pos
, oldpoint
) - BEG
;
330 oldbegv
-= min (pos
, oldbegv
) - BEG
;
331 oldzv
-= min (pos
, oldzv
) - BEG
;
332 del_range_1 (BEG
, pos
, 0);
337 TEMP_SET_PT (oldpoint
);
338 set_buffer_internal (oldbuf
);
339 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
340 message_log_need_newline
= !nlflag
;
344 /* We are at the end of the buffer after just having inserted a newline.
345 (Note: We depend on the fact we won't be crossing the gap.)
346 Check to see if the most recent message looks a lot like the previous one.
347 Return 0 if different, 1 if the new one should just replace it, or a
348 value N > 1 if we should also append " [N times]". */
351 message_log_check_duplicate (prev_bol
, this_bol
)
352 int prev_bol
, this_bol
;
355 int len
= Z
- 1 - this_bol
;
357 unsigned char *p1
= BUF_CHAR_ADDRESS (current_buffer
, prev_bol
);
358 unsigned char *p2
= BUF_CHAR_ADDRESS (current_buffer
, this_bol
);
360 for (i
= 0; i
< len
; i
++)
362 if (i
>= 3 && p1
[i
-3] == '.' && p1
[i
-2] == '.' && p1
[i
-1] == '.'
371 if (*p1
++ == ' ' && *p1
++ == '[')
374 while (*p1
>= '0' && *p1
<= '9')
375 n
= n
* 10 + *p1
++ - '0';
376 if (strncmp (p1
, " times]\n", 8) == 0)
382 /* Display an echo area message M with a specified length of LEN chars.
383 The string may include null characters. If M is 0, clear out any
384 existing message, and let the minibuffer text show through.
386 The buffer M must continue to exist until after the echo area
387 gets cleared or some other message gets displayed there.
389 Do not pass text that is stored in a Lisp string.
390 Do not pass text in a buffer that was alloca'd. */
397 /* First flush out any partial line written with print. */
398 message_log_maybe_newline ();
400 message_dolog (m
, len
, 1);
401 message2_nolog (m
, len
);
405 /* The non-logging counterpart of message2. */
408 message2_nolog (m
, len
)
414 if (noninteractive_need_newline
)
416 noninteractive_need_newline
= 0;
417 fwrite (m
, len
, 1, stderr
);
418 if (cursor_in_echo_area
== 0)
419 fprintf (stderr
, "\n");
422 /* A null message buffer means that the frame hasn't really been
423 initialized yet. Error messages get reported properly by
424 cmd_error, so this must be just an informative message; toss it. */
425 else if (INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
427 Lisp_Object mini_window
;
430 /* Get the frame containing the minibuffer
431 that the selected frame is using. */
432 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
433 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
435 FRAME_SAMPLE_VISIBILITY (f
);
436 if (FRAME_VISIBLE_P (selected_frame
)
437 && ! FRAME_VISIBLE_P (f
))
438 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window
)));
442 echo_area_glyphs
= m
;
443 echo_area_glyphs_length
= len
;
445 if (minibuffer_auto_raise
)
446 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window
)));
449 echo_area_glyphs
= previous_echo_glyphs
= 0;
451 do_pending_window_change ();
452 echo_area_display ();
453 update_frame (f
, 1, 1);
454 do_pending_window_change ();
455 if (frame_up_to_date_hook
!= 0 && ! gc_in_progress
)
456 (*frame_up_to_date_hook
) (f
);
460 /* Display a null-terminated echo area message M. If M is 0, clear out any
461 existing message, and let the minibuffer text show through.
463 The buffer M must continue to exist until after the echo area
464 gets cleared or some other message gets displayed there.
466 Do not pass text that is stored in a Lisp string.
467 Do not pass text in a buffer that was alloca'd. */
473 message2 (m
, (m
? strlen (m
) : 0));
480 message2_nolog (m
, (m
? strlen (m
) : 0));
483 /* Truncate what will be displayed in the echo area
484 the next time we display it--but don't redisplay it now. */
487 truncate_echo_area (len
)
490 /* A null message buffer means that the frame hasn't really been
491 initialized yet. Error messages get reported properly by
492 cmd_error, so this must be just an informative message; toss it. */
493 if (!noninteractive
&& INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
494 echo_area_glyphs_length
= len
;
497 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
498 zero if being used by message. */
499 int message_buf_print
;
501 /* Dump an informative message to the minibuf. If M is 0, clear out
502 any existing message, and let the minibuffer text show through. */
506 message (m
, a1
, a2
, a3
)
508 EMACS_INT a1
, a2
, a3
;
514 if (noninteractive_need_newline
)
516 noninteractive_need_newline
= 0;
517 fprintf (stderr
, m
, a1
, a2
, a3
);
518 if (cursor_in_echo_area
== 0)
519 fprintf (stderr
, "\n");
523 else if (INTERACTIVE
)
525 /* The frame whose minibuffer we're going to display the message on.
526 It may be larger than the selected frame, so we need
527 to use its buffer, not the selected frame's buffer. */
528 Lisp_Object mini_window
;
531 /* Get the frame containing the minibuffer
532 that the selected frame is using. */
533 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
534 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
536 /* A null message buffer means that the frame hasn't really been
537 initialized yet. Error messages get reported properly by
538 cmd_error, so this must be just an informative message; toss it. */
539 if (FRAME_MESSAGE_BUF (f
))
550 len
= doprnt (FRAME_MESSAGE_BUF (f
),
551 (int) FRAME_WIDTH (f
), m
, (char *)0, 3, a
);
553 len
= doprnt (FRAME_MESSAGE_BUF (f
),
554 (int) FRAME_WIDTH (f
), m
, (char *)0, 3, &a1
);
555 #endif /* NO_ARG_ARRAY */
557 message2 (FRAME_MESSAGE_BUF (f
), len
);
562 /* Print should start at the beginning of the message
564 message_buf_print
= 0;
569 /* The non-logging version of message. */
571 message_nolog (m
, a1
, a2
, a3
)
573 EMACS_INT a1
, a2
, a3
;
575 Lisp_Object old_log_max
;
576 old_log_max
= Vmessage_log_max
;
577 Vmessage_log_max
= Qnil
;
578 message (m
, a1
, a2
, a3
);
579 Vmessage_log_max
= old_log_max
;
585 message2 (echo_area_glyphs
, echo_area_glyphs_length
);
593 Lisp_Object mini_window
;
595 /* Choose the minibuffer window for this display.
596 It is the minibuffer window used by the selected frame. */
597 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
598 /* This is the frame that window is in. */
599 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
601 if (! FRAME_VISIBLE_P (f
))
606 redraw_garbaged_frames ();
610 if (echo_area_glyphs
|| minibuf_level
== 0)
614 echo_area_window
= mini_window
;
616 vpos
= XFASTINT (XWINDOW (mini_window
)->top
);
617 get_display_line (f
, vpos
, 0);
619 /* Make sure the columns that overlap a left-hand scroll bar
621 for (i
= 0; i
< FRAME_LEFT_SCROLL_BAR_WIDTH (f
); i
++)
622 f
->desired_glyphs
->glyphs
[vpos
][i
] = SPACEGLYPH
;
624 display_string (XWINDOW (mini_window
), vpos
,
625 echo_area_glyphs
? echo_area_glyphs
: "",
626 echo_area_glyphs
? echo_area_glyphs_length
: -1,
627 FRAME_LEFT_SCROLL_BAR_WIDTH (f
),
628 0, 0, 0, FRAME_WIDTH (f
));
630 #if 0 /* This just gets in the way. update_frame does the job. */
631 /* If desired cursor location is on this line, put it at end of text */
632 if (cursor_in_echo_area
)
633 FRAME_CURSOR_Y (f
) = vpos
;
634 if (FRAME_CURSOR_Y (f
) == vpos
)
635 FRAME_CURSOR_X (f
) = FRAME_DESIRED_GLYPHS (f
)->used
[vpos
];
638 /* Fill the rest of the minibuffer window with blank lines. */
643 i
< vpos
+ XFASTINT (XWINDOW (mini_window
)->height
); i
++)
645 get_display_line (f
, i
, 0);
646 display_string (XWINDOW (mini_window
), vpos
,
648 FRAME_LEFT_SCROLL_BAR_WIDTH (f
),
649 0, 0, 0, FRAME_WIDTH (f
));
653 else if (!EQ (mini_window
, selected_window
))
654 windows_or_buffers_changed
++;
656 if (EQ (mini_window
, selected_window
))
657 this_line_bufpos
= 0;
659 previous_echo_glyphs
= echo_area_glyphs
;
662 /* Update frame titles. */
664 #ifdef HAVE_WINDOW_SYSTEM
665 static char frame_title_buf
[512];
666 static char *frame_title_ptr
;
669 store_frame_title (str
, mincol
, maxcol
)
674 if (maxcol
< 0 || maxcol
>= sizeof(frame_title_buf
))
675 maxcol
= sizeof (frame_title_buf
);
676 limit
= &frame_title_buf
[maxcol
];
677 while (*str
!= '\0' && frame_title_ptr
< limit
)
678 *frame_title_ptr
++ = *str
++;
679 while (frame_title_ptr
< &frame_title_buf
[mincol
])
680 *frame_title_ptr
++ = ' ';
681 return frame_title_ptr
- frame_title_buf
;
685 x_consider_frame_title (frame
)
691 FRAME_PTR f
= XFRAME (frame
);
693 if (!(FRAME_WINDOW_P (f
) || FRAME_MINIBUF_ONLY_P (f
) || f
->explicit_name
))
696 /* Do we have more than one visible frame on this X display? */
700 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
702 FRAME_PTR tf
= XFRAME (XCONS (tail
)->car
);
704 if (tf
!= f
&& FRAME_KBOARD (tf
) == FRAME_KBOARD (f
)
705 && !FRAME_MINIBUF_ONLY_P (tf
)
706 && (FRAME_VISIBLE_P (tf
) || FRAME_ICONIFIED_P (tf
)))
710 multiple_frames
= CONSP (tail
);
713 obuf
= current_buffer
;
714 Fset_buffer (XWINDOW (f
->selected_window
)->buffer
);
715 fmt
= (FRAME_ICONIFIED_P (f
) ? Vicon_title_format
: Vframe_title_format
);
716 frame_title_ptr
= frame_title_buf
;
717 len
= display_mode_element (XWINDOW (f
->selected_window
), 0, 0, 0,
718 0, sizeof (frame_title_buf
), fmt
);
720 set_buffer_internal (obuf
);
721 /* Set the name only if it's changed. This avoids consing
722 in the common case where it hasn't. (If it turns out that we've
723 already wasted too much time by walking through the list with
724 display_mode_element, then we might need to optimize at a higher
726 if (! STRINGP (f
->name
) || XSTRING (f
->name
)->size
!= len
727 || bcmp (frame_title_buf
, XSTRING (f
->name
)->data
, len
) != 0)
728 x_implicitly_set_name (f
, make_string (frame_title_buf
, len
), Qnil
);
731 #define frame_title_ptr ((char *)0)
732 #define store_frame_title(str, mincol, maxcol) 0
735 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
736 This can call eval. */
741 register struct window
*w
= XWINDOW (selected_window
);
743 struct gcpro gcpro1
, gcpro2
;
745 all_windows
= (update_mode_lines
|| buffer_shared
> 1
746 || windows_or_buffers_changed
);
748 /* Update all frame titles based on their buffer names, etc.
749 We do this before the menu bars so that the buffer-menu
750 will show the up-to-date frame titles.
752 This used to be done after the menu bars, for a reason that
753 was stated as follows but which I do not understand:
754 "We do this after the menu bars so that the frame will first
755 create its menu bar using the name `emacs' if no other name
756 has yet been specified."
757 I think that is no longer a concern. */
758 #ifdef HAVE_WINDOW_SYSTEM
759 if (windows_or_buffers_changed
|| update_mode_lines
)
761 Lisp_Object tail
, frame
;
763 FOR_EACH_FRAME (tail
, frame
)
764 if (FRAME_VISIBLE_P (XFRAME (frame
))
765 || FRAME_ICONIFIED_P (XFRAME (frame
)))
766 x_consider_frame_title (frame
);
770 /* Update the menu bar item lists, if appropriate.
771 This has to be done before any actual redisplay
772 or generation of display lines. */
775 Lisp_Object tail
, frame
;
776 int count
= specpdl_ptr
- specpdl
;
778 record_unwind_protect (Fstore_match_data
, Fmatch_data (Qnil
, Qnil
));
780 FOR_EACH_FRAME (tail
, frame
)
782 /* If a window on this frame changed size,
783 report that to the user and clear the size-change flag. */
784 if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame
)))
786 Lisp_Object functions
;
787 /* Clear flag first in case we get error below. */
788 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame
)) = 0;
789 functions
= Vwindow_size_change_functions
;
790 GCPRO2 (tail
, functions
);
791 while (CONSP (functions
))
793 call1 (XCONS (functions
)->car
, frame
);
794 functions
= XCONS (functions
)->cdr
;
799 update_menu_bar (XFRAME (frame
), 0);
803 unbind_to (count
, Qnil
);
806 update_menu_bar (selected_frame
, 1);
808 /* Motif needs this. See comment in xmenu.c.
809 Turn it off when pending_menu_activation is not defined. */
811 pending_menu_activation
= 0;
815 /* Do a frame update, taking possible shortcuts into account.
816 This is the main external entry point for redisplay.
818 If the last redisplay displayed an echo area message and that
819 message is no longer requested, we clear the echo area
820 or bring back the minibuffer if that is in use.
822 Do not call eval from within this function.
823 Calls to eval after the call to echo_area_display would confuse
824 the display_line mechanism and would cause a crash.
825 Calls to eval before that point will work most of the time,
826 but can still lose, because this function
827 can be called from signal handlers; with alarms set up;
828 or with synchronous processes running.
830 See Fcall_process; if you called it from here, it could be
831 entered recursively. */
833 static int do_verify_charstarts
;
835 /* Counter is used to clear the face cache
836 no more than once ever 1000 redisplays. */
837 static int clear_face_cache_count
;
839 /* Record the previous terminal frame we displayed. */
840 static FRAME_PTR previous_terminal_frame
;
845 redisplay_internal (0);
848 /* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay
849 is not in response to any user action; therefore, we should
850 preserve the echo area. (Actually, our caller does that job.)
851 Perhaps in the future avoid recentering windows
852 if it is not necessary; currently that causes some problems. */
855 redisplay_internal (preserve_echo_area
)
856 int preserve_echo_area
;
858 register struct window
*w
= XWINDOW (selected_window
);
862 register int tlbufpos
, tlendpos
;
869 if (popup_activated ())
873 if (! FRAME_WINDOW_P (selected_frame
)
874 && previous_terminal_frame
!= selected_frame
)
876 /* Since frames on an ASCII terminal share the same display area,
877 displaying a different frame means redisplay the whole thing. */
878 windows_or_buffers_changed
++;
879 SET_FRAME_GARBAGED (selected_frame
);
880 XSETFRAME (Vterminal_frame
, selected_frame
);
882 previous_terminal_frame
= selected_frame
;
884 /* Set the visible flags for all frames.
885 Do this before checking for resized or garbaged frames; they want
886 to know if their frames are visible.
887 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
889 Lisp_Object tail
, frame
;
891 FOR_EACH_FRAME (tail
, frame
)
893 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
895 /* Clear out all the display lines in which we will generate the
896 glyphs to display. */
897 init_desired_glyphs (XFRAME (frame
));
901 /* Notice any pending interrupt request to change frame size. */
902 do_pending_window_change ();
906 redraw_garbaged_frames ();
910 prepare_menu_bars ();
912 if (windows_or_buffers_changed
)
915 /* Detect case that we need to write or remove a star in the mode line. */
916 if ((SAVE_MODIFF
< MODIFF
) != !NILP (w
->last_had_star
))
918 w
->update_mode_line
= Qt
;
919 if (buffer_shared
> 1)
923 /* If %c is in use, update it if needed. */
924 if (!NILP (w
->column_number_displayed
)
925 /* This alternative quickly identifies a common case
926 where no change is needed. */
927 && !(PT
== XFASTINT (w
->last_point
)
928 && XFASTINT (w
->last_modified
) >= MODIFF
929 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
)
930 && XFASTINT (w
->column_number_displayed
) != current_column ())
931 w
->update_mode_line
= Qt
;
933 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w
->frame
)) = -1;
935 all_windows
= update_mode_lines
|| buffer_shared
> 1;
937 /* If specs for an arrow have changed, do thorough redisplay
938 to ensure we remove any arrow that should no longer exist. */
939 if (! EQ (Voverlay_arrow_position
, last_arrow_position
)
940 || ! EQ (Voverlay_arrow_string
, last_arrow_string
))
943 /* Normally the message* functions will have already displayed and
944 updated the echo area, but the frame may have been trashed, or
945 the update may have been preempted, so display the echo area
947 if (echo_area_glyphs
|| previous_echo_glyphs
)
949 echo_area_display ();
953 /* If showing region, and mark has changed, must redisplay whole window. */
954 if (((!NILP (Vtransient_mark_mode
)
955 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
956 != !NILP (w
->region_showing
))
957 || (!NILP (w
->region_showing
)
958 && !EQ (w
->region_showing
,
959 Fmarker_position (XBUFFER (w
->buffer
)->mark
))))
960 this_line_bufpos
= -1;
962 tlbufpos
= this_line_bufpos
;
963 tlendpos
= this_line_endpos
;
964 if (!all_windows
&& tlbufpos
> 0 && NILP (w
->update_mode_line
)
965 && !current_buffer
->clip_changed
966 && FRAME_VISIBLE_P (XFRAME (w
->frame
))
967 /* Make sure recorded data applies to current buffer, etc */
968 && this_line_buffer
== current_buffer
969 && current_buffer
== XBUFFER (w
->buffer
)
970 && NILP (w
->force_start
)
971 /* Point must be on the line that we have info recorded about */
973 && PT
<= Z
- tlendpos
974 /* All text outside that line, including its final newline,
976 && ((XFASTINT (w
->last_modified
) >= MODIFF
977 && (XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
))
978 || (beg_unchanged
>= tlbufpos
- 1
980 /* If selective display, can't optimize
981 if the changes start at the beginning of the line. */
982 && ((INTEGERP (current_buffer
->selective_display
)
983 && XINT (current_buffer
->selective_display
) > 0
984 ? (beg_unchanged
>= tlbufpos
987 && end_unchanged
>= tlendpos
988 && Z
- GPT
>= tlendpos
)))
990 if (tlbufpos
> BEGV
&& FETCH_CHAR (tlbufpos
- 1) != '\n'
992 || FETCH_CHAR (tlbufpos
) == '\n'))
993 /* Former continuation line has disappeared by becoming empty */
995 else if (XFASTINT (w
->last_modified
) < MODIFF
996 || XFASTINT (w
->last_overlay_modified
) < OVERLAY_MODIFF
997 || MINI_WINDOW_P (w
))
1000 overlay_arrow_seen
= 0;
1001 zv_strings_seen
= 0;
1002 display_text_line (w
, tlbufpos
, this_line_vpos
, this_line_start_hpos
,
1003 pos_tab_offset (w
, tlbufpos
), 0);
1004 /* If line contains point, is not continued,
1005 and ends at same distance from eob as before, we win */
1006 if (cursor_vpos
>= 0 && this_line_bufpos
1007 && this_line_endpos
== tlendpos
)
1009 /* If this is not the window's last line,
1010 we must adjust the charstarts of the lines below. */
1011 if (this_line_vpos
+ 1
1012 < XFASTINT (w
->top
) + window_internal_height (w
))
1014 int left
= WINDOW_LEFT_MARGIN (w
);
1015 int *charstart_next_line
1016 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w
)))->charstarts
[this_line_vpos
+ 1];
1019 if (Z
- tlendpos
== ZV
)
1020 /* This line ends at end of (accessible part of) buffer.
1021 There is no newline to count. */
1022 adjust
= Z
- tlendpos
- charstart_next_line
[left
];
1024 /* This line ends in a newline.
1025 Must take account of the newline and the rest of the
1026 text that follows. */
1027 adjust
= Z
- tlendpos
+ 1 - charstart_next_line
[left
];
1029 adjust_window_charstarts (w
, this_line_vpos
, adjust
);
1032 if (!WINDOW_FULL_WIDTH_P (w
))
1033 preserve_other_columns (w
);
1039 else if (PT
== XFASTINT (w
->last_point
)
1040 /* Make sure the cursor was last displayed
1041 in this window. Otherwise we have to reposition it. */
1042 && XINT (w
->top
) <= FRAME_CURSOR_Y (selected_frame
)
1043 && (XINT (w
->top
) + XINT (w
->height
)
1044 > FRAME_CURSOR_Y (selected_frame
)))
1048 do_pending_window_change ();
1053 /* If highlighting the region, or if the cursor is in the echo area,
1054 then we can't just move the cursor. */
1055 else if (! (!NILP (Vtransient_mark_mode
)
1056 && !NILP (current_buffer
->mark_active
))
1057 && w
== XWINDOW (current_buffer
->last_selected_window
)
1058 && NILP (w
->region_showing
)
1059 && !cursor_in_echo_area
)
1061 pos
= *compute_motion (tlbufpos
, 0,
1062 XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0,
1064 PT
, 2, - (1 << (BITS_PER_SHORT
- 1)),
1065 window_internal_width (w
) - 1,
1067 pos_tab_offset (w
, tlbufpos
), w
);
1070 int width
= window_internal_width (w
) - 1;
1071 FRAME_CURSOR_X (selected_frame
)
1072 = WINDOW_LEFT_MARGIN (w
) + minmax (0, pos
.hpos
, width
);
1073 FRAME_CURSOR_Y (selected_frame
) = this_line_vpos
;
1080 /* Text changed drastically or point moved off of line */
1081 cancel_line (this_line_vpos
, selected_frame
);
1084 this_line_bufpos
= 0;
1085 all_windows
|= buffer_shared
> 1;
1087 clear_face_cache_count
++;
1091 Lisp_Object tail
, frame
;
1094 /* Clear the face cache, only when we do a full redisplay
1095 and not too often either. */
1096 if (clear_face_cache_count
> 1000)
1098 clear_face_cache ();
1099 clear_face_cache_count
= 0;
1103 /* Recompute # windows showing selected buffer.
1104 This will be incremented each time such a window is displayed. */
1107 FOR_EACH_FRAME (tail
, frame
)
1109 FRAME_PTR f
= XFRAME (frame
);
1110 if (FRAME_WINDOW_P (f
) || f
== selected_frame
)
1113 /* Mark all the scroll bars to be removed; we'll redeem the ones
1114 we want when we redisplay their windows. */
1115 if (condemn_scroll_bars_hook
)
1116 (*condemn_scroll_bars_hook
) (f
);
1118 if (FRAME_VISIBLE_P (f
))
1119 redisplay_windows (FRAME_ROOT_WINDOW (f
), preserve_echo_area
);
1121 /* Any scroll bars which redisplay_windows should have nuked
1122 should now go away. */
1123 if (judge_scroll_bars_hook
)
1124 (*judge_scroll_bars_hook
) (f
);
1128 else if (FRAME_VISIBLE_P (selected_frame
))
1130 redisplay_window (selected_window
, 1, preserve_echo_area
);
1131 if (!WINDOW_FULL_WIDTH_P (w
))
1132 preserve_other_columns (w
);
1136 /* Prevent various kinds of signals during display update.
1137 stdio is not robust about handling signals,
1138 which can cause an apparent I/O error. */
1139 if (interrupt_input
)
1149 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1153 if (!FRAMEP (XCONS (tail
)->car
))
1156 f
= XFRAME (XCONS (tail
)->car
);
1158 if ((FRAME_WINDOW_P (f
) || f
== selected_frame
)
1159 && FRAME_VISIBLE_P (f
))
1161 pause
|= update_frame (f
, 0, 0);
1164 mark_window_display_accurate (f
->root_window
, 1);
1165 if (frame_up_to_date_hook
!= 0)
1166 (*frame_up_to_date_hook
) (f
);
1173 if (FRAME_VISIBLE_P (selected_frame
))
1174 pause
= update_frame (selected_frame
, 0, 0);
1178 /* We may have called echo_area_display at the top of this
1179 function. If the echo area is on another frame, that may
1180 have put text on a frame other than the selected one, so the
1181 above call to update_frame would not have caught it. Catch
1184 Lisp_Object mini_window
;
1185 FRAME_PTR mini_frame
;
1187 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
1188 mini_frame
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
1190 if (mini_frame
!= selected_frame
&& FRAME_WINDOW_P (mini_frame
))
1191 pause
|= update_frame (mini_frame
, 0, 0);
1195 /* If frame does not match, prevent doing single-line-update next time.
1196 Also, don't forget to check every line to update the arrow. */
1199 this_line_bufpos
= 0;
1200 if (!NILP (last_arrow_position
))
1202 last_arrow_position
= Qt
;
1203 last_arrow_string
= Qt
;
1205 /* If we pause after scrolling, some lines in current_frame
1206 may be null, so preserve_other_columns won't be able to
1207 preserve all the vertical-bar separators. So, avoid using it
1209 if (!WINDOW_FULL_WIDTH_P (w
))
1210 update_mode_lines
= 1;
1213 /* Now text on frame agrees with windows, so
1214 put info into the windows for partial redisplay to follow */
1218 register struct buffer
*b
= XBUFFER (w
->buffer
);
1220 blank_end_of_window
= 0;
1221 unchanged_modified
= BUF_MODIFF (b
);
1222 overlay_unchanged_modified
= BUF_OVERLAY_MODIFF (b
);
1223 beg_unchanged
= BUF_GPT (b
) - BUF_BEG (b
);
1224 end_unchanged
= BUF_Z (b
) - BUF_GPT (b
);
1226 XSETFASTINT (w
->last_point
, BUF_PT (b
));
1227 XSETFASTINT (w
->last_point_x
, FRAME_CURSOR_X (selected_frame
));
1228 XSETFASTINT (w
->last_point_y
, FRAME_CURSOR_Y (selected_frame
));
1231 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame
), 1);
1234 b
->clip_changed
= 0;
1235 w
->update_mode_line
= Qnil
;
1236 XSETFASTINT (w
->last_modified
, BUF_MODIFF (b
));
1237 XSETFASTINT (w
->last_overlay_modified
, BUF_OVERLAY_MODIFF (b
));
1239 = (BUF_MODIFF (XBUFFER (w
->buffer
)) > BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))
1241 w
->window_end_valid
= w
->buffer
;
1242 last_arrow_position
= Voverlay_arrow_position
;
1243 last_arrow_string
= Voverlay_arrow_string
;
1244 if (do_verify_charstarts
)
1245 verify_charstarts (w
);
1246 if (frame_up_to_date_hook
!= 0)
1247 (*frame_up_to_date_hook
) (selected_frame
);
1249 update_mode_lines
= 0;
1250 windows_or_buffers_changed
= 0;
1253 /* Start SIGIO interrupts coming again.
1254 Having them off during the code above
1255 makes it less likely one will discard output,
1256 but not impossible, since there might be stuff
1257 in the system buffer here.
1258 But it is much hairier to try to do anything about that. */
1260 if (interrupt_input
)
1264 /* Change frame size now if a change is pending. */
1265 do_pending_window_change ();
1267 /* If we just did a pending size change, redisplay again
1268 for the new size. */
1269 if (windows_or_buffers_changed
&& !pause
)
1273 /* Redisplay, but leave alone any recent echo area message
1274 unless another message has been requested in its place.
1276 This is useful in situations where you need to redisplay but no
1277 user action has occurred, making it inappropriate for the message
1278 area to be cleared. See tracking_off and
1279 wait_reading_process_input for examples of these situations. */
1281 redisplay_preserve_echo_area ()
1283 if (echo_area_glyphs
== 0 && previous_echo_glyphs
!= 0)
1285 echo_area_glyphs
= previous_echo_glyphs
;
1286 redisplay_internal (1);
1287 echo_area_glyphs
= 0;
1290 redisplay_internal (1);
1294 mark_window_display_accurate (window
, flag
)
1298 register struct window
*w
;
1300 for (;!NILP (window
); window
= w
->next
)
1302 if (!WINDOWP (window
)) abort ();
1303 w
= XWINDOW (window
);
1305 if (!NILP (w
->buffer
))
1307 XSETFASTINT (w
->last_modified
,
1308 !flag
? 0 : BUF_MODIFF (XBUFFER (w
->buffer
)));
1309 XSETFASTINT (w
->last_overlay_modified
,
1310 !flag
? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)));
1312 = (BUF_MODIFF (XBUFFER (w
->buffer
)) > BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))
1315 /* Record if we are showing a region, so can make sure to
1316 update it fully at next redisplay. */
1317 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
1318 && w
== XWINDOW (current_buffer
->last_selected_window
)
1319 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
1320 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
1324 w
->window_end_valid
= w
->buffer
;
1325 w
->update_mode_line
= Qnil
;
1326 if (!NILP (w
->buffer
) && flag
)
1327 XBUFFER (w
->buffer
)->clip_changed
= 0;
1329 if (!NILP (w
->vchild
))
1330 mark_window_display_accurate (w
->vchild
, flag
);
1331 if (!NILP (w
->hchild
))
1332 mark_window_display_accurate (w
->hchild
, flag
);
1337 last_arrow_position
= Voverlay_arrow_position
;
1338 last_arrow_string
= Voverlay_arrow_string
;
1342 /* t is unequal to any useful value of Voverlay_arrow_... */
1343 last_arrow_position
= Qt
;
1344 last_arrow_string
= Qt
;
1348 /* Update the menu bar item list for frame F.
1349 This has to be done before we start to fill in any display lines,
1350 because it can call eval.
1352 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1355 update_menu_bar (f
, save_match_data
)
1357 int save_match_data
;
1359 struct buffer
*old
= current_buffer
;
1361 register struct window
*w
;
1363 window
= FRAME_SELECTED_WINDOW (f
);
1364 w
= XWINDOW (window
);
1366 if (update_mode_lines
)
1367 w
->update_mode_line
= Qt
;
1369 if (FRAME_WINDOW_P (f
)
1371 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1372 FRAME_EXTERNAL_MENU_BAR (f
)
1374 FRAME_MENU_BAR_LINES (f
) > 0
1376 : FRAME_MENU_BAR_LINES (f
) > 0)
1378 /* If the user has switched buffers or windows, we need to
1379 recompute to reflect the new bindings. But we'll
1380 recompute when update_mode_lines is set too; that means
1381 that people can use force-mode-line-update to request
1382 that the menu bar be recomputed. The adverse effect on
1383 the rest of the redisplay algorithm is about the same as
1384 windows_or_buffers_changed anyway. */
1385 if (windows_or_buffers_changed
1386 || !NILP (w
->update_mode_line
)
1387 || ((BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))
1388 < BUF_MODIFF (XBUFFER (w
->buffer
)))
1389 != !NILP (w
->last_had_star
))
1390 || ((!NILP (Vtransient_mark_mode
)
1391 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
1392 != !NILP (w
->region_showing
)))
1394 struct buffer
*prev
= current_buffer
;
1395 int count
= specpdl_ptr
- specpdl
;
1397 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1398 if (save_match_data
)
1399 record_unwind_protect (Fstore_match_data
, Fmatch_data (Qnil
, Qnil
));
1400 if (NILP (Voverriding_local_map_menu_flag
))
1402 specbind (Qoverriding_terminal_local_map
, Qnil
);
1403 specbind (Qoverriding_local_map
, Qnil
);
1406 /* Run the Lucid hook. */
1407 call1 (Vrun_hooks
, Qactivate_menubar_hook
);
1408 /* If it has changed current-menubar from previous value,
1409 really recompute the menubar from the value. */
1410 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1411 call0 (Qrecompute_lucid_menubar
);
1412 safe_run_hooks (Qmenu_bar_update_hook
);
1413 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1414 /* Redisplay the menu bar in case we changed it. */
1415 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1416 if (FRAME_WINDOW_P (f
))
1417 set_frame_menubar (f
, 0, 0);
1419 /* On a terminal screen, the menu bar is an ordinary screen
1420 line, and this makes it get updated. */
1421 w
->update_mode_line
= Qt
;
1422 #else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
1423 /* In the non-toolkit version, the menu bar is an ordinary screen
1424 line, and this makes it get updated. */
1425 w
->update_mode_line
= Qt
;
1426 #endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
1428 unbind_to (count
, Qnil
);
1429 set_buffer_internal_1 (prev
);
1436 /* Redisplay WINDOW and its subwindows and siblings. */
1439 redisplay_windows (window
, preserve_echo_area
)
1441 int preserve_echo_area
;
1443 for (; !NILP (window
); window
= XWINDOW (window
)->next
)
1444 redisplay_window (window
, 0, preserve_echo_area
);
1447 /* Redisplay window WINDOW and its subwindows. */
1450 redisplay_window (window
, just_this_one
, preserve_echo_area
)
1452 int just_this_one
, preserve_echo_area
;
1454 register struct window
*w
= XWINDOW (window
);
1455 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1457 register int lpoint
= PT
;
1458 struct buffer
*old
= current_buffer
;
1459 register int width
= window_internal_width (w
) - 1;
1460 register int startp
;
1461 register int hscroll
= XINT (w
->hscroll
);
1462 struct position pos
;
1465 int update_mode_line
;
1466 struct Lisp_Char_Table
*dp
= window_display_table (w
);
1468 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1470 /* If this is a combination window, do its children; that's all. */
1472 if (!NILP (w
->vchild
))
1474 redisplay_windows (w
->vchild
, preserve_echo_area
);
1477 if (!NILP (w
->hchild
))
1479 redisplay_windows (w
->hchild
, preserve_echo_area
);
1482 if (NILP (w
->buffer
))
1485 height
= window_internal_height (w
);
1486 update_mode_line
= (!NILP (w
->update_mode_line
) || update_mode_lines
);
1487 if (XBUFFER (w
->buffer
)->clip_changed
)
1488 update_mode_line
= 1;
1490 if (MINI_WINDOW_P (w
))
1492 if (w
== XWINDOW (echo_area_window
) && echo_area_glyphs
)
1493 /* We've already displayed the echo area glyphs in this window. */
1494 goto finish_scroll_bars
;
1495 else if (w
!= XWINDOW (minibuf_window
))
1497 /* This is a minibuffer, but it's not the currently active one,
1499 int vpos
= XFASTINT (w
->top
);
1502 for (i
= 0; i
< height
; i
++)
1504 get_display_line (f
, vpos
+ i
, 0);
1505 display_string (w
, vpos
+ i
, "", 0,
1506 FRAME_LEFT_SCROLL_BAR_WIDTH (f
),
1510 goto finish_scroll_bars
;
1514 /* Otherwise set up data on this window; select its buffer and point value */
1516 if (update_mode_line
)
1517 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1519 set_buffer_temp (XBUFFER (w
->buffer
));
1523 /* If %c is in mode line, update it if needed. */
1524 if (!NILP (w
->column_number_displayed
)
1525 /* This alternative quickly identifies a common case
1526 where no change is needed. */
1527 && !(PT
== XFASTINT (w
->last_point
)
1528 && XFASTINT (w
->last_modified
) >= MODIFF
1529 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
)
1530 && XFASTINT (w
->column_number_displayed
) != current_column ())
1531 update_mode_line
= 1;
1533 /* Count number of windows showing the selected buffer.
1534 An indirect buffer counts as its base buffer. */
1538 struct buffer
*current_base
, *window_base
;
1539 current_base
= current_buffer
;
1540 window_base
= XBUFFER (XWINDOW (selected_window
)->buffer
);
1541 if (current_base
->base_buffer
)
1542 current_base
= current_base
->base_buffer
;
1543 if (window_base
->base_buffer
)
1544 window_base
= window_base
->base_buffer
;
1545 if (current_base
== window_base
)
1549 /* POINT refers normally to the selected window.
1550 For any other window, set up appropriate value. */
1552 if (!EQ (window
, selected_window
))
1554 int new_pt
= marker_position (w
->pointm
);
1558 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1560 else if (new_pt
> (ZV
- 1))
1563 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1565 /* We don't use SET_PT so that the point-motion hooks don't run. */
1566 BUF_PT (current_buffer
) = new_pt
;
1569 /* If any of the character widths specified in the display table
1570 have changed, invalidate the width run cache. It's true that this
1571 may be a bit late to catch such changes, but the rest of
1572 redisplay goes (non-fatally) haywire when the display table is
1573 changed, so why should we worry about doing any better? */
1574 if (current_buffer
->width_run_cache
)
1576 struct Lisp_Char_Table
*disptab
= buffer_display_table ();
1578 if (! disptab_matches_widthtab (disptab
,
1579 XVECTOR (current_buffer
->width_table
)))
1581 invalidate_region_cache (current_buffer
,
1582 current_buffer
->width_run_cache
,
1584 recompute_width_table (current_buffer
, disptab
);
1588 /* If window-start is screwed up, choose a new one. */
1589 if (XMARKER (w
->start
)->buffer
!= current_buffer
)
1592 startp
= marker_position (w
->start
);
1594 /* If someone specified a new starting point but did not insist,
1595 check whether it can be used. */
1596 if (!NILP (w
->optional_new_start
))
1598 w
->optional_new_start
= Qnil
;
1599 /* Check whether this start pos is usable given where point is. */
1601 pos
= *compute_motion (startp
, 0,
1602 (((EQ (window
, minibuf_window
)
1604 ? minibuf_prompt_width
: 0)
1605 + (hscroll
? 1 - hscroll
: 0)),
1608 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1609 /* If PT does fit on the screen, we will use this start pos,
1610 so do so by setting force_start. */
1611 if (pos
.bufpos
== PT
)
1612 w
->force_start
= Qt
;
1615 /* Handle case where place to start displaying has been specified,
1616 unless the specified location is outside the accessible range. */
1617 if (!NILP (w
->force_start
))
1619 w
->force_start
= Qnil
;
1620 /* Forget any recorded base line for line number display. */
1621 w
->base_line_number
= Qnil
;
1622 /* Redisplay the mode line. Select the buffer properly for that.
1623 Also, run the hook window-scroll-functions
1624 because we have scrolled. */
1625 /* Note, we do this after clearing force_start because
1626 if there's an error, it is better to forget about force_start
1627 than to get into an infinite loop calling the hook functions
1628 and having them get more errors. */
1629 if (!update_mode_line
1630 || ! NILP (Vwindow_scroll_functions
))
1632 Lisp_Object temp
[3];
1634 set_buffer_temp (old
);
1635 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1636 update_mode_line
= 1;
1637 w
->update_mode_line
= Qt
;
1638 if (! NILP (Vwindow_scroll_functions
))
1640 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1641 make_number (startp
));
1642 startp
= marker_position (w
->start
);
1645 XSETFASTINT (w
->last_modified
, 0);
1646 XSETFASTINT (w
->last_overlay_modified
, 0);
1647 if (startp
< BEGV
) startp
= BEGV
;
1648 if (startp
> ZV
) startp
= ZV
;
1649 try_window (window
, startp
);
1650 if (cursor_vpos
< 0)
1652 /* If point does not appear, move point so it does appear */
1653 pos
= *compute_motion (startp
, 0,
1654 (((EQ (window
, minibuf_window
)
1656 ? minibuf_prompt_width
: 0)
1657 + (hscroll
? 1 - hscroll
: 0)),
1660 - (1 << (BITS_PER_SHORT
- 1)),
1661 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1662 BUF_PT (current_buffer
) = pos
.bufpos
;
1663 if (w
!= XWINDOW (selected_window
))
1664 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
1667 if (current_buffer
== old
)
1669 FRAME_CURSOR_X (f
) = (WINDOW_LEFT_MARGIN (w
)
1670 + minmax (0, pos
.hpos
, width
));
1671 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1673 /* If we are highlighting the region,
1674 then we just changed the region, so redisplay to show it. */
1675 if (!NILP (Vtransient_mark_mode
)
1676 && !NILP (current_buffer
->mark_active
))
1678 cancel_my_columns (XWINDOW (window
));
1679 try_window (window
, startp
);
1685 /* Handle case where text has not changed, only point,
1686 and it has not moved off the frame. */
1688 /* This code is not used for minibuffer for the sake of
1689 the case of redisplaying to replace an echo area message;
1690 since in that case the minibuffer contents per se are usually unchanged.
1691 This code is of no real use in the minibuffer since
1692 the handling of this_line_bufpos, etc.,
1693 in redisplay handles the same cases. */
1695 if (XFASTINT (w
->last_modified
) >= MODIFF
1696 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
1697 && PT
>= startp
&& !current_buffer
->clip_changed
1698 && (just_this_one
|| WINDOW_FULL_WIDTH_P (w
))
1699 /* If force-mode-line-update was called, really redisplay;
1700 that's how redisplay is forced after e.g. changing
1701 buffer-invisibility-spec. */
1702 && NILP (w
->update_mode_line
)
1703 /* Can't use this case if highlighting a region. */
1704 && !(!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1705 && NILP (w
->region_showing
)
1706 /* If end pos is out of date, scroll bar and percentage will be wrong */
1707 && INTEGERP (w
->window_end_vpos
)
1708 && XFASTINT (w
->window_end_vpos
) < XFASTINT (w
->height
)
1709 && !EQ (window
, minibuf_window
))
1711 int this_scroll_margin
= scroll_margin
;
1713 pos
= *compute_motion (startp
, 0, (hscroll
? 1 - hscroll
: 0), 0,
1714 PT
, height
, 0, width
, hscroll
,
1715 pos_tab_offset (w
, startp
), w
);
1717 /* Don't use a scroll margin that is negative or too large. */
1718 if (this_scroll_margin
< 0)
1719 this_scroll_margin
= 0;
1721 if (XINT (w
->height
) < 4 * scroll_margin
)
1722 this_scroll_margin
= XINT (w
->height
) / 4;
1724 /* If point fits on the screen, and not within the scroll margin,
1726 if (pos
.vpos
< height
- this_scroll_margin
1727 && (pos
.vpos
>= this_scroll_margin
|| startp
== BEGV
))
1729 /* Ok, point is still on frame */
1730 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
1732 /* These variables are supposed to be origin 1 */
1733 FRAME_CURSOR_X (f
) = (WINDOW_LEFT_MARGIN (w
)
1734 + minmax (0, pos
.hpos
, width
));
1735 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1737 /* This doesn't do the trick, because if a window to the right of
1738 this one must be redisplayed, this does nothing because there
1739 is nothing in DesiredFrame yet, and then the other window is
1740 redisplayed, making likes that are empty in this window's columns.
1741 if (WINDOW_FULL_WIDTH_P (w))
1742 preserve_my_columns (w);
1746 /* Don't bother trying redisplay with same start;
1747 we already know it will lose */
1749 /* If current starting point was originally the beginning of a line
1750 but no longer is, find a new starting point. */
1751 else if (!NILP (w
->start_at_line_beg
)
1753 || FETCH_CHAR (startp
- 1) == '\n'))
1757 else if (just_this_one
&& !MINI_WINDOW_P (w
)
1759 && XFASTINT (w
->last_modified
)
1760 /* or else vmotion on first line won't work. */
1761 && ! NILP (w
->start_at_line_beg
)
1762 && ! EQ (w
->window_end_valid
, Qnil
)
1763 && do_id
&& !current_buffer
->clip_changed
1764 && !blank_end_of_window
1765 && WINDOW_FULL_WIDTH_P (w
)
1766 /* Can't use this case if highlighting a region. */
1767 && !(!NILP (Vtransient_mark_mode
)
1768 && !NILP (current_buffer
->mark_active
))
1769 /* Don't use try_window_id if newline
1770 doesn't display as the end of a line. */
1771 && !(dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, '\n')))
1772 && NILP (w
->region_showing
)
1773 && EQ (last_arrow_position
, Voverlay_arrow_position
)
1774 && EQ (last_arrow_string
, Voverlay_arrow_string
)
1775 && (tem
= try_window_id (FRAME_SELECTED_WINDOW (f
)))
1778 /* tem > 0 means success. tem == -1 means choose new start.
1779 tem == -2 means try again with same start,
1780 and nothing but whitespace follows the changed stuff.
1781 tem == 0 means try again with same start. */
1785 else if (startp
>= BEGV
&& startp
<= ZV
1787 /* Avoid starting at end of buffer. */
1788 #if 0 /* This change causes trouble for M-! finger & RET.
1789 It will have to be considered later. */
1790 || ! EQ (window
, selected_window
)
1791 /* Don't do the recentering if redisplay
1792 is not for no user action. */
1793 || preserve_echo_area
1796 || (XFASTINT (w
->last_modified
) >= MODIFF
1797 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
)))
1799 /* Try to redisplay starting at same place as before */
1800 /* If point has not moved off frame, accept the results */
1801 try_window (window
, startp
);
1802 if (cursor_vpos
>= 0)
1804 if (!just_this_one
|| current_buffer
->clip_changed
1805 || beg_unchanged
< startp
)
1806 /* Forget any recorded base line for line number display. */
1807 w
->base_line_number
= Qnil
;
1811 cancel_my_columns (w
);
1814 XSETFASTINT (w
->last_modified
, 0);
1815 XSETFASTINT (w
->last_overlay_modified
, 0);
1816 /* Redisplay the mode line. Select the buffer properly for that. */
1817 if (!update_mode_line
)
1819 set_buffer_temp (old
);
1820 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1821 update_mode_line
= 1;
1822 w
->update_mode_line
= Qt
;
1825 /* Try to scroll by specified few lines */
1827 if (scroll_conservatively
&& !current_buffer
->clip_changed
1828 && startp
>= BEGV
&& startp
<= ZV
)
1830 int this_scroll_margin
= scroll_margin
;
1832 /* Don't use a scroll margin that is negative or too large. */
1833 if (this_scroll_margin
< 0)
1834 this_scroll_margin
= 0;
1836 if (XINT (w
->height
) < 4 * scroll_margin
)
1837 this_scroll_margin
= XINT (w
->height
) / 4;
1839 if (PT
>= Z
- XFASTINT (w
->window_end_pos
))
1841 struct position pos
;
1842 pos
= *compute_motion (Z
- XFASTINT (w
->window_end_pos
), 0, 0, 0,
1843 PT
, XFASTINT (w
->height
), 0,
1844 XFASTINT (w
->width
), XFASTINT (w
->hscroll
),
1845 pos_tab_offset (w
, startp
), w
);
1846 if (pos
.vpos
> scroll_conservatively
)
1849 pos
= *vmotion (startp
, pos
.vpos
+ 1 + this_scroll_margin
, w
);
1851 if (! NILP (Vwindow_scroll_functions
))
1853 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
1854 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1855 make_number (pos
.bufpos
));
1856 pos
.bufpos
= marker_position (w
->start
);
1858 try_window (window
, pos
.bufpos
);
1859 if (cursor_vpos
>= 0)
1861 if (!just_this_one
|| current_buffer
->clip_changed
1862 || beg_unchanged
< startp
)
1863 /* Forget any recorded base line for line number display. */
1864 w
->base_line_number
= Qnil
;
1868 cancel_my_columns (w
);
1872 struct position pos
;
1873 pos
= *compute_motion (PT
, 0, 0, 0,
1874 startp
, XFASTINT (w
->height
), 0,
1875 XFASTINT (w
->width
), XFASTINT (w
->hscroll
),
1876 pos_tab_offset (w
, startp
), w
);
1877 if (pos
.vpos
>= scroll_conservatively
)
1880 pos
= *vmotion (startp
, - pos
.vpos
- this_scroll_margin
, w
);
1882 if (! NILP (Vwindow_scroll_functions
))
1884 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
1885 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1886 make_number (pos
.bufpos
));
1887 pos
.bufpos
= marker_position (w
->start
);
1889 try_window (window
, pos
.bufpos
);
1890 if (cursor_vpos
>= 0)
1892 if (!just_this_one
|| current_buffer
->clip_changed
1893 || beg_unchanged
< startp
)
1894 /* Forget any recorded base line for line number display. */
1895 w
->base_line_number
= Qnil
;
1899 cancel_my_columns (w
);
1904 if (scroll_step
&& !current_buffer
->clip_changed
1905 && startp
>= BEGV
&& startp
<= ZV
)
1909 pos
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), scroll_step
, w
);
1910 if (pos
.vpos
>= height
)
1914 pos
= *vmotion (startp
, (PT
< startp
? - scroll_step
: scroll_step
), w
);
1916 if (PT
>= pos
.bufpos
)
1918 if (! NILP (Vwindow_scroll_functions
))
1920 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
1921 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1922 make_number (pos
.bufpos
));
1923 pos
.bufpos
= marker_position (w
->start
);
1925 try_window (window
, pos
.bufpos
);
1926 if (cursor_vpos
>= 0)
1928 if (!just_this_one
|| current_buffer
->clip_changed
1929 || beg_unchanged
< startp
)
1930 /* Forget any recorded base line for line number display. */
1931 w
->base_line_number
= Qnil
;
1935 cancel_my_columns (w
);
1940 /* Finally, just choose place to start which centers point */
1943 /* Forget any previously recorded base line for line number display. */
1944 w
->base_line_number
= Qnil
;
1946 pos
= *vmotion (PT
, - (height
/ 2), w
);
1947 /* Set startp here explicitly in case that helps avoid an infinite loop
1948 in case the window-scroll-functions functions get errors. */
1949 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
1950 if (! NILP (Vwindow_scroll_functions
))
1952 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1953 make_number (pos
.bufpos
));
1954 pos
.bufpos
= marker_position (w
->start
);
1956 try_window (window
, pos
.bufpos
);
1958 startp
= marker_position (w
->start
);
1959 w
->start_at_line_beg
1960 = (startp
== BEGV
|| FETCH_CHAR (startp
- 1) == '\n') ? Qt
: Qnil
;
1963 if ((update_mode_line
1964 /* If window not full width, must redo its mode line
1965 if the window to its side is being redone */
1966 || (!just_this_one
&& !WINDOW_FULL_WIDTH_P (w
))
1967 || INTEGERP (w
->base_line_pos
)
1968 || (!NILP (w
->column_number_displayed
)
1969 && XFASTINT (w
->column_number_displayed
) != current_column ()))
1970 && height
!= XFASTINT (w
->height
))
1971 display_mode_line (w
);
1972 if (! line_number_displayed
1973 && ! BUFFERP (w
->base_line_pos
))
1975 w
->base_line_pos
= Qnil
;
1976 w
->base_line_number
= Qnil
;
1979 /* When we reach a frame's selected window, redo the frame's menu bar. */
1980 if (update_mode_line
1981 && (FRAME_WINDOW_P (f
)
1983 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1984 FRAME_EXTERNAL_MENU_BAR (f
)
1986 FRAME_MENU_BAR_LINES (f
) > 0
1988 : FRAME_MENU_BAR_LINES (f
) > 0)
1989 && EQ (FRAME_SELECTED_WINDOW (f
), window
))
1990 display_menu_bar (w
);
1993 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1995 int start
, end
, whole
;
1997 /* Calculate the start and end positions for the current window.
1998 At some point, it would be nice to choose between scrollbars
1999 which reflect the whole buffer size, with special markers
2000 indicating narrowing, and scrollbars which reflect only the
2003 Note that minibuffers sometimes aren't displaying any text. */
2004 if (! MINI_WINDOW_P (w
)
2005 || (w
== XWINDOW (minibuf_window
) && ! echo_area_glyphs
))
2008 start
= marker_position (w
->start
) - BEGV
;
2009 /* I don't think this is guaranteed to be right. For the
2010 moment, we'll pretend it is. */
2011 end
= (Z
- XINT (w
->window_end_pos
)) - BEGV
;
2013 if (end
< start
) end
= start
;
2014 if (whole
< (end
- start
)) whole
= end
- start
;
2017 start
= end
= whole
= 0;
2019 /* Indicate what this scroll bar ought to be displaying now. */
2020 (*set_vertical_scroll_bar_hook
) (w
, end
- start
, whole
, start
);
2022 /* Note that we actually used the scroll bar attached to this window,
2023 so it shouldn't be deleted at the end of redisplay. */
2024 (*redeem_scroll_bar_hook
) (w
);
2027 BUF_PT (current_buffer
) = opoint
;
2028 if (update_mode_line
)
2029 set_buffer_internal_1 (old
);
2031 set_buffer_temp (old
);
2032 BUF_PT (current_buffer
) = lpoint
;
2035 /* Do full redisplay on one window, starting at position `pos'. */
2038 try_window (window
, pos
)
2042 register struct window
*w
= XWINDOW (window
);
2043 register int height
= window_internal_height (w
);
2044 register int vpos
= XFASTINT (w
->top
);
2045 register int last_text_vpos
= vpos
;
2046 int tab_offset
= pos_tab_offset (w
, pos
);
2047 FRAME_PTR f
= XFRAME (w
->frame
);
2048 int width
= window_internal_width (w
) - 1;
2049 struct position val
;
2051 /* POS should never be out of range! */
2052 if (pos
< XBUFFER (w
->buffer
)->begv
2053 || pos
> XBUFFER (w
->buffer
)->zv
)
2056 Fset_marker (w
->start
, make_number (pos
), Qnil
);
2058 overlay_arrow_seen
= 0;
2059 zv_strings_seen
= 0;
2060 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
2061 val
.ovstring_chars_done
= 0;
2063 while (--height
>= 0)
2065 val
= *display_text_line (w
, pos
, vpos
, val
.hpos
, tab_offset
,
2066 val
.ovstring_chars_done
);
2067 tab_offset
+= width
;
2068 /* For the first line displayed, display_text_line
2069 subtracts the prompt width from the tab offset.
2070 But it does not affect the value of our variable tab_offset.
2071 So we do the subtraction again,
2072 for the sake of continuation lines of that first line. */
2073 if (MINI_WINDOW_P (w
) && vpos
== XFASTINT (w
->top
))
2074 tab_offset
-= minibuf_prompt_width
;
2076 if (val
.vpos
) tab_offset
= 0;
2078 if (pos
!= val
.bufpos
)
2081 #ifdef USE_TEXT_PROPERTIES
2082 Lisp_Object invis_prop
;
2083 invis_prop
= Fget_char_property (val
.bufpos
-1, Qinvisible
, window
);
2084 invis
= TEXT_PROP_MEANS_INVISIBLE (invis_prop
);
2088 /* Next line, unless prev line ended in end of buffer with no cr */
2090 && (FETCH_CHAR (val
.bufpos
- 1) != '\n' || invis
));
2095 /* If last line is continued in middle of character,
2096 include the split character in the text considered on the frame */
2097 if (val
.hpos
< (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
2100 /* If bottom just moved off end of frame, change mode line percentage. */
2101 if (XFASTINT (w
->window_end_pos
) == 0
2103 w
->update_mode_line
= Qt
;
2105 /* Say where last char on frame will be, once redisplay is finished. */
2106 XSETFASTINT (w
->window_end_pos
, Z
- pos
);
2107 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
- XFASTINT (w
->top
));
2108 /* But that is not valid info until redisplay finishes. */
2109 w
->window_end_valid
= Qnil
;
2112 /* Try to redisplay when buffer is modified locally,
2113 computing insert/delete line to preserve text outside
2114 the bounds of the changes.
2115 Return 1 if successful, 0 if if cannot tell what to do,
2116 or -1 to tell caller to find a new window start,
2117 or -2 to tell caller to do normal redisplay with same window start. */
2120 try_window_id (window
)
2124 register struct window
*w
= XWINDOW (window
);
2125 register int height
= window_internal_height (w
);
2126 FRAME_PTR f
= XFRAME (w
->frame
);
2127 int top
= XFASTINT (w
->top
);
2128 int start
= marker_position (w
->start
);
2129 int width
= window_internal_width (w
) - 1;
2130 int hscroll
= XINT (w
->hscroll
);
2131 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
2134 register int i
, tem
;
2135 int last_text_vpos
= 0;
2137 int selective
= (INTEGERP (current_buffer
->selective_display
)
2138 ? XINT (current_buffer
->selective_display
)
2139 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2141 struct position val
, bp
, ep
, xp
, pp
;
2142 int scroll_amount
= 0;
2144 int tab_offset
, epto
, old_tick
;
2146 if (GPT
- BEG
< beg_unchanged
)
2147 beg_unchanged
= GPT
- BEG
;
2148 if (Z
- GPT
< end_unchanged
)
2149 end_unchanged
= Z
- GPT
;
2151 if (beg_unchanged
+ BEG
< start
)
2152 return 0; /* Give up if changes go above top of window */
2154 /* Find position before which nothing is changed. */
2155 bp
= *compute_motion (start
, 0, lmargin
, 0,
2156 min (ZV
, beg_unchanged
+ BEG
), height
, 0,
2157 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2158 if (bp
.vpos
>= height
)
2162 /* All changes are beyond the window end, and point is on the screen.
2163 We don't need to change the text at all.
2164 But we need to update window_end_pos to account for
2165 any change in buffer size. */
2166 bp
= *compute_motion (start
, 0, lmargin
, 0,
2168 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2169 XSETFASTINT (w
->window_end_vpos
, height
);
2170 XSETFASTINT (w
->window_end_pos
, Z
- bp
.bufpos
);
2178 /* Find beginning of that frame line. Must display from there. */
2179 bp
= *vmotion (bp
.bufpos
, 0, w
);
2187 /* If about to start displaying at the beginning of a continuation line,
2188 really start with previous frame line, in case it was not
2189 continued when last redisplayed */
2190 if ((bp
.contin
&& bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0)
2192 /* Likewise if we have to worry about selective display. */
2193 (selective
> 0 && bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0))
2195 bp
= *vmotion (bp
.bufpos
, -1, w
);
2200 if (bp
.contin
&& bp
.hpos
!= lmargin
)
2202 val
.hpos
= bp
.prevhpos
- width
+ lmargin
;
2209 /* Find first visible newline after which no more is changed. */
2210 tem
= find_next_newline (Z
- max (end_unchanged
, Z
- ZV
), 1);
2212 while (tem
< ZV
- 1 && (indented_beyond_p (tem
, selective
)))
2213 tem
= find_next_newline (tem
, 1);
2215 /* Compute the cursor position after that newline. */
2216 ep
= *compute_motion (pos
, vpos
, val
.hpos
, did_motion
, tem
,
2217 height
, - (1 << (BITS_PER_SHORT
- 1)),
2218 width
, hscroll
, pos_tab_offset (w
, bp
.bufpos
), w
);
2220 /* If changes reach past the text available on the frame,
2221 just display rest of frame. */
2222 if (ep
.bufpos
> Z
- XFASTINT (w
->window_end_pos
))
2225 stop_vpos
= ep
.vpos
;
2227 /* If no newline before ep, the line ep is on includes some changes
2228 that must be displayed. Make sure we don't stop before it. */
2229 /* Also, if changes reach all the way until ep.bufpos,
2230 it is possible that something was deleted after the
2231 newline before it, so the following line must be redrawn. */
2232 if (stop_vpos
== ep
.vpos
2233 && (ep
.bufpos
== BEGV
2234 || FETCH_CHAR (ep
.bufpos
- 1) != '\n'
2235 || ep
.bufpos
== Z
- end_unchanged
))
2236 stop_vpos
= ep
.vpos
+ 1;
2239 overlay_arrow_seen
= 0;
2240 zv_strings_seen
= 0;
2242 /* If changes do not reach to bottom of window,
2243 figure out how much to scroll the rest of the window */
2244 if (stop_vpos
< height
)
2246 /* Now determine how far up or down the rest of the window has moved */
2247 epto
= pos_tab_offset (w
, ep
.bufpos
);
2248 xp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
2249 Z
- XFASTINT (w
->window_end_pos
),
2250 10000, 0, width
, hscroll
, epto
, w
);
2251 scroll_amount
= xp
.vpos
- XFASTINT (w
->window_end_vpos
);
2253 /* Is everything on frame below the changes whitespace?
2254 If so, no scrolling is really necessary. */
2255 for (i
= ep
.bufpos
; i
< xp
.bufpos
; i
++)
2257 tem
= FETCH_CHAR (i
);
2258 if (tem
!= ' ' && tem
!= '\n' && tem
!= '\t')
2264 XSETFASTINT (w
->window_end_vpos
,
2265 XFASTINT (w
->window_end_vpos
) + scroll_amount
);
2267 /* Before doing any scrolling, verify that point will be on frame. */
2268 if (PT
> ep
.bufpos
&& !(PT
<= xp
.bufpos
&& xp
.bufpos
< height
))
2270 if (PT
<= xp
.bufpos
)
2272 pp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
2273 PT
, height
, - (1 << (BITS_PER_SHORT
- 1)),
2274 width
, hscroll
, epto
, w
);
2278 pp
= *compute_motion (xp
.bufpos
, xp
.vpos
, xp
.hpos
, 1,
2279 PT
, height
, - (1 << (BITS_PER_SHORT
- 1)),
2281 pos_tab_offset (w
, xp
.bufpos
), w
);
2283 if (pp
.bufpos
< PT
|| pp
.vpos
== height
)
2285 cursor_vpos
= pp
.vpos
+ top
;
2286 cursor_hpos
= WINDOW_LEFT_MARGIN (w
) + minmax (0, pp
.hpos
, width
);
2289 if (stop_vpos
- scroll_amount
>= height
2290 || ep
.bufpos
== xp
.bufpos
)
2292 if (scroll_amount
< 0)
2293 stop_vpos
-= scroll_amount
;
2295 /* In this path, we have altered window_end_vpos
2296 and not left it negative.
2297 We must make sure that, in case display is preempted
2298 before the frame changes to reflect what we do here,
2299 further updates will not come to try_window_id
2300 and assume the frame and window_end_vpos match. */
2301 blank_end_of_window
= 1;
2303 else if (!scroll_amount
)
2305 /* Even if we don't need to scroll, we must adjust the
2306 charstarts of subsequent lines (that we won't redisplay)
2307 according to the amount of text inserted or deleted. */
2308 int oldpos
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2309 int adjust
= ep
.bufpos
- oldpos
;
2310 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1, adjust
);
2312 else if (bp
.bufpos
== Z
- end_unchanged
)
2314 /* If reprinting everything is nearly as fast as scrolling,
2315 don't bother scrolling. Can happen if lines are short. */
2316 if (scroll_cost (f
, bp
.vpos
+ top
- scroll_amount
,
2317 top
+ height
- max (0, scroll_amount
),
2319 > xp
.bufpos
- bp
.bufpos
- 20)
2320 /* Return "try normal display with same window-start."
2321 Too bad we can't prevent further scroll-thinking. */
2323 /* If pure deletion, scroll up as many lines as possible.
2324 In common case of killing a line, this can save the
2325 following line from being overwritten by scrolling
2326 and therefore having to be redrawn. */
2327 tem
= scroll_frame_lines (f
, bp
.vpos
+ top
- scroll_amount
,
2328 top
+ height
- max (0, scroll_amount
),
2329 scroll_amount
, bp
.bufpos
);
2334 /* scroll_frame_lines did not properly adjust subsequent
2335 lines' charstarts in the case where the text of the
2336 screen line at bp.vpos has changed.
2337 (This can happen in a deletion that ends in mid-line.)
2338 To adjust properly, we need to make things consistent
2340 So do a second adjust to make that happen.
2341 Note that stop_vpos >= ep.vpos, so it is sufficient
2342 to update the charstarts for lines at ep.vpos and below. */
2344 = FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2345 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1,
2346 ep
.bufpos
- oldstart
);
2349 else if (scroll_amount
)
2351 /* If reprinting everything is nearly as fast as scrolling,
2352 don't bother scrolling. Can happen if lines are short. */
2353 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2354 overestimate of cost of reprinting, since xp.bufpos
2355 would end up below the bottom of the window. */
2356 if (scroll_cost (f
, ep
.vpos
+ top
- scroll_amount
,
2357 top
+ height
- max (0, scroll_amount
),
2359 > xp
.bufpos
- ep
.bufpos
- 20)
2360 /* Return "try normal display with same window-start."
2361 Too bad we can't prevent further scroll-thinking. */
2363 tem
= scroll_frame_lines (f
, ep
.vpos
+ top
- scroll_amount
,
2364 top
+ height
- max (0, scroll_amount
),
2365 scroll_amount
, ep
.bufpos
);
2366 if (!tem
) stop_vpos
= height
;
2370 /* In any case, do not display past bottom of window */
2371 if (stop_vpos
>= height
)
2377 /* Handle case where pos is before w->start --
2378 can happen if part of line had been clipped and is not clipped now */
2379 if (vpos
== 0 && pos
< marker_position (w
->start
))
2380 Fset_marker (w
->start
, make_number (pos
), Qnil
);
2382 /* Redisplay the lines where the text was changed */
2383 last_text_vpos
= vpos
;
2384 tab_offset
= pos_tab_offset (w
, pos
);
2385 /* If we are starting display in mid-character, correct tab_offset
2386 to account for passing the line that that character really starts in. */
2387 if (val
.hpos
< lmargin
)
2388 tab_offset
+= width
;
2390 while (vpos
< stop_vpos
)
2392 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
,
2393 val
.ovstring_chars_done
);
2394 /* If display_text_line ran a hook and changed some text,
2395 redisplay all the way to bottom of buffer
2396 So that we show the changes. */
2397 if (old_tick
!= MODIFF
)
2399 tab_offset
+= width
;
2400 if (val
.vpos
) tab_offset
= 0;
2401 if (pos
!= val
.bufpos
)
2403 /* Next line, unless prev line ended in end of buffer with no cr */
2404 = vpos
- (val
.vpos
&& FETCH_CHAR (val
.bufpos
- 1) != '\n');
2408 /* There are two cases:
2409 1) we have displayed down to the bottom of the window
2410 2) we have scrolled lines below stop_vpos by scroll_amount */
2414 /* If last line is continued in middle of character,
2415 include the split character in the text considered on the frame */
2416 if (val
.hpos
< lmargin
)
2418 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
);
2419 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2422 /* If scrolling made blank lines at window bottom,
2423 redisplay to fill those lines */
2424 if (scroll_amount
< 0)
2426 /* Don't consider these lines for general-purpose scrolling.
2427 That will save time in the scrolling computation. */
2428 FRAME_SCROLL_BOTTOM_VPOS (f
) = xp
.vpos
;
2433 vpos
= height
+ scroll_amount
;
2434 else if (xp
.contin
&& xp
.hpos
!= lmargin
)
2436 val
.hpos
= xp
.prevhpos
- width
+ lmargin
;
2440 blank_end_of_window
= 1;
2441 tab_offset
= pos_tab_offset (w
, pos
);
2442 /* If we are starting display in mid-character, correct tab_offset
2443 to account for passing the line that that character starts in. */
2444 if (val
.hpos
< lmargin
)
2445 tab_offset
+= width
;
2447 while (vpos
< height
)
2449 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
,
2450 val
.ovstring_chars_done
);
2451 tab_offset
+= width
;
2452 if (val
.vpos
) tab_offset
= 0;
2456 /* Here is a case where display_text_line sets cursor_vpos wrong.
2457 Make it be fixed up, below. */
2463 /* If bottom just moved off end of frame, change mode line percentage. */
2464 if (XFASTINT (w
->window_end_pos
) == 0
2466 w
->update_mode_line
= Qt
;
2468 /* Attempt to adjust end-of-text positions to new bottom line */
2471 delta
= height
- xp
.vpos
;
2473 || (delta
> 0 && xp
.bufpos
<= ZV
)
2474 || (delta
== 0 && xp
.hpos
))
2476 val
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), delta
, w
);
2477 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2478 XSETFASTINT (w
->window_end_vpos
,
2479 XFASTINT (w
->window_end_vpos
) + val
.vpos
);
2483 w
->window_end_valid
= Qnil
;
2485 /* If point was not in a line that was displayed, find it */
2486 if (cursor_vpos
< 0)
2489 val
= *compute_motion (start
, 0, lmargin
, 0, PT
, 10000, 10000,
2490 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2491 /* Admit failure if point is off frame now */
2492 if (val
.vpos
>= height
)
2494 for (vpos
= 0; vpos
< height
; vpos
++)
2495 cancel_line (vpos
+ top
, f
);
2498 cursor_vpos
= val
.vpos
+ top
;
2499 cursor_hpos
= WINDOW_LEFT_MARGIN (w
) + minmax (0, val
.hpos
, width
);
2502 FRAME_CURSOR_X (f
) = cursor_hpos
;
2503 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2507 val
= *compute_motion (start
, 0, lmargin
, 0, ZV
,
2508 height
, - (1 << (BITS_PER_SHORT
- 1)),
2509 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2510 if (val
.vpos
!= XFASTINT (w
->window_end_vpos
))
2512 if (XFASTINT (w
->window_end_pos
)
2520 /* Copy LEN glyphs starting address FROM to the rope TO.
2521 But don't actually copy the parts that would come in before S.
2522 Value is TO, advanced past the copied data.
2523 F is the frame we are displaying in. */
2526 copy_part_of_rope (f
, to
, s
, from
, len
, face
)
2528 register GLYPH
*to
; /* Copy to here. */
2529 register GLYPH
*s
; /* Starting point. */
2530 Lisp_Object
*from
; /* Data to copy. */
2532 int face
; /* Face to apply to glyphs which don't specify one. */
2535 register Lisp_Object
*fp
= from
;
2536 /* These cache the results of the last call to compute_glyph_face. */
2538 int last_merged
= 0;
2541 if (! FRAME_TERMCAP_P (f
))
2544 int glyph
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2547 if (FAST_GLYPH_FACE (glyph
) == 0)
2548 /* If GLYPH has no face code, use FACE. */
2550 else if (FAST_GLYPH_FACE (glyph
) == last_code
)
2551 /* If it's same as previous glyph, use same result. */
2552 facecode
= last_merged
;
2555 /* Merge this glyph's face and remember the result. */
2556 last_code
= FAST_GLYPH_FACE (glyph
);
2557 last_merged
= facecode
= compute_glyph_face (f
, last_code
, face
);
2561 *to
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), facecode
);
2569 if (to
>= s
) *to
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2576 /* Correct a glyph by replacing its specified user-level face code
2577 with a displayable computed face code. */
2580 fix_glyph (f
, glyph
, cface
)
2586 if (! FRAME_TERMCAP_P (f
))
2588 if (FAST_GLYPH_FACE (glyph
) != 0)
2589 cface
= compute_glyph_face (f
, FAST_GLYPH_FACE (glyph
), cface
);
2590 glyph
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), cface
);
2596 /* Display one line of window W, starting at position START in W's buffer.
2598 Display starting at horizontal position HPOS, expressed relative to
2599 W's left edge. In situations where the text at START shouldn't
2600 start at the left margin (i.e. when the window is hscrolled, or
2601 we're continuing a line which left off in the midst of a
2602 multi-column character), HPOS should be negative; we throw away
2603 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2606 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2608 OVSTR_DONE is the number of chars of overlay before/after strings
2609 at this position which have already been processed.
2611 Display on position VPOS on the frame. It is origin 0, relative to
2612 the top of the frame, not W.
2614 Returns a STRUCT POSITION giving character to start next line with
2615 and where to display it, including a zero or negative hpos.
2616 The vpos field is not really a vpos; it is 1 unless the line is continued */
2618 struct position val_display_text_line
;
2620 static struct position
*
2621 display_text_line (w
, start
, vpos
, hpos
, taboffset
, ovstr_done
)
2629 register int pos
= start
;
2633 register unsigned char *p
;
2635 register GLYPH
*leftmargin
;
2636 register GLYPH
*p1prev
;
2637 register GLYPH
*p1start
;
2640 FRAME_PTR f
= XFRAME (w
->frame
);
2641 int tab_width
= XINT (current_buffer
->tab_width
);
2642 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
2643 int width
= window_internal_width (w
) - 1;
2644 struct position val
;
2647 int last_invis_skip
= 0;
2648 Lisp_Object last_invis_prop
;
2649 int hscroll
= XINT (w
->hscroll
);
2650 int truncate
= (hscroll
2651 || (truncate_partial_width_windows
2652 && !WINDOW_FULL_WIDTH_P (w
))
2653 || !NILP (current_buffer
->truncate_lines
));
2655 /* 1 if we should highlight the region. */
2656 int highlight_region
2657 = (!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
)
2658 && XWINDOW (current_buffer
->last_selected_window
) == w
);
2659 int region_beg
, region_end
;
2661 int selective
= (INTEGERP (current_buffer
->selective_display
)
2662 ? XINT (current_buffer
->selective_display
)
2663 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2664 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
2665 register struct Lisp_Char_Table
*dp
= window_display_table (w
);
2667 Lisp_Object default_invis_vector
[3];
2668 /* Number of characters of ellipsis to display after an invisible line
2669 if it calls for an ellipsis.
2670 Note that this value can be nonzero regardless of whether
2671 selective display is enabled--you must check that separately. */
2673 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2674 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
2675 : !NILP (current_buffer
->selective_display_ellipses
) ? 3 : 0);
2676 /* This is the sequence of Lisp objects to display
2677 when there are invisible lines. */
2678 Lisp_Object
*invis_vector_contents
2679 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2680 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->contents
2681 : default_invis_vector
);
2683 GLYPH truncator
= (dp
== 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp
))
2684 ? '$' : XINT (DISP_TRUNC_GLYPH (dp
)));
2685 GLYPH continuer
= (dp
== 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp
))
2686 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp
)));
2688 /* The next buffer location at which the face should change, due
2689 to overlays or text property changes. */
2690 int next_face_change
;
2692 /* The next location where the `invisible' property changes, or an
2693 overlay starts or ends. */
2696 /* The face we're currently using. */
2697 int current_face
= 0;
2700 XSETFASTINT (default_invis_vector
[2], '.');
2701 default_invis_vector
[0] = default_invis_vector
[1] = default_invis_vector
[2];
2703 hpos
+= WINDOW_LEFT_MARGIN (w
);
2704 get_display_line (f
, vpos
, WINDOW_LEFT_MARGIN (w
));
2705 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
2707 /* Show where to highlight the region. */
2708 if (highlight_region
&& XMARKER (current_buffer
->mark
)->buffer
!= 0
2709 /* Maybe highlight only in selected window. */
2710 && (highlight_nonselected_windows
2711 || w
== XWINDOW (selected_window
)))
2713 region_beg
= marker_position (current_buffer
->mark
);
2714 if (PT
< region_beg
)
2716 region_end
= region_beg
;
2721 w
->region_showing
= Qt
;
2724 region_beg
= region_end
= -1;
2726 if (MINI_WINDOW_P (w
)
2728 && vpos
== XFASTINT (w
->top
))
2730 if (! NILP (minibuf_prompt
))
2732 minibuf_prompt_width
2733 = (display_string (w
, vpos
, XSTRING (minibuf_prompt
)->data
,
2734 XSTRING (minibuf_prompt
)->size
, hpos
,
2735 /* Display a space if we truncate. */
2738 /* Truncate the prompt a little before the
2739 margin, so user input can at least start
2740 on the first line. */
2741 w
->width
> 10 ? w
->width
- 4 : -1)
2743 hpos
+= minibuf_prompt_width
;
2744 taboffset
-= minibuf_prompt_width
;
2747 minibuf_prompt_width
= 0;
2750 /* If we're hscrolled at all, use compute_motion to skip over any
2751 text off the left edge of the window. compute_motion may know
2752 tricks to do this faster than we can. */
2755 struct position
*left_edge
2756 = compute_motion (pos
, vpos
, hpos
, 0,
2758 width
, hscroll
, taboffset
, w
);
2760 /* Retrieve the buffer position and column provided by
2761 compute_motion. We can't assume that the column will be
2762 zero, because you may have multi-column characters crossing
2765 compute_motion may have moved us past the screen position we
2766 requested, if we hit a multi-column character, or the end of
2767 the line. If so, back up. */
2768 if (left_edge
->vpos
> vpos
2769 || left_edge
->hpos
> 0)
2771 pos
= left_edge
->bufpos
- 1;
2772 hpos
= left_edge
->prevhpos
;
2776 pos
= left_edge
->bufpos
;
2777 hpos
= left_edge
->hpos
;
2781 desired_glyphs
->bufp
[vpos
] = start
;
2782 p1
= desired_glyphs
->glyphs
[vpos
] + hpos
;
2784 charstart
= desired_glyphs
->charstarts
[vpos
] + hpos
;
2785 /* In case we don't ever write anything into it... */
2786 desired_glyphs
->charstarts
[vpos
][WINDOW_LEFT_MARGIN (w
)] = -1;
2787 leftmargin
= desired_glyphs
->glyphs
[vpos
] + WINDOW_LEFT_MARGIN (w
);
2788 endp
= leftmargin
+ width
;
2790 /* Arrange the overlays nicely for our purposes. Usually, we call
2791 display_text_line on only one line at a time, in which case this
2792 can't really hurt too much, or we call it on lines which appear
2793 one after another in the buffer, in which case all calls to
2794 recenter_overlay_lists but the first will be pretty cheap. */
2795 recenter_overlay_lists (current_buffer
, pos
);
2797 /* Loop generating characters.
2798 Stop at end of buffer, before newline,
2799 if reach or pass continuation column,
2800 or at face change. */
2802 next_face_change
= pos
;
2803 next_boundary
= pos
;
2812 while (pos
== next_boundary
)
2814 Lisp_Object position
, limit
, prop
, ww
;
2816 /* Display the overlay strings here, unless we're at ZV
2817 and have already displayed the appropriate strings
2818 on an earlier line. */
2819 if (pos
< ZV
|| !zv_strings_seen
++)
2822 unsigned char *ovstr
;
2823 ovlen
= overlay_strings (pos
, w
, &ovstr
);
2827 /* Skip the ones we did in a previous line. */
2828 ovstr
+= ovstr_done
;
2829 ovlen
-= ovstr_done
;
2831 /* Start outputting. */
2832 for (; ovlen
; ovlen
--, ovstr
++)
2834 if (p1
>= leftmargin
&& p1
< endp
)
2835 *p1
= MAKE_GLYPH (f
, *ovstr
, current_face
);
2839 /* If we did all the overlay strings
2840 and we have room for text, clear ovstr_done
2841 just for neatness' sake. */
2842 if (ovlen
== 0 && p1
< endp
)
2847 /* Did we reach point? Record the cursor location. */
2848 if (pos
== PT
&& cursor_vpos
< 0)
2851 cursor_hpos
= p1
- leftmargin
;
2857 XSETFASTINT (position
, pos
);
2858 limit
= Fnext_overlay_change (position
);
2859 #ifdef USE_TEXT_PROPERTIES
2860 /* This is just an estimate to give reasonable
2861 performance; nothing should go wrong if it is too small. */
2862 if (XFASTINT (limit
) > pos
+ 50)
2863 XSETFASTINT (limit
, pos
+ 50);
2864 limit
= Fnext_single_property_change (position
, Qinvisible
,
2865 Fcurrent_buffer (), limit
);
2867 next_boundary
= XFASTINT (limit
);
2868 /* if the `invisible' property is set, we can skip to
2869 the next property change. */
2871 prop
= Fget_char_property (position
, Qinvisible
, ww
);
2872 if (TEXT_PROP_MEANS_INVISIBLE (prop
))
2874 if (pos
< PT
&& next_boundary
>= PT
)
2877 cursor_hpos
= p1
- leftmargin
;
2879 pos
= next_boundary
;
2880 last_invis_skip
= pos
;
2881 last_invis_prop
= prop
;
2885 /* Did we reach point? Record the cursor location. */
2886 if (pos
== PT
&& cursor_vpos
< 0)
2889 cursor_hpos
= p1
- leftmargin
;
2892 /* Did we hit the end of the visible region of the buffer?
2896 /* Update charstarts for the end of this line. */
2897 /* Do nothing if off the left edge or at the right edge. */
2898 if (p1
>= leftmargin
&& p1
+ 1 != endp
)
2900 int *p2x
= &charstart
[(p1
< leftmargin
2908 /* Figure out where (if at all) the
2909 redisplay_end_trigger-hook should run. */
2910 if (MARKERP (w
->redisplay_end_trigger
)
2911 && XMARKER (w
->redisplay_end_trigger
)->buffer
!= 0)
2912 e_t_h
= marker_position (w
->redisplay_end_trigger
);
2913 else if (INTEGERP (w
->redisplay_end_trigger
))
2914 e_t_h
= XINT (w
->redisplay_end_trigger
);
2918 /* If we've gone past the place to run a hook,
2920 if (pos
>= e_t_h
&& e_t_h
!= ZV
)
2922 Lisp_Object args
[3];
2924 args
[0] = Qredisplay_end_trigger_functions
;
2925 XSETWINDOW (args
[1], w
);
2926 XSETINT (args
[2], e_t_h
);
2928 /* Since we are *trying* to run these functions,
2929 don't try to run them again, even if they get an error. */
2930 w
->redisplay_end_trigger
= Qnil
;
2931 Frun_hook_with_args (3, args
);
2934 /* Notice if it changed the face of this character. */
2935 next_face_change
= pos
;
2939 /* Did we hit a face change? Figure out what face we should
2940 use now. We also hit this the first time through the
2941 loop, to see what face we should start with. */
2942 if (pos
>= next_face_change
2943 && (FRAME_WINDOW_P (f
) || FRAME_MSDOS_P (f
)))
2944 current_face
= compute_char_face (f
, w
, pos
,
2945 region_beg
, region_end
,
2946 &next_face_change
, pos
+ 50, 0);
2949 /* Compute the next place we need to stop
2950 and do something special; set PAUSE. */
2954 if (pos
< next_boundary
&& next_boundary
< pause
)
2955 pause
= next_boundary
;
2956 if (pos
< next_face_change
&& next_face_change
< pause
)
2957 pause
= next_face_change
;
2962 /* Wouldn't you hate to read the next line to someone over
2964 if (pos
< PT
&& PT
< pause
)
2966 if (pos
< GPT
&& GPT
< pause
)
2969 p
= &FETCH_CHAR (pos
);
2978 /* Let a display table override all standard display methods. */
2979 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
2981 p1
= copy_part_of_rope (f
, p1
, leftmargin
,
2982 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
2983 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
2986 else if (c
>= 040 && c
< 0177)
2988 if (p1
>= leftmargin
)
2989 *p1
= MAKE_GLYPH (f
, c
, current_face
);
2995 if (last_invis_skip
== pos
2996 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop
))
3000 && indented_beyond_p (pos
+ 1, selective
))
3003 pos
= find_next_newline (pos
+ 1, 1);
3004 if (FETCH_CHAR (pos
- 1) == '\n')
3007 if (invis
&& selective_rlen
> 0 && p1
>= leftmargin
)
3009 p1
+= selective_rlen
;
3010 if (p1
- leftmargin
> width
)
3012 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
3013 (p1
- p1prev
), current_face
);
3016 /* Draw the face of the newline character as extending all the
3017 way to the end of the frame line. */
3020 if (p1
< leftmargin
)
3023 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
3027 /* Update charstarts for the newline that ended this line. */
3028 /* Do nothing here for a char that's entirely off the left edge
3029 or if it starts at the right edge. */
3030 if (p1
>= leftmargin
&& p1prev
!= endp
)
3032 /* Store the newline's position into charstarts
3033 for the column where the newline starts.
3034 Store -1 for the rest of the glyphs it occupies. */
3035 int *p2x
= &charstart
[(p1prev
< leftmargin
3036 ? leftmargin
: p1prev
)
3038 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
3051 if (p1
>= leftmargin
&& p1
< endp
)
3052 *p1
= MAKE_GLYPH (f
, ' ', current_face
);
3055 while ((p1
- leftmargin
+ taboffset
+ hscroll
- (hscroll
> 0))
3058 else if (c
== Ctl ('M') && selective
== -1)
3060 pos
= find_next_newline (pos
, 1);
3061 if (FETCH_CHAR (pos
- 1) == '\n')
3063 if (selective_rlen
> 0)
3065 p1
+= selective_rlen
;
3066 if (p1
- leftmargin
> width
)
3068 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
3069 (p1
- p1prev
), current_face
);
3072 /* Draw the face of the newline character as extending all the
3073 way to the end of the frame line. */
3076 if (p1
< leftmargin
)
3079 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
3083 /* Update charstarts for the ^M that ended this line. */
3084 /* Do nothing here for a char that's entirely off the left edge
3085 or if it starts at the right edge. */
3086 if (p1
>= leftmargin
&& p1prev
!= endp
)
3088 /* Store the newline's position into charstarts
3089 for the column where the newline starts.
3090 Store -1 for the rest of the glyphs it occupies. */
3091 int *p2x
= &charstart
[(p1prev
< leftmargin
3092 ? leftmargin
: p1prev
)
3094 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
3102 else if (c
< 0200 && ctl_arrow
)
3104 if (p1
>= leftmargin
)
3105 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
3106 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
3109 if (p1
>= leftmargin
&& p1
< endp
)
3110 *p1
= MAKE_GLYPH (f
, c
^ 0100, current_face
);
3115 if (p1
>= leftmargin
)
3116 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
3117 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
3120 if (p1
>= leftmargin
&& p1
< endp
)
3121 *p1
= MAKE_GLYPH (f
, (c
>> 6) + '0', current_face
);
3123 if (p1
>= leftmargin
&& p1
< endp
)
3124 *p1
= MAKE_GLYPH (f
, (7 & (c
>> 3)) + '0', current_face
);
3126 if (p1
>= leftmargin
&& p1
< endp
)
3127 *p1
= MAKE_GLYPH (f
, (7 & c
) + '0', current_face
);
3134 /* Update charstarts for the character just output. */
3136 /* Do nothing here for a char that's entirely off the left edge. */
3137 if (p1
>= leftmargin
)
3139 /* Store the char's position into charstarts
3140 for the first glyph occupied by this char.
3141 Store -1 for the rest of the glyphs it occupies. */
3144 int *p2x
= &charstart
[(p1prev
< leftmargin
3145 ? leftmargin
: p1prev
)
3147 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
3157 val
.hpos
= - XINT (w
->hscroll
);
3165 /* Store 0 in this charstart line for the positions where
3166 there is no character. But do leave what was recorded
3167 for the character that ended the line. */
3168 /* Add 1 in the endtest to compensate for the fact that ENDP was
3169 made from WIDTH, which is 1 less than the window's actual
3171 i
= p1
- p1start
+ 1;
3172 if (p1
< leftmargin
)
3173 i
+= leftmargin
- p1
;
3174 for (; i
< endp
- p1start
+ 1; i
++)
3177 /* Handle continuation in middle of a character */
3178 /* by backing up over it */
3181 /* Don't back up if we never actually displayed any text.
3182 This occurs when the minibuffer prompt takes up the whole line. */
3185 /* Start the next line with that same character */
3187 /* but at negative hpos, to skip the columns output on this line. */
3188 val
.hpos
+= p1prev
- endp
;
3191 /* Keep in this line everything up to the continuation column. */
3195 /* Finish deciding which character to start the next line on,
3196 and what hpos to start it at.
3197 Also set `lastpos' to the last position which counts as "on this line"
3198 for cursor-positioning. */
3202 if (FETCH_CHAR (pos
) == '\n')
3204 /* If stopped due to a newline, start next line after it */
3206 /* Check again for hidden lines, in case the newline occurred exactly
3207 at the right margin. */
3208 while (pos
< ZV
&& selective
> 0
3209 && indented_beyond_p (pos
, selective
))
3210 pos
= find_next_newline (pos
, 1);
3213 /* Stopped due to right margin of window */
3217 *p1
++ = fix_glyph (f
, truncator
, 0);
3218 /* Truncating => start next line after next newline,
3219 and point is on this line if it is before the newline,
3220 and skip none of first char of next line */
3222 pos
= find_next_newline (pos
, 1);
3223 while (pos
< ZV
&& selective
> 0
3224 && indented_beyond_p (pos
, selective
));
3225 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
3227 lastpos
= pos
- (FETCH_CHAR (pos
- 1) == '\n');
3231 *p1
++ = fix_glyph (f
, continuer
, 0);
3238 /* If point is at eol or in invisible text at eol,
3239 record its frame location now. */
3241 if (start
<= PT
&& PT
<= lastpos
&& cursor_vpos
< 0)
3244 cursor_hpos
= p1
- leftmargin
;
3247 if (cursor_vpos
== vpos
)
3249 if (cursor_hpos
< 0) cursor_hpos
= 0;
3250 if (cursor_hpos
> width
) cursor_hpos
= width
;
3251 cursor_hpos
+= WINDOW_LEFT_MARGIN (w
);
3252 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
3254 if (!(cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f
)
3255 && EQ (FRAME_MINIBUF_WINDOW (f
), minibuf_window
)))
3257 FRAME_CURSOR_Y (f
) = cursor_vpos
;
3258 FRAME_CURSOR_X (f
) = cursor_hpos
;
3261 if (w
== XWINDOW (selected_window
))
3263 /* Line is not continued and did not start
3264 in middle of character */
3265 if ((hpos
- WINDOW_LEFT_MARGIN (w
)
3266 == (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
3269 this_line_bufpos
= start
;
3270 this_line_buffer
= current_buffer
;
3271 this_line_vpos
= cursor_vpos
;
3272 this_line_start_hpos
= hpos
;
3273 this_line_endpos
= Z
- lastpos
;
3276 this_line_bufpos
= 0;
3281 /* If hscroll and line not empty, insert truncation-at-left marker */
3282 if (hscroll
&& lastpos
!= start
)
3284 *leftmargin
= fix_glyph (f
, truncator
, 0);
3285 if (p1
<= leftmargin
)
3286 p1
= leftmargin
+ 1;
3289 if (!WINDOW_RIGHTMOST_P (w
))
3292 if (p1
< leftmargin
) p1
= leftmargin
;
3293 while (p1
< endp
) *p1
++ = SPACEGLYPH
;
3295 /* Don't draw vertical bars if we're using scroll bars. They're
3296 covered up by the scroll bars, and it's distracting to see
3297 them when the scroll bar windows are flickering around to be
3299 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
3302 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
3305 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3306 *p1
++ = (dp
&& INTEGERP (DISP_BORDER_GLYPH (dp
))
3307 ? DISP_BORDER_GLYPH (dp
)
3310 desired_glyphs
->used
[vpos
] = max (desired_glyphs
->used
[vpos
],
3311 p1
- desired_glyphs
->glyphs
[vpos
]);
3312 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
3314 /* If the start of this line is the overlay arrow-position,
3315 then put the arrow string into the display-line. */
3317 if (MARKERP (Voverlay_arrow_position
)
3318 && current_buffer
== XMARKER (Voverlay_arrow_position
)->buffer
3319 && start
== marker_position (Voverlay_arrow_position
)
3320 && STRINGP (Voverlay_arrow_string
)
3321 && ! overlay_arrow_seen
)
3323 unsigned char *p
= XSTRING (Voverlay_arrow_string
)->data
;
3325 int len
= XSTRING (Voverlay_arrow_string
)->size
;
3331 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string
)->intervals
))
3333 /* If the arrow string has text props, obey them when displaying. */
3334 for (i
= 0; i
< len
; i
++)
3337 Lisp_Object face
, ilisp
;
3340 XSETFASTINT (ilisp
, i
);
3341 face
= Fget_text_property (ilisp
, Qface
, Voverlay_arrow_string
);
3342 newface
= compute_glyph_face_1 (f
, face
, 0);
3343 leftmargin
[i
] = FAST_MAKE_GLYPH (c
, newface
);
3347 #endif /* HAVE_FACES */
3349 for (i
= 0; i
< len
; i
++)
3350 leftmargin
[i
] = p
[i
];
3353 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
3354 arrow_end
= (leftmargin
- desired_glyphs
->glyphs
[vpos
]) + len
;
3355 if (desired_glyphs
->used
[vpos
] < arrow_end
)
3356 desired_glyphs
->used
[vpos
] = arrow_end
;
3358 overlay_arrow_seen
= 1;
3362 val
.ovstring_chars_done
= ovstr_done
;
3363 val_display_text_line
= val
;
3364 return &val_display_text_line
;
3367 /* Redisplay the menu bar in the frame for window W. */
3370 display_menu_bar (w
)
3373 Lisp_Object items
, tail
;
3374 register int vpos
= 0;
3375 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3376 int maxendcol
= FRAME_WIDTH (f
);
3381 if (!NILP (Vwindow_system
))
3385 #ifdef USE_X_TOOLKIT
3388 #endif /* USE_X_TOOLKIT */
3390 get_display_line (f
, vpos
, 0);
3392 items
= FRAME_MENU_BAR_ITEMS (f
);
3393 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
3395 Lisp_Object pos
, string
;
3396 string
= XVECTOR (items
)->contents
[i
+ 1];
3400 XSETFASTINT (XVECTOR (items
)->contents
[i
+ 3], hpos
);
3402 if (hpos
< maxendcol
)
3403 hpos
= display_string (XWINDOW (FRAME_ROOT_WINDOW (f
)), vpos
,
3404 XSTRING (string
)->data
,
3405 XSTRING (string
)->size
,
3406 hpos
, 0, 0, hpos
, maxendcol
);
3407 /* Put a space between items. */
3408 if (hpos
< maxendcol
)
3410 int hpos1
= hpos
+ 1;
3411 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0,
3412 min (hpos1
, maxendcol
), maxendcol
);
3416 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3417 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3419 /* Fill out the line with spaces. */
3420 if (maxendcol
> hpos
)
3421 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0, maxendcol
, maxendcol
);
3423 /* Clear the rest of the lines allocated to the menu bar. */
3425 while (vpos
< FRAME_MENU_BAR_LINES (f
))
3426 get_display_line (f
, vpos
++, 0);
3429 /* Display the mode line for window w */
3432 display_mode_line (w
)
3435 register int vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
3436 register int left
= WINDOW_LEFT_MARGIN (w
);
3437 register int right
= WINDOW_RIGHT_MARGIN (w
);
3438 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3440 line_number_displayed
= 0;
3441 w
->column_number_displayed
= Qnil
;
3443 get_display_line (f
, vpos
, left
);
3445 /* Temporarily make frame F's kboard the current kboard
3446 so that kboard-local variables in the mode_line_format
3447 will get the right values. */
3448 push_frame_kboard (f
);
3450 display_mode_element (w
, vpos
, left
, 0, right
, right
,
3451 current_buffer
->mode_line_format
);
3453 pop_frame_kboard ();
3455 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3457 /* Put the mode line in inverse video.
3458 Use faces if possible, since that lets us handle
3459 partial-width windows and avoid inverting the scroll bar columns. */
3461 if (! FRAME_TERMCAP_P (f
) && mode_line_inverse_video
)
3463 /* For a partial width window, explicitly set face of each glyph. */
3465 GLYPH
*ptr
= FRAME_DESIRED_GLYPHS (f
)->glyphs
[vpos
];
3466 for (i
= left
; i
< right
; ++i
)
3467 ptr
[i
] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr
[i
]), 1);
3471 /* Make the mode line inverse video if the entire line
3472 is made of mode lines.
3473 I.e. if this window is full width,
3474 or if it is the child of a full width window
3475 (which implies that that window is split side-by-side
3476 and the rest of this line is mode lines of the sibling windows). */
3477 else if (WINDOW_FULL_WIDTH_P (w
)
3478 || WINDOW_FULL_WIDTH_P (XWINDOW (w
->parent
)))
3479 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3482 /* Contribute ELT to the mode line for window W.
3483 How it translates into text depends on its data type.
3485 VPOS is the position of the mode line being displayed.
3487 HPOS is the position (absolute on frame) where this element's text
3488 should start. The output is truncated automatically at the right
3491 DEPTH is the depth in recursion. It is used to prevent
3492 infinite recursion here.
3494 MINENDCOL is the hpos before which the element may not end.
3495 The element is padded at the right with spaces if nec
3496 to reach this column.
3498 MAXENDCOL is the hpos past which this element may not extend.
3499 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3500 (This is necessary to make nested padding and truncation work.)
3502 Returns the hpos of the end of the text generated by ELT.
3503 The next element will receive that value as its HPOS arg,
3504 so as to concatenate the elements. */
3507 display_mode_element (w
, vpos
, hpos
, depth
, minendcol
, maxendcol
, elt
)
3509 register int vpos
, hpos
;
3512 register int maxendcol
;
3513 register Lisp_Object elt
;
3521 switch (SWITCH_ENUM_CAST (XTYPE (elt
)))
3525 /* A string: output it and check for %-constructs within it. */
3526 register unsigned char c
;
3527 register unsigned char *this = XSTRING (elt
)->data
;
3529 while (hpos
< maxendcol
&& *this)
3531 unsigned char *last
= this;
3532 while ((c
= *this++) != '\0' && c
!= '%')
3534 if (this - 1 != last
)
3536 register int lim
= --this - last
+ hpos
;
3537 if (frame_title_ptr
)
3538 hpos
= store_frame_title (last
, hpos
, min (lim
, maxendcol
));
3540 hpos
= display_string (w
, vpos
, last
, -1, hpos
, 0, 1,
3541 hpos
, min (lim
, maxendcol
));
3545 register int minendcol
;
3546 register int spec_width
= 0;
3548 /* We can't allow -ve args due to the "%-" construct */
3549 /* Argument specifies minwidth but not maxwidth
3550 (maxwidth can be specified by
3551 (<negative-number> . <stuff>) mode-line elements) */
3553 while ((c
= *this++) >= '0' && c
<= '9')
3555 spec_width
= spec_width
* 10 + (c
- '0');
3558 minendcol
= hpos
+ spec_width
;
3559 if (minendcol
> maxendcol
)
3561 spec_width
= maxendcol
- hpos
;
3562 minendcol
= maxendcol
;
3566 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
3567 spec_width
, maxendcol
,
3568 Vglobal_mode_string
);
3571 char *spec
= decode_mode_spec (w
, c
, spec_width
,
3573 if (frame_title_ptr
)
3574 hpos
= store_frame_title (spec
, minendcol
, maxendcol
);
3576 hpos
= display_string (w
, vpos
, spec
, -1,
3578 minendcol
, maxendcol
);
3586 /* A symbol: process the value of the symbol recursively
3587 as if it appeared here directly. Avoid error if symbol void.
3588 Special case: if value of symbol is a string, output the string
3591 register Lisp_Object tem
;
3592 tem
= Fboundp (elt
);
3595 tem
= Fsymbol_value (elt
);
3596 /* If value is a string, output that string literally:
3597 don't check for % within it. */
3600 if (frame_title_ptr
)
3601 hpos
= store_frame_title (XSTRING (tem
)->data
,
3602 minendcol
, maxendcol
);
3604 hpos
= display_string (w
, vpos
, XSTRING (tem
)->data
,
3605 XSTRING (tem
)->size
,
3606 hpos
, 0, 1, minendcol
, maxendcol
);
3608 /* Give up right away for nil or t. */
3609 else if (!EQ (tem
, elt
))
3610 { elt
= tem
; goto tail_recurse
; }
3617 register Lisp_Object car
, tem
;
3619 /* A cons cell: three distinct cases.
3620 If first element is a string or a cons, process all the elements
3621 and effectively concatenate them.
3622 If first element is a negative number, truncate displaying cdr to
3623 at most that many characters. If positive, pad (with spaces)
3624 to at least that many characters.
3625 If first element is a symbol, process the cadr or caddr recursively
3626 according to whether the symbol's value is non-nil or nil. */
3627 car
= XCONS (elt
)->car
;
3630 tem
= Fboundp (car
);
3631 elt
= XCONS (elt
)->cdr
;
3634 /* elt is now the cdr, and we know it is a cons cell.
3635 Use its car if CAR has a non-nil value. */
3638 tem
= Fsymbol_value (car
);
3640 { elt
= XCONS (elt
)->car
; goto tail_recurse
; }
3642 /* Symbol's value is nil (or symbol is unbound)
3643 Get the cddr of the original list
3644 and if possible find the caddr and use that. */
3645 elt
= XCONS (elt
)->cdr
;
3648 else if (!CONSP (elt
))
3650 elt
= XCONS (elt
)->car
;
3653 else if (INTEGERP (car
))
3655 register int lim
= XINT (car
);
3656 elt
= XCONS (elt
)->cdr
;
3658 /* Negative int means reduce maximum width.
3659 DO NOT change MINENDCOL here!
3660 (20 -10 . foo) should truncate foo to 10 col
3661 and then pad to 20. */
3662 maxendcol
= min (maxendcol
, hpos
- lim
);
3665 /* Padding specified. Don't let it be more than
3668 if (lim
> maxendcol
)
3670 /* If that's more padding than already wanted, queue it.
3671 But don't reduce padding already specified even if
3672 that is beyond the current truncation point. */
3673 if (lim
> minendcol
)
3678 else if (STRINGP (car
) || CONSP (car
))
3680 register int limit
= 50;
3681 /* LIMIT is to protect against circular lists. */
3682 while (CONSP (elt
) && --limit
> 0
3683 && hpos
< maxendcol
)
3685 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
3688 elt
= XCONS (elt
)->cdr
;
3696 if (frame_title_ptr
)
3697 hpos
= store_frame_title ("*invalid*", minendcol
, maxendcol
);
3699 hpos
= display_string (w
, vpos
, "*invalid*", -1, hpos
, 0, 1,
3700 minendcol
, maxendcol
);
3704 if (minendcol
> hpos
)
3705 if (frame_title_ptr
)
3706 hpos
= store_frame_title ("", minendcol
, maxendcol
);
3708 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 1, minendcol
, maxendcol
);
3712 /* Write a null-terminated, right justified decimal representation of
3713 the positive integer D to BUF using a minimal field width WIDTH. */
3716 pint2str (buf
, width
, d
)
3721 register char *p
= buf
;
3728 *p
++ = d
% 10 + '0';
3731 for (width
-= (int) (p
- buf
); width
> 0; --width
) *p
++ = ' ';
3741 /* Return a string for the output of a mode line %-spec for window W,
3742 generated by character C. SPEC_WIDTH is the field width when
3743 padding to the left (%c, %l). The value returned from this
3744 function will later be truncated to width MAXWIDTH. */
3746 static char lots_of_dashes
[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3749 decode_mode_spec (w
, c
, spec_width
, maxwidth
)
3752 register int spec_width
;
3753 register int maxwidth
;
3756 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3757 char *decode_mode_spec_buf
= (char *) FRAME_TEMP_GLYPHS (f
)->total_contents
;
3758 struct buffer
*b
= XBUFFER (w
->buffer
);
3761 if (maxwidth
> FRAME_WIDTH (f
))
3762 maxwidth
= FRAME_WIDTH (f
);
3767 if (!NILP (b
->read_only
))
3769 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3774 /* This differs from %* only for a modified read-only buffer. */
3775 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3777 if (!NILP (b
->read_only
))
3782 /* This differs from %* in ignoring read-only-ness. */
3783 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3795 if (command_loop_level
> 5)
3797 p
= decode_mode_spec_buf
;
3798 for (i
= 0; i
< command_loop_level
; i
++)
3801 return decode_mode_spec_buf
;
3809 if (command_loop_level
> 5)
3811 p
= decode_mode_spec_buf
;
3812 for (i
= 0; i
< command_loop_level
; i
++)
3815 return decode_mode_spec_buf
;
3823 if (maxwidth
< sizeof (lots_of_dashes
))
3824 return lots_of_dashes
;
3827 for (p
= decode_mode_spec_buf
, i
= maxwidth
; i
> 0; i
--)
3831 return decode_mode_spec_buf
;
3837 if (maxwidth
>= 3 && XSTRING (obj
)->size
> maxwidth
)
3839 bcopy (XSTRING (obj
)->data
, decode_mode_spec_buf
, maxwidth
- 1);
3840 decode_mode_spec_buf
[maxwidth
- 1] = '\\';
3841 decode_mode_spec_buf
[maxwidth
] = '\0';
3842 return decode_mode_spec_buf
;
3849 int col
= current_column ();
3850 XSETFASTINT (w
->column_number_displayed
, col
);
3851 pint2str (decode_mode_spec_buf
, spec_width
, col
);
3852 return decode_mode_spec_buf
;
3856 /* %F displays the frame name. */
3857 if (!NILP (f
->title
))
3858 return (char *) XSTRING (f
->title
)->data
;
3859 if (f
->explicit_name
|| ! FRAME_WINDOW_P (f
))
3860 return (char *) XSTRING (f
->name
)->data
;
3868 else if (STRINGP (obj
) && XSTRING (obj
)->size
> maxwidth
)
3870 bcopy ("...", decode_mode_spec_buf
, 3);
3871 bcopy (XSTRING (obj
)->data
+ XSTRING (obj
)->size
- maxwidth
+ 3,
3872 decode_mode_spec_buf
+ 3, maxwidth
- 3);
3873 return decode_mode_spec_buf
;
3880 int startpos
= marker_position (w
->start
);
3881 int line
, linepos
, topline
;
3884 int height
= XFASTINT (w
->height
);
3886 /* If we decided that this buffer isn't suitable for line numbers,
3887 don't forget that too fast. */
3888 if (EQ (w
->base_line_pos
, w
->buffer
))
3890 /* But do forget it, if the window shows a different buffer now. */
3891 else if (BUFFERP (w
->base_line_pos
))
3892 w
->base_line_pos
= Qnil
;
3894 /* If the buffer is very big, don't waste time. */
3895 if (BUF_ZV (b
) - BUF_BEGV (b
) > line_number_display_limit
)
3897 w
->base_line_pos
= Qnil
;
3898 w
->base_line_number
= Qnil
;
3902 if (!NILP (w
->base_line_number
)
3903 && !NILP (w
->base_line_pos
)
3904 && XFASTINT (w
->base_line_pos
) <= marker_position (w
->start
))
3906 line
= XFASTINT (w
->base_line_number
);
3907 linepos
= XFASTINT (w
->base_line_pos
);
3912 linepos
= BUF_BEGV (b
);
3915 /* Count lines from base line to window start position. */
3916 nlines
= display_count_lines (linepos
, startpos
, startpos
, &junk
);
3918 topline
= nlines
+ line
;
3920 /* Determine a new base line, if the old one is too close
3921 or too far away, or if we did not have one.
3922 "Too close" means it's plausible a scroll-down would
3924 if (startpos
== BUF_BEGV (b
))
3926 XSETFASTINT (w
->base_line_number
, topline
);
3927 XSETFASTINT (w
->base_line_pos
, BUF_BEGV (b
));
3929 else if (nlines
< height
+ 25 || nlines
> height
* 3 + 50
3930 || linepos
== BUF_BEGV (b
))
3932 int limit
= BUF_BEGV (b
);
3934 int distance
= (height
* 2 + 30) * 200;
3936 if (startpos
- distance
> limit
)
3937 limit
= startpos
- distance
;
3939 nlines
= display_count_lines (startpos
, limit
,
3942 /* If we couldn't find the lines we wanted within
3944 give up on line numbers for this window. */
3945 if (position
== startpos
- distance
)
3947 w
->base_line_pos
= w
->buffer
;
3948 w
->base_line_number
= Qnil
;
3952 XSETFASTINT (w
->base_line_number
, topline
- nlines
);
3953 XSETFASTINT (w
->base_line_pos
, position
);
3956 /* Now count lines from the start pos to point. */
3957 nlines
= display_count_lines (startpos
, PT
, PT
, &junk
);
3959 /* Record that we did display the line number. */
3960 line_number_displayed
= 1;
3962 /* Make the string to show. */
3963 pint2str (decode_mode_spec_buf
, spec_width
, topline
+ nlines
);
3964 return decode_mode_spec_buf
;
3967 char* p
= decode_mode_spec_buf
;
3968 for (spec_width
-= 2; spec_width
> 0; --spec_width
) *p
++ = ' ';
3970 return decode_mode_spec_buf
;
3980 if (BUF_BEGV (b
) > BUF_BEG (b
) || BUF_ZV (b
) < BUF_Z (b
))
3986 int pos
= marker_position (w
->start
);
3987 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3989 if (XFASTINT (w
->window_end_pos
) <= BUF_Z (b
) - BUF_ZV (b
))
3991 if (pos
<= BUF_BEGV (b
))
3996 else if (pos
<= BUF_BEGV (b
))
4000 if (total
> 1000000)
4001 /* Do it differently for a large value, to avoid overflow. */
4002 total
= ((pos
- BUF_BEGV (b
)) + (total
/ 100) - 1) / (total
/ 100);
4004 total
= ((pos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
4005 /* We can't normally display a 3-digit number,
4006 so get us a 2-digit number that is close. */
4009 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
4010 return decode_mode_spec_buf
;
4014 /* Display percentage of size above the bottom of the screen. */
4017 int toppos
= marker_position (w
->start
);
4018 int botpos
= BUF_Z (b
) - XFASTINT (w
->window_end_pos
);
4019 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
4021 if (botpos
>= BUF_ZV (b
))
4023 if (toppos
<= BUF_BEGV (b
))
4030 if (total
> 1000000)
4031 /* Do it differently for a large value, to avoid overflow. */
4032 total
= ((botpos
- BUF_BEGV (b
)) + (total
/ 100) - 1) / (total
/ 100);
4034 total
= ((botpos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
4035 /* We can't normally display a 3-digit number,
4036 so get us a 2-digit number that is close. */
4039 if (toppos
<= BUF_BEGV (b
))
4040 sprintf (decode_mode_spec_buf
, "Top%2d%%", total
);
4042 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
4043 return decode_mode_spec_buf
;
4048 /* status of process */
4049 obj
= Fget_buffer_process (w
->buffer
);
4051 return "no process";
4053 obj
= Fsymbol_name (Fprocess_status (obj
));
4057 case 't': /* indicate TEXT or BINARY */
4058 #ifdef MODE_LINE_BINARY_TEXT
4059 return MODE_LINE_BINARY_TEXT (b
);
4066 return (char *) XSTRING (obj
)->data
;
4071 /* Search for COUNT instances of a line boundary, which means either a
4072 newline or (if selective display enabled) a carriage return.
4073 Start at START. If COUNT is negative, search backwards.
4075 If we find COUNT instances, set *SHORTAGE to zero, and return the
4076 position after the COUNTth match. Note that for reverse motion
4077 this is not the same as the usual convention for Emacs motion commands.
4079 If we don't find COUNT instances before reaching the end of the
4080 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
4081 the number of line boundaries left unfound, and return the end of the
4082 buffer we bumped up against. */
4085 display_scan_buffer (start
, count
, shortage
)
4086 int *shortage
, start
;
4089 int limit
= ((count
> 0) ? ZV
- 1 : BEGV
);
4090 int direction
= ((count
> 0) ? 1 : -1);
4092 register unsigned char *cursor
;
4093 unsigned char *base
;
4095 register int ceiling
;
4096 register unsigned char *ceiling_addr
;
4098 /* If we are not in selective display mode,
4099 check only for newlines. */
4100 if (! (!NILP (current_buffer
->selective_display
)
4101 && !INTEGERP (current_buffer
->selective_display
)))
4102 return scan_buffer ('\n', start
, 0, count
, shortage
, 0);
4104 /* The code that follows is like scan_buffer
4105 but checks for either newline or carriage return. */
4111 while (start
!= limit
+ 1)
4113 ceiling
= BUFFER_CEILING_OF (start
);
4114 ceiling
= min (limit
, ceiling
);
4115 ceiling_addr
= &FETCH_CHAR (ceiling
) + 1;
4116 base
= (cursor
= &FETCH_CHAR (start
));
4119 while (*cursor
!= '\n' && *cursor
!= 015 && ++cursor
!= ceiling_addr
)
4121 if (cursor
!= ceiling_addr
)
4126 return (start
+ cursor
- base
+ 1);
4129 if (++cursor
== ceiling_addr
)
4135 start
+= cursor
- base
;
4139 start
--; /* first character we scan */
4140 while (start
> limit
- 1)
4141 { /* we WILL scan under start */
4142 ceiling
= BUFFER_FLOOR_OF (start
);
4143 ceiling
= max (limit
, ceiling
);
4144 ceiling_addr
= &FETCH_CHAR (ceiling
) - 1;
4145 base
= (cursor
= &FETCH_CHAR (start
));
4149 while (--cursor
!= ceiling_addr
4150 && *cursor
!= '\n' && *cursor
!= 015)
4152 if (cursor
!= ceiling_addr
)
4157 return (start
+ cursor
- base
+ 1);
4163 start
+= cursor
- base
;
4168 *shortage
= count
* direction
;
4169 return (start
+ ((direction
== 1 ? 0 : 1)));
4172 /* Count up to N lines starting from FROM.
4173 But don't go beyond LIMIT.
4174 Return the number of lines thus found (always positive).
4175 Store the position after what was found into *POS_PTR. */
4178 display_count_lines (from
, limit
, n
, pos_ptr
)
4191 *pos_ptr
= display_scan_buffer (from
, n
, &shortage
);
4197 /* When scanning backwards, scan_buffer stops *after* the last newline
4198 it finds, but does count it. Compensate for that. */
4199 return - n
- shortage
- (*pos_ptr
!= limit
);
4200 return n
- shortage
;
4203 /* Display STRING on one line of window W, starting at HPOS.
4204 Display at position VPOS. Caller should have done get_display_line.
4205 If VPOS == -1, display it as the current frame's title.
4206 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
4208 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
4210 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
4211 MAXCOL is the last column ok to end at. Truncate here.
4212 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
4213 Both count from the left edge of the frame, as does HPOS.
4214 The right edge of W is an implicit maximum.
4215 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
4217 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
4218 at the place where the current window ends in this line
4219 and not display anything beyond there. Otherwise, only MAXCOL
4220 controls where to stop output.
4222 Returns ending hpos. */
4225 display_string (w
, vpos
, string
, length
, hpos
, truncate
,
4226 obey_window_width
, mincol
, maxcol
)
4228 unsigned char *string
;
4232 int obey_window_width
;
4238 int hscroll
= XINT (w
->hscroll
);
4239 int tab_width
= XINT (XBUFFER (w
->buffer
)->tab_width
);
4240 register GLYPH
*start
;
4241 register GLYPH
*end
;
4242 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
4243 struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
4244 GLYPH
*p1start
= desired_glyphs
->glyphs
[vpos
] + hpos
;
4245 int window_width
= XFASTINT (w
->width
);
4247 /* Use the standard display table, not the window's display table.
4248 We don't want the mode line in rot13. */
4249 register struct Lisp_Char_Table
*dp
= 0;
4252 if (DISP_TABLE_P (Vstandard_display_table
))
4253 dp
= XCHAR_TABLE (Vstandard_display_table
);
4255 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
4258 start
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
4260 if (obey_window_width
)
4262 end
= start
+ window_width
- (truncate
!= 0);
4264 if (!WINDOW_RIGHTMOST_P (w
))
4266 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4270 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
4273 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4278 if (! obey_window_width
4279 || (maxcol
>= 0 && end
- desired_glyphs
->glyphs
[vpos
] > maxcol
))
4280 end
= desired_glyphs
->glyphs
[vpos
] + maxcol
;
4282 /* Store 0 in charstart for these columns. */
4283 for (i
= (hpos
>= 0 ? hpos
: 0); i
< end
- p1start
+ hpos
; i
++)
4284 desired_glyphs
->charstarts
[vpos
][i
] = 0;
4286 if (maxcol
>= 0 && mincol
> maxcol
)
4289 /* We set truncated to 1 if we get stopped by trying to pass END
4290 (that is, trying to pass MAXCOL.) */
4297 /* Specified length. */
4300 /* Unspecified length (null-terminated string). */
4310 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
4312 p1
= copy_part_of_rope (f
, p1
, start
,
4313 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
4314 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
4317 else if (c
>= 040 && c
< 0177)
4327 if (p1
>= start
&& p1
< end
)
4331 while ((p1
- start
+ hscroll
- (hscroll
> 0)) % tab_width
);
4333 else if (c
< 0200 && ! NILP (buffer_defaults
.ctl_arrow
))
4336 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
4337 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
4340 if (p1
>= start
&& p1
< end
)
4347 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
4348 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
4351 if (p1
>= start
&& p1
< end
)
4352 *p1
= (c
>> 6) + '0';
4354 if (p1
>= start
&& p1
< end
)
4355 *p1
= (7 & (c
>> 3)) + '0';
4357 if (p1
>= start
&& p1
< end
)
4358 *p1
= (7 & c
) + '0';
4366 if (truncate
) *p1
++ = fix_glyph (f
, truncate
, 0);
4368 else if (mincol
>= 0)
4370 end
= desired_glyphs
->glyphs
[vpos
] + mincol
;
4376 register int len
= p1
- desired_glyphs
->glyphs
[vpos
];
4378 if (len
> desired_glyphs
->used
[vpos
])
4379 desired_glyphs
->used
[vpos
] = len
;
4380 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
4386 /* This is like a combination of memq and assq.
4387 Return 1 if PROPVAL appears as an element of LIST
4388 or as the car of an element of LIST.
4389 If PROPVAL is a list, compare each element against LIST
4390 in that way, and return 1 if any element of PROPVAL is found in LIST.
4392 This function cannot quit. */
4395 invisible_p (propval
, list
)
4396 register Lisp_Object propval
;
4399 register Lisp_Object tail
, proptail
;
4400 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4402 register Lisp_Object tem
;
4403 tem
= XCONS (tail
)->car
;
4404 if (EQ (propval
, tem
))
4406 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4409 if (CONSP (propval
))
4410 for (proptail
= propval
; CONSP (proptail
);
4411 proptail
= XCONS (proptail
)->cdr
)
4413 Lisp_Object propelt
;
4414 propelt
= XCONS (proptail
)->car
;
4415 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4417 register Lisp_Object tem
;
4418 tem
= XCONS (tail
)->car
;
4419 if (EQ (propelt
, tem
))
4421 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4428 /* Return 1 if PROPVAL appears as the car of an element of LIST
4429 and the cdr of that element is non-nil.
4430 If PROPVAL is a list, check each element of PROPVAL in that way,
4431 and the first time some element is found,
4432 return 1 if the cdr of that element is non-nil.
4434 This function cannot quit. */
4437 invisible_ellipsis_p (propval
, list
)
4438 register Lisp_Object propval
;
4441 register Lisp_Object tail
, proptail
;
4442 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4444 register Lisp_Object tem
;
4445 tem
= XCONS (tail
)->car
;
4446 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4447 return ! NILP (XCONS (tem
)->cdr
);
4449 if (CONSP (propval
))
4450 for (proptail
= propval
; CONSP (proptail
);
4451 proptail
= XCONS (proptail
)->cdr
)
4453 Lisp_Object propelt
;
4454 propelt
= XCONS (proptail
)->car
;
4455 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4457 register Lisp_Object tem
;
4458 tem
= XCONS (tail
)->car
;
4459 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4460 return ! NILP (XCONS (tem
)->cdr
);
4469 staticpro (&Qmenu_bar_update_hook
);
4470 Qmenu_bar_update_hook
= intern ("menu-bar-update-hook");
4472 staticpro (&Qoverriding_terminal_local_map
);
4473 Qoverriding_terminal_local_map
= intern ("overriding-terminal-local-map");
4475 staticpro (&Qoverriding_local_map
);
4476 Qoverriding_local_map
= intern ("overriding-local-map");
4478 staticpro (&Qwindow_scroll_functions
);
4479 Qwindow_scroll_functions
= intern ("window-scroll-functions");
4481 staticpro (&Qredisplay_end_trigger_functions
);
4482 Qredisplay_end_trigger_functions
= intern ("redisplay-end-trigger-functions");
4484 staticpro (&last_arrow_position
);
4485 staticpro (&last_arrow_string
);
4486 last_arrow_position
= Qnil
;
4487 last_arrow_string
= Qnil
;
4489 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
,
4490 "String (or mode line construct) included (normally) in `mode-line-format'.");
4491 Vglobal_mode_string
= Qnil
;
4493 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
,
4494 "Marker for where to display an arrow on top of the buffer text.\n\
4495 This must be the beginning of a line in order to work.\n\
4496 See also `overlay-arrow-string'.");
4497 Voverlay_arrow_position
= Qnil
;
4499 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
,
4500 "String to display as an arrow. See also `overlay-arrow-position'.");
4501 Voverlay_arrow_string
= Qnil
;
4503 DEFVAR_INT ("scroll-step", &scroll_step
,
4504 "*The number of lines to try scrolling a window by when point moves out.\n\
4505 If that fails to bring point back on frame, point is centered instead.\n\
4506 If this is zero, point is always centered after it moves off frame.");
4508 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively
,
4509 "*Scroll up to this many lines, to bring point back on screen.");
4510 scroll_conservatively
= 0;
4512 DEFVAR_INT ("scroll-margin", &scroll_margin
,
4513 "*Number of lines of margin at the top and bottom of a window.\n\
4514 Recenter the window whenever point gets within this many lines\n\
4515 of the top or bottom of the window.");
4518 DEFVAR_INT ("debug-end-pos", &debug_end_pos
, "Don't ask");
4520 DEFVAR_BOOL ("truncate-partial-width-windows",
4521 &truncate_partial_width_windows
,
4522 "*Non-nil means truncate lines in all windows less than full frame wide.");
4523 truncate_partial_width_windows
= 1;
4525 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
,
4526 "*Non-nil means use inverse video for the mode line.");
4527 mode_line_inverse_video
= 1;
4529 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit
,
4530 "*Maximum buffer size for which line number should be displayed.");
4531 line_number_display_limit
= 1000000;
4533 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
,
4534 "*Non-nil means highlight region even in nonselected windows.");
4535 highlight_nonselected_windows
= 1;
4537 DEFVAR_BOOL ("multiple-frames", &multiple_frames
,
4538 "Non-nil if more than one frame is visible on this display.\n\
4539 Minibuffer-only frames don't count, but iconified frames do.\n\
4540 This variable is not guaranteed to be accurate except while processing\n\
4541 `frame-title-format' and `icon-title-format'.");
4543 DEFVAR_LISP ("frame-title-format", &Vframe_title_format
,
4544 "Template for displaying the titlebar of visible frames.\n\
4545 \(Assuming the window manager supports this feature.)\n\
4546 This variable has the same structure as `mode-line-format' (which see),\n\
4547 and is used only on frames for which no explicit name has been set\n\
4548 \(see `modify-frame-parameters').");
4549 DEFVAR_LISP ("icon-title-format", &Vicon_title_format
,
4550 "Template for displaying the titlebar of an iconified frame.\n\
4551 \(Assuming the window manager supports this feature.)\n\
4552 This variable has the same structure as `mode-line-format' (which see),\n\
4553 and is used only on frames for which no explicit name has been set\n\
4554 \(see `modify-frame-parameters').");
4556 = Vframe_title_format
4557 = Fcons (intern ("multiple-frames"),
4558 Fcons (build_string ("%b"),
4559 Fcons (Fcons (build_string (""),
4560 Fcons (intern ("invocation-name"),
4561 Fcons (build_string ("@"),
4562 Fcons (intern ("system-name"),
4566 DEFVAR_LISP ("message-log-max", &Vmessage_log_max
,
4567 "Maximum number of lines to keep in the message log buffer.\n\
4568 If nil, disable message logging. If t, log messages but don't truncate\n\
4569 the buffer when it becomes large.");
4570 XSETFASTINT (Vmessage_log_max
, 50);
4572 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions
,
4573 "Functions called before redisplay, if window sizes have changed.\n\
4574 The value should be a list of functions that take one argument.\n\
4575 Just before redisplay, for each frame, if any of its windows have changed\n\
4576 size since the last redisplay, or have been split or deleted,\n\
4577 all the functions in the list are called, with the frame as argument.");
4578 Vwindow_size_change_functions
= Qnil
;
4580 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions
,
4581 "List of Functions to call before redisplaying a window with scrolling.\n\
4582 Each function is called with two arguments, the window\n\
4583 and its new display-start position. Note that the value of `window-end'\n\
4584 is not valid when these functions are called.");
4585 Vwindow_scroll_functions
= Qnil
;
4588 /* initialize the window system */
4591 Lisp_Object root_window
;
4592 #ifndef COMPILER_REGISTER_BUG
4594 #endif /* COMPILER_REGISTER_BUG */
4595 struct window
*mini_w
;
4597 this_line_bufpos
= 0;
4599 mini_w
= XWINDOW (minibuf_window
);
4600 root_window
= FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w
)));
4602 echo_area_glyphs
= 0;
4603 previous_echo_glyphs
= 0;
4605 if (!noninteractive
)
4607 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (root_window
)));
4608 XSETFASTINT (XWINDOW (root_window
)->top
, 0);
4609 set_window_height (root_window
, FRAME_HEIGHT (f
) - 1, 0);
4610 XSETFASTINT (mini_w
->top
, FRAME_HEIGHT (f
) - 1);
4611 set_window_height (minibuf_window
, 1, 0);
4613 XSETFASTINT (XWINDOW (root_window
)->width
, FRAME_WIDTH (f
));
4614 XSETFASTINT (mini_w
->width
, FRAME_WIDTH (f
));