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 ();
44 extern int interrupt_input
;
45 extern int command_loop_level
;
47 extern Lisp_Object Qface
;
49 extern Lisp_Object Voverriding_local_map
;
50 extern Lisp_Object Voverriding_local_map_menu_flag
;
52 Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
53 Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
54 Lisp_Object Qredisplay_end_trigger_functions
;
56 /* Nonzero means print newline to stdout before next minibuffer message. */
58 int noninteractive_need_newline
;
60 /* Nonzero means print newline to message log before next message. */
62 static int message_log_need_newline
;
64 #define min(a, b) ((a) < (b) ? (a) : (b))
65 #define max(a, b) ((a) > (b) ? (a) : (b))
66 #define minmax(floor, val, ceil) \
67 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
69 /* The buffer position of the first character appearing
70 entirely or partially on the current frame line.
71 Or zero, which disables the optimization for the current frame line. */
72 static int this_line_bufpos
;
74 /* Number of characters past the end of this line,
75 including the terminating newline */
76 static int this_line_endpos
;
78 /* The vertical position of this frame line. */
79 static int this_line_vpos
;
81 /* Hpos value for start of display on this frame line.
82 Usually zero, but negative if first character really began
84 static int this_line_start_hpos
;
86 /* Buffer that this_line variables are describing. */
87 static struct buffer
*this_line_buffer
;
89 /* Value of echo_area_glyphs when it was last acted on.
90 If this is nonzero, there is a message on the frame
91 in the minibuffer and it should be erased as soon
92 as it is no longer requested to appear. */
93 char *previous_echo_glyphs
;
95 /* Nonzero means truncate lines in all windows less wide than the frame */
96 int truncate_partial_width_windows
;
98 /* Nonzero means we have more than one non-minibuffer-only frame.
99 Not guaranteed to be accurate except while parsing frame-title-format. */
102 Lisp_Object Vglobal_mode_string
;
104 /* Marker for where to display an arrow on top of the buffer text. */
105 Lisp_Object Voverlay_arrow_position
;
107 /* String to display for the arrow. */
108 Lisp_Object Voverlay_arrow_string
;
110 /* Like mode-line-format, but for the titlebar on a visible frame. */
111 Lisp_Object Vframe_title_format
;
113 /* Like mode-line-format, but for the titlebar on an iconified frame. */
114 Lisp_Object Vicon_title_format
;
116 /* List of functions to call when a window's size changes. These
117 functions get one arg, a frame on which one or more windows' sizes
119 static Lisp_Object Vwindow_size_change_functions
;
121 /* Values of those variables at last redisplay. */
122 static Lisp_Object last_arrow_position
, last_arrow_string
;
124 Lisp_Object Qmenu_bar_update_hook
;
126 /* Nonzero if overlay arrow has been displayed once in this window. */
127 static int overlay_arrow_seen
;
129 /* Nonzero if visible end of buffer has already been displayed once
130 in this window. (We need this variable in case there are overlay
131 strings that get displayed there.) */
132 static int zv_strings_seen
;
134 /* Nonzero means highlight the region even in nonselected windows. */
135 static int highlight_nonselected_windows
;
137 /* If cursor motion alone moves point off frame,
138 Try scrolling this many lines up or down if that will bring it back. */
139 static int scroll_step
;
141 /* Nonzero if try_window_id has made blank lines at window bottom
142 since the last redisplay that paused */
143 static int blank_end_of_window
;
145 /* Number of windows showing the buffer of the selected window
146 (or another buffer with the same base buffer).
147 keyboard.c refers to this. */
150 /* display_text_line sets these to the frame position (origin 0) of point,
151 whether the window is selected or not.
152 Set one to -1 first to determine whether point was found afterwards. */
154 static int cursor_vpos
;
155 static int cursor_hpos
;
157 static int debug_end_pos
;
159 /* Nonzero means display mode line highlighted */
160 int mode_line_inverse_video
;
162 static int message_log_check_duplicate ();
163 static void echo_area_display ();
164 void mark_window_display_accurate ();
165 static void redisplay_windows ();
166 static void redisplay_window ();
167 static void update_menu_bar ();
168 static void try_window ();
169 static int try_window_id ();
170 static struct position
*display_text_line ();
171 static void display_mode_line ();
172 static int display_mode_element ();
173 static char *decode_mode_spec ();
174 static int display_string ();
175 static void display_menu_bar ();
176 static int display_count_lines ();
178 /* Prompt to display in front of the minibuffer contents */
179 Lisp_Object minibuf_prompt
;
181 /* Width in columns of current minibuffer prompt. */
182 int minibuf_prompt_width
;
184 /* Message to display instead of minibuffer contents
185 This is what the functions error and message make,
186 and command echoing uses it as well.
187 It overrides the minibuf_prompt as well as the buffer. */
188 char *echo_area_glyphs
;
190 /* This is the length of the message in echo_area_glyphs. */
191 int echo_area_glyphs_length
;
193 /* This is the window where the echo area message was displayed.
194 It is always a minibuffer window, but it may not be the
195 same window currently active as a minibuffer. */
196 Lisp_Object echo_area_window
;
198 /* true iff we should redraw the mode lines on the next redisplay */
199 int update_mode_lines
;
201 /* Smallest number of characters before the gap
202 at any time since last redisplay that finished.
203 Valid for current buffer when try_window_id can be called. */
206 /* Smallest number of characters after the gap
207 at any time since last redisplay that finished.
208 Valid for current buffer when try_window_id can be called. */
211 /* MODIFF as of last redisplay that finished;
212 if it matches MODIFF, beg_unchanged and end_unchanged
213 contain no useful information */
214 int unchanged_modified
;
216 /* Nonzero if window sizes or contents have changed
217 since last redisplay that finished */
218 int windows_or_buffers_changed
;
220 /* Nonzero after display_mode_line if %l was used
221 and it displayed a line number. */
222 int line_number_displayed
;
224 /* Maximum buffer size for which to display line numbers. */
225 static int line_number_display_limit
;
227 /* Number of lines to keep in the message log buffer.
228 t means infinite. nil means don't log at all. */
229 Lisp_Object Vmessage_log_max
;
232 message_log_maybe_newline ()
234 if (message_log_need_newline
)
235 message_dolog ("", 0, 1);
239 /* Add a string to the message log, optionally terminated with a newline.
240 This function calls low-level routines in order to bypass text property
241 hooks, etc. which might not be safe to run. */
244 message_dolog (m
, len
, nlflag
)
248 if (!NILP (Vmessage_log_max
))
250 struct buffer
*oldbuf
;
251 int oldpoint
, oldbegv
, oldzv
;
252 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
254 oldbuf
= current_buffer
;
255 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
256 current_buffer
->undo_list
= Qt
;
263 oldpoint
+= len
+ nlflag
;
265 oldzv
+= len
+ nlflag
;
268 insert_1 (m
, len
, 1, 0);
271 int this_bol
, prev_bol
, dup
;
272 insert_1 ("\n", 1, 1, 0);
274 this_bol
= scan_buffer ('\n', Z
, 0, -2, 0, 0);
277 prev_bol
= scan_buffer ('\n', this_bol
, 0, -2, 0, 0);
278 dup
= message_log_check_duplicate (prev_bol
, this_bol
);
281 if (oldpoint
> prev_bol
)
282 oldpoint
-= min (this_bol
, oldpoint
) - prev_bol
;
283 if (oldbegv
> prev_bol
)
284 oldbegv
-= min (this_bol
, oldbegv
) - prev_bol
;
285 if (oldzv
> prev_bol
)
286 oldzv
-= min (this_bol
, oldzv
) - prev_bol
;
287 del_range_1 (prev_bol
, this_bol
, 0);
293 /* If you change this format, don't forget to also
294 change message_log_check_duplicate. */
295 sprintf (dupstr
, " [%d times]", dup
);
296 duplen
= strlen (dupstr
);
302 insert_1 (dupstr
, duplen
, 1, 0);
307 if (NATNUMP (Vmessage_log_max
))
309 int pos
= scan_buffer ('\n', Z
, 0,
310 -XFASTINT (Vmessage_log_max
) - 1, 0, 0);
311 oldpoint
-= min (pos
, oldpoint
) - BEG
;
312 oldbegv
-= min (pos
, oldbegv
) - BEG
;
313 oldzv
-= min (pos
, oldzv
) - BEG
;
314 del_range_1 (BEG
, pos
, 0);
319 TEMP_SET_PT (oldpoint
);
320 set_buffer_internal (oldbuf
);
321 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
322 message_log_need_newline
= !nlflag
;
327 /* We are at the end of the buffer after just having inserted a newline.
328 (Note: We depend on the fact we won't be crossing the gap.)
329 Check to see if the most recent message looks a lot like the previous one.
330 Return 0 if different, 1 if the new one should just replace it, or a
331 value N > 1 if we should also append " [N times]". */
334 message_log_check_duplicate (prev_bol
, this_bol
)
335 int prev_bol
, this_bol
;
338 int len
= Z
- 1 - this_bol
;
340 unsigned char *p1
= BUF_CHAR_ADDRESS (current_buffer
, prev_bol
);
341 unsigned char *p2
= BUF_CHAR_ADDRESS (current_buffer
, this_bol
);
343 for (i
= 0; i
< len
; i
++)
345 if (i
>= 3 && p1
[i
-3] == '.' && p1
[i
-2] == '.' && p1
[i
-1] == '.'
354 if (*p1
++ == ' ' && *p1
++ == '[')
357 while (*p1
>= '0' && *p1
<= '9')
358 n
= n
* 10 + *p1
++ - '0';
359 if (strncmp (p1
, " times]\n", 8) == 0)
365 /* Display an echo area message M with a specified length of LEN chars.
366 The string may include null characters. If m is 0, clear out any
367 existing message, and let the minibuffer text show through.
368 Do not pass text that is stored in a Lisp string. */
375 /* First flush out any partial line written with print. */
376 message_log_maybe_newline ();
378 message_dolog (m
, len
, 1);
379 message2_nolog (m
, len
);
383 /* The non-logging part of that function. */
386 message2_nolog (m
, len
)
392 if (noninteractive_need_newline
)
394 noninteractive_need_newline
= 0;
395 fwrite (m
, len
, 1, stderr
);
396 if (cursor_in_echo_area
== 0)
397 fprintf (stderr
, "\n");
400 /* A null message buffer means that the frame hasn't really been
401 initialized yet. Error messages get reported properly by
402 cmd_error, so this must be just an informative message; toss it. */
403 else if (INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
405 Lisp_Object mini_window
;
408 /* Get the frame containing the minibuffer
409 that the selected frame is using. */
410 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
411 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
414 FRAME_SAMPLE_VISIBILITY (f
);
415 if (FRAME_VISIBLE_P (selected_frame
)
416 && ! FRAME_VISIBLE_P (f
))
417 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window
)));
422 echo_area_glyphs
= m
;
423 echo_area_glyphs_length
= len
;
426 echo_area_glyphs
= previous_echo_glyphs
= 0;
428 do_pending_window_change ();
429 echo_area_display ();
430 update_frame (f
, 1, 1);
431 do_pending_window_change ();
432 if (frame_up_to_date_hook
!= 0 && ! gc_in_progress
)
433 (*frame_up_to_date_hook
) (f
);
441 message2 (m
, (m
? strlen (m
) : 0));
448 message2_nolog (m
, (m
? strlen (m
) : 0));
451 /* Truncate what will be displayed in the echo area
452 the next time we display it--but don't redisplay it now. */
455 truncate_echo_area (len
)
458 /* A null message buffer means that the frame hasn't really been
459 initialized yet. Error messages get reported properly by
460 cmd_error, so this must be just an informative message; toss it. */
461 if (!noninteractive
&& INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
462 echo_area_glyphs_length
= len
;
465 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
466 zero if being used by message. */
467 int message_buf_print
;
469 /* Dump an informative message to the minibuf. If m is 0, clear out
470 any existing message, and let the minibuffer text show through. */
473 message (m
, a1
, a2
, a3
)
475 EMACS_INT a1
, a2
, a3
;
481 if (noninteractive_need_newline
)
483 noninteractive_need_newline
= 0;
484 fprintf (stderr
, m
, a1
, a2
, a3
);
485 if (cursor_in_echo_area
== 0)
486 fprintf (stderr
, "\n");
490 else if (INTERACTIVE
)
492 /* The frame whose minibuffer we're going to display the message on.
493 It may be larger than the selected frame, so we need
494 to use its buffer, not the selected frame's buffer. */
495 Lisp_Object mini_window
;
498 /* Get the frame containing the minibuffer
499 that the selected frame is using. */
500 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
501 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
503 /* A null message buffer means that the frame hasn't really been
504 initialized yet. Error messages get reported properly by
505 cmd_error, so this must be just an informative message; toss it. */
506 if (FRAME_MESSAGE_BUF (f
))
517 len
= doprnt (FRAME_MESSAGE_BUF (f
),
518 FRAME_WIDTH (f
), m
, (char *)0, 3, a
);
520 len
= doprnt (FRAME_MESSAGE_BUF (f
),
521 FRAME_WIDTH (f
), m
, (char *)0, 3, &a1
);
522 #endif /* NO_ARG_ARRAY */
524 message2 (FRAME_MESSAGE_BUF (f
), len
);
529 /* Print should start at the beginning of the message
531 message_buf_print
= 0;
536 /* The non-logging version of that function. */
538 message_nolog (m
, a1
, a2
, a3
)
540 EMACS_INT a1
, a2
, a3
;
542 Lisp_Object old_log_max
;
543 old_log_max
= Vmessage_log_max
;
544 Vmessage_log_max
= Qnil
;
545 message (m
, a1
, a2
, a3
);
546 Vmessage_log_max
= old_log_max
;
552 message2 (echo_area_glyphs
, echo_area_glyphs_length
);
560 Lisp_Object mini_window
;
562 /* Choose the minibuffer window for this display.
563 It is the minibuffer window used by the selected frame. */
564 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
565 /* This is the frame that window is in. */
566 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
568 if (! FRAME_VISIBLE_P (f
))
573 redraw_garbaged_frames ();
577 if (echo_area_glyphs
|| minibuf_level
== 0)
579 echo_area_window
= mini_window
;
581 vpos
= XFASTINT (XWINDOW (mini_window
)->top
);
582 get_display_line (f
, vpos
, 0);
583 display_string (XWINDOW (mini_window
), vpos
,
584 echo_area_glyphs
? echo_area_glyphs
: "",
585 echo_area_glyphs
? echo_area_glyphs_length
: -1,
586 0, 0, 0, 0, FRAME_WIDTH (f
));
588 #if 0 /* This just gets in the way. update_frame does the job. */
589 /* If desired cursor location is on this line, put it at end of text */
590 if (cursor_in_echo_area
)
591 FRAME_CURSOR_Y (f
) = vpos
;
592 if (FRAME_CURSOR_Y (f
) == vpos
)
593 FRAME_CURSOR_X (f
) = FRAME_DESIRED_GLYPHS (f
)->used
[vpos
];
596 /* Fill the rest of the minibuffer window with blank lines. */
601 i
< vpos
+ XFASTINT (XWINDOW (mini_window
)->height
); i
++)
603 get_display_line (f
, i
, 0);
604 display_string (XWINDOW (mini_window
), vpos
,
605 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f
));
609 else if (!EQ (mini_window
, selected_window
))
610 windows_or_buffers_changed
++;
612 if (EQ (mini_window
, selected_window
))
613 this_line_bufpos
= 0;
615 previous_echo_glyphs
= echo_area_glyphs
;
618 #ifdef HAVE_WINDOW_SYSTEM
619 static char frame_title_buf
[512];
620 static char *frame_title_ptr
;
623 store_frame_title (str
, mincol
, maxcol
)
628 if (maxcol
< 0 || maxcol
>= sizeof(frame_title_buf
))
629 maxcol
= sizeof (frame_title_buf
);
630 limit
= &frame_title_buf
[maxcol
];
631 while (*str
!= '\0' && frame_title_ptr
< limit
)
632 *frame_title_ptr
++ = *str
++;
633 while (frame_title_ptr
< &frame_title_buf
[mincol
])
634 *frame_title_ptr
++ = ' ';
635 return frame_title_ptr
- frame_title_buf
;
639 x_consider_frame_title (frame
)
645 FRAME_PTR f
= XFRAME (frame
);
647 if (!(FRAME_WINDOW_P (f
) || FRAME_MINIBUF_ONLY_P (f
) || f
->explicit_name
))
650 /* Do we have more than one visible frame on this X display? */
654 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
656 FRAME_PTR tf
= XFRAME (XCONS (tail
)->car
);
658 if (tf
!= f
&& FRAME_KBOARD (tf
) == FRAME_KBOARD (f
)
659 && !FRAME_MINIBUF_ONLY_P (tf
)
660 && (FRAME_VISIBLE_P (tf
) || FRAME_ICONIFIED_P (tf
)))
664 multiple_frames
= CONSP (tail
);
667 obuf
= current_buffer
;
668 Fset_buffer (XWINDOW (f
->selected_window
)->buffer
);
669 fmt
= (FRAME_ICONIFIED_P (f
) ? Vicon_title_format
: Vframe_title_format
);
670 frame_title_ptr
= frame_title_buf
;
671 len
= display_mode_element (XWINDOW (f
->selected_window
), 0, 0, 0,
672 0, sizeof (frame_title_buf
), fmt
);
674 set_buffer_internal (obuf
);
675 /* Set the name only if it's changed. This avoids consing
676 in the common case where it hasn't. (If it turns out that we've
677 already wasted too much time by walking through the list with
678 display_mode_element, then we might need to optimize at a higher
680 if (! STRINGP (f
->name
) || XSTRING (f
->name
)->size
!= len
681 || bcmp (frame_title_buf
, XSTRING (f
->name
)->data
, len
) != 0)
682 x_implicitly_set_name (f
, make_string (frame_title_buf
, len
), Qnil
);
685 #define frame_title_ptr ((char *)0)
686 #define store_frame_title(str, mincol, maxcol) 0
689 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
690 This can call eval. */
695 register struct window
*w
= XWINDOW (selected_window
);
697 struct gcpro gcpro1
, gcpro2
;
699 all_windows
= (update_mode_lines
|| buffer_shared
> 1
700 || windows_or_buffers_changed
);
702 /* Update all frame titles based on their buffer names, etc.
703 We do this before the menu bars so that the buffer-menu
704 will show the up-to-date frame titles.
706 This used to be done after the menu bars, for a reason that
707 was stated as follows but which I do not understand:
708 "We do this after the menu bars so that the frame will first
709 create its menu bar using the name `emacs' if no other name
710 has yet been specified."
711 I think that is no longer a concern. */
712 #ifdef HAVE_WINDOW_SYSTEM
713 if (windows_or_buffers_changed
|| update_mode_lines
)
715 Lisp_Object tail
, frame
;
717 FOR_EACH_FRAME (tail
, frame
)
718 if (FRAME_VISIBLE_P (XFRAME (frame
))
719 || FRAME_ICONIFIED_P (XFRAME (frame
)))
720 x_consider_frame_title (frame
);
724 /* Update the menu bar item lists, if appropriate.
725 This has to be done before any actual redisplay
726 or generation of display lines. */
729 Lisp_Object tail
, frame
;
730 int count
= specpdl_ptr
- specpdl
;
732 record_unwind_protect (Fstore_match_data
, Fmatch_data ());
734 FOR_EACH_FRAME (tail
, frame
)
736 /* If a window on this frame changed size,
737 report that to the user and clear the size-change flag. */
738 if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame
)))
740 Lisp_Object functions
;
741 /* Clear flag first in case we get error below. */
742 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame
)) = 0;
743 functions
= Vwindow_size_change_functions
;
744 GCPRO2 (tail
, functions
);
745 while (CONSP (functions
))
747 call1 (XCONS (functions
)->car
, frame
);
748 functions
= XCONS (functions
)->cdr
;
753 update_menu_bar (XFRAME (frame
), 0);
757 unbind_to (count
, Qnil
);
760 update_menu_bar (selected_frame
, 1);
763 /* Do a frame update, taking possible shortcuts into account.
764 This is the main external entry point for redisplay.
766 If the last redisplay displayed an echo area message and that
767 message is no longer requested, we clear the echo area
768 or bring back the minibuffer if that is in use.
770 Do not call eval from within this function.
771 Calls to eval after the call to echo_area_display would confuse
772 the display_line mechanism and would cause a crash.
773 Calls to eval before that point will work most of the time,
774 but can still lose, because this function
775 can be called from signal handlers; with alarms set up;
776 or with synchronous processes running.
778 See Fcall_process; if you called it from here, it could be
779 entered recursively. */
781 static int do_verify_charstarts
;
783 /* Counter is used to clear the face cache
784 no more than once ever 1000 redisplays. */
785 static int clear_face_cache_count
;
787 /* Record the previous terminal frame we displayed. */
788 static FRAME_PTR previous_terminal_frame
;
793 register struct window
*w
= XWINDOW (selected_window
);
797 register int tlbufpos
, tlendpos
;
804 if (FRAME_TERMCAP_P (selected_frame
)
805 && previous_terminal_frame
!= selected_frame
)
807 /* Since frames on an ASCII terminal share the same display area,
808 displaying a different frame means redisplay the whole thing. */
809 windows_or_buffers_changed
++;
810 SET_FRAME_GARBAGED (selected_frame
);
811 XSETFRAME (Vterminal_frame
, selected_frame
);
813 previous_terminal_frame
= selected_frame
;
816 /* Set the visible flags for all frames.
817 Do this before checking for resized or garbaged frames; they want
818 to know if their frames are visible.
819 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
821 Lisp_Object tail
, frame
;
823 FOR_EACH_FRAME (tail
, frame
)
825 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
827 /* Clear out all the display lines in which we will generate the
828 glyphs to display. */
829 init_desired_glyphs (XFRAME (frame
));
833 /* Notice any pending interrupt request to change frame size. */
834 do_pending_window_change ();
838 redraw_garbaged_frames ();
842 prepare_menu_bars ();
844 if (windows_or_buffers_changed
)
847 /* Detect case that we need to write a star in the mode line. */
848 if (XFASTINT (w
->last_modified
) < MODIFF
849 && XFASTINT (w
->last_modified
) <= SAVE_MODIFF
)
851 w
->update_mode_line
= Qt
;
852 if (buffer_shared
> 1)
856 /* If %c is in use, update it if needed. */
857 if (!NILP (w
->column_number_displayed
)
858 /* This alternative quickly identifies a common case
859 where no change is needed. */
860 && !(PT
== XFASTINT (w
->last_point
)
861 && XFASTINT (w
->last_modified
) >= MODIFF
)
862 && XFASTINT (w
->column_number_displayed
) != current_column ())
863 w
->update_mode_line
= Qt
;
865 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w
->frame
)) = -1;
867 all_windows
= update_mode_lines
|| buffer_shared
> 1;
869 /* If specs for an arrow have changed, do thorough redisplay
870 to ensure we remove any arrow that should no longer exist. */
871 if (! EQ (Voverlay_arrow_position
, last_arrow_position
)
872 || ! EQ (Voverlay_arrow_string
, last_arrow_string
))
875 /* Normally the message* functions will have already displayed and
876 updated the echo area, but the frame may have been trashed, or
877 the update may have been preempted, so display the echo area
879 if (echo_area_glyphs
|| previous_echo_glyphs
)
881 echo_area_display ();
885 /* If showing region, and mark has changed, must redisplay whole window. */
886 if (((!NILP (Vtransient_mark_mode
)
887 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
888 != !NILP (w
->region_showing
))
889 || (!NILP (w
->region_showing
)
890 && !EQ (w
->region_showing
,
891 Fmarker_position (XBUFFER (w
->buffer
)->mark
))))
892 this_line_bufpos
= -1;
894 tlbufpos
= this_line_bufpos
;
895 tlendpos
= this_line_endpos
;
896 if (!all_windows
&& tlbufpos
> 0 && NILP (w
->update_mode_line
)
897 && !current_buffer
->clip_changed
898 && FRAME_VISIBLE_P (XFRAME (w
->frame
))
899 /* Make sure recorded data applies to current buffer, etc */
900 && this_line_buffer
== current_buffer
901 && current_buffer
== XBUFFER (w
->buffer
)
902 && NILP (w
->force_start
)
903 /* Point must be on the line that we have info recorded about */
905 && PT
<= Z
- tlendpos
906 /* All text outside that line, including its final newline,
908 && (XFASTINT (w
->last_modified
) >= MODIFF
909 || (beg_unchanged
>= tlbufpos
- 1
911 /* If selective display, can't optimize
912 if the changes start at the beginning of the line. */
913 && ((INTEGERP (current_buffer
->selective_display
)
914 && XINT (current_buffer
->selective_display
) > 0
915 ? (beg_unchanged
>= tlbufpos
918 && end_unchanged
>= tlendpos
919 && Z
- GPT
>= tlendpos
)))
921 if (tlbufpos
> BEGV
&& FETCH_CHAR (tlbufpos
- 1) != '\n'
923 || FETCH_CHAR (tlbufpos
) == '\n'))
924 /* Former continuation line has disappeared by becoming empty */
926 else if (XFASTINT (w
->last_modified
) < MODIFF
927 || MINI_WINDOW_P (w
))
930 overlay_arrow_seen
= 0;
932 display_text_line (w
, tlbufpos
, this_line_vpos
, this_line_start_hpos
,
933 pos_tab_offset (w
, tlbufpos
));
934 /* If line contains point, is not continued,
935 and ends at same distance from eob as before, we win */
936 if (cursor_vpos
>= 0 && this_line_bufpos
937 && this_line_endpos
== tlendpos
)
939 /* If this is not the window's last line,
940 we must adjust the charstarts of the lines below. */
941 if (this_line_vpos
+ 1
942 < XFASTINT (w
->top
) + window_internal_height (w
))
944 int left
= XFASTINT (w
->left
);
945 int *charstart_next_line
946 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w
)))->charstarts
[this_line_vpos
+ 1];
949 if (Z
- tlendpos
== ZV
)
950 /* This line ends at end of (accessible part of) buffer.
951 There is no newline to count. */
952 adjust
= Z
- tlendpos
- charstart_next_line
[left
];
954 /* This line ends in a newline.
955 Must take account of the newline and the rest of the
956 text that follows. */
957 adjust
= Z
- tlendpos
+ 1 - charstart_next_line
[left
];
959 adjust_window_charstarts (w
, this_line_vpos
, adjust
);
962 if (XFASTINT (w
->width
) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w
))))
963 preserve_other_columns (w
);
969 else if (PT
== XFASTINT (w
->last_point
)
970 /* Make sure the cursor was last displayed
971 in this window. Otherwise we have to reposition it. */
972 && XINT (w
->top
) <= FRAME_CURSOR_Y (selected_frame
)
973 && (XINT (w
->top
) + XINT (w
->height
)
974 > FRAME_CURSOR_Y (selected_frame
)))
978 do_pending_window_change ();
983 /* If highlighting the region, or if the cursor is in the echo area,
984 then we can't just move the cursor. */
985 else if (! (!NILP (Vtransient_mark_mode
)
986 && !NILP (current_buffer
->mark_active
))
987 && NILP (w
->region_showing
)
988 && !cursor_in_echo_area
)
990 pos
= *compute_motion (tlbufpos
, 0,
991 XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0,
993 PT
, 2, - (1 << (BITS_PER_SHORT
- 1)),
994 window_internal_width (w
) - 1,
996 pos_tab_offset (w
, tlbufpos
), w
);
999 int width
= window_internal_width (w
) - 1;
1000 FRAME_CURSOR_X (selected_frame
)
1001 = XFASTINT (w
->left
) + minmax (0, pos
.hpos
, width
);
1002 FRAME_CURSOR_Y (selected_frame
) = this_line_vpos
;
1009 /* Text changed drastically or point moved off of line */
1010 cancel_line (this_line_vpos
, selected_frame
);
1013 this_line_bufpos
= 0;
1014 all_windows
|= buffer_shared
> 1;
1016 clear_face_cache_count
++;
1020 Lisp_Object tail
, frame
;
1023 /* Clear the face cache, only when we do a full redisplay
1024 and not too often either. */
1025 if (clear_face_cache_count
> 1000)
1027 clear_face_cache ();
1028 clear_face_cache_count
= 0;
1032 /* Recompute # windows showing selected buffer.
1033 This will be incremented each time such a window is displayed. */
1036 FOR_EACH_FRAME (tail
, frame
)
1038 FRAME_PTR f
= XFRAME (frame
);
1039 if (! FRAME_TERMCAP_P (f
) || f
== selected_frame
)
1042 /* Mark all the scroll bars to be removed; we'll redeem the ones
1043 we want when we redisplay their windows. */
1044 if (condemn_scroll_bars_hook
)
1045 (*condemn_scroll_bars_hook
) (f
);
1047 if (FRAME_VISIBLE_P (f
))
1048 redisplay_windows (FRAME_ROOT_WINDOW (f
));
1050 /* Any scroll bars which redisplay_windows should have nuked
1051 should now go away. */
1052 if (judge_scroll_bars_hook
)
1053 (*judge_scroll_bars_hook
) (f
);
1057 else if (FRAME_VISIBLE_P (selected_frame
))
1059 redisplay_window (selected_window
, 1);
1060 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
1061 preserve_other_columns (w
);
1065 /* Prevent various kinds of signals during display update.
1066 stdio is not robust about handling signals,
1067 which can cause an apparent I/O error. */
1068 if (interrupt_input
)
1079 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1083 if (!FRAMEP (XCONS (tail
)->car
))
1086 f
= XFRAME (XCONS (tail
)->car
);
1088 if ((! FRAME_TERMCAP_P (f
) || f
== selected_frame
)
1089 && FRAME_VISIBLE_P (f
))
1091 pause
|= update_frame (f
, 0, 0);
1094 mark_window_display_accurate (f
->root_window
, 1);
1095 if (frame_up_to_date_hook
!= 0)
1096 (*frame_up_to_date_hook
) (f
);
1102 #endif /* MULTI_FRAME */
1104 if (FRAME_VISIBLE_P (selected_frame
))
1105 pause
= update_frame (selected_frame
, 0, 0);
1109 /* We may have called echo_area_display at the top of this
1110 function. If the echo area is on another frame, that may
1111 have put text on a frame other than the selected one, so the
1112 above call to update_frame would not have caught it. Catch
1115 Lisp_Object mini_window
;
1116 FRAME_PTR mini_frame
;
1118 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
1119 mini_frame
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
1121 if (mini_frame
!= selected_frame
1122 && ! FRAME_TERMCAP_P (mini_frame
))
1123 pause
|= update_frame (mini_frame
, 0, 0);
1127 /* If frame does not match, prevent doing single-line-update next time.
1128 Also, don't forget to check every line to update the arrow. */
1131 this_line_bufpos
= 0;
1132 if (!NILP (last_arrow_position
))
1134 last_arrow_position
= Qt
;
1135 last_arrow_string
= Qt
;
1137 /* If we pause after scrolling, some lines in current_frame
1138 may be null, so preserve_other_columns won't be able to
1139 preserve all the vertical-bar separators. So, avoid using it
1141 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
1142 update_mode_lines
= 1;
1145 /* Now text on frame agrees with windows, so
1146 put info into the windows for partial redisplay to follow */
1150 register struct buffer
*b
= XBUFFER (w
->buffer
);
1152 blank_end_of_window
= 0;
1153 unchanged_modified
= BUF_MODIFF (b
);
1154 beg_unchanged
= BUF_GPT (b
) - BUF_BEG (b
);
1155 end_unchanged
= BUF_Z (b
) - BUF_GPT (b
);
1157 XSETFASTINT (w
->last_point
, BUF_PT (b
));
1158 XSETFASTINT (w
->last_point_x
, FRAME_CURSOR_X (selected_frame
));
1159 XSETFASTINT (w
->last_point_y
, FRAME_CURSOR_Y (selected_frame
));
1162 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame
), 1);
1165 b
->clip_changed
= 0;
1166 w
->update_mode_line
= Qnil
;
1167 XSETFASTINT (w
->last_modified
, BUF_MODIFF (b
));
1168 w
->window_end_valid
= w
->buffer
;
1169 last_arrow_position
= Voverlay_arrow_position
;
1170 last_arrow_string
= Voverlay_arrow_string
;
1171 if (do_verify_charstarts
)
1172 verify_charstarts (w
);
1173 if (frame_up_to_date_hook
!= 0)
1174 (*frame_up_to_date_hook
) (selected_frame
);
1176 update_mode_lines
= 0;
1177 windows_or_buffers_changed
= 0;
1180 /* Start SIGIO interrupts coming again.
1181 Having them off during the code above
1182 makes it less likely one will discard output,
1183 but not impossible, since there might be stuff
1184 in the system buffer here.
1185 But it is much hairier to try to do anything about that. */
1187 if (interrupt_input
)
1191 /* Change frame size now if a change is pending. */
1192 do_pending_window_change ();
1194 /* If we just did a pending size change, redisplay again
1195 for the new size. */
1196 if (windows_or_buffers_changed
&& !pause
)
1200 /* Redisplay, but leave alone any recent echo area message
1201 unless another message has been requested in its place.
1203 This is useful in situations where you need to redisplay but no
1204 user action has occurred, making it inappropriate for the message
1205 area to be cleared. See tracking_off and
1206 wait_reading_process_input for examples of these situations. */
1208 redisplay_preserve_echo_area ()
1210 if (echo_area_glyphs
== 0 && previous_echo_glyphs
!= 0)
1212 echo_area_glyphs
= previous_echo_glyphs
;
1214 echo_area_glyphs
= 0;
1221 mark_window_display_accurate (window
, flag
)
1225 register struct window
*w
;
1227 for (;!NILP (window
); window
= w
->next
)
1229 if (!WINDOWP (window
)) abort ();
1230 w
= XWINDOW (window
);
1232 if (!NILP (w
->buffer
))
1234 XSETFASTINT (w
->last_modified
,
1235 !flag
? 0 : BUF_MODIFF (XBUFFER (w
->buffer
)));
1237 /* Record if we are showing a region, so can make sure to
1238 update it fully at next redisplay. */
1239 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
1240 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
1241 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
1245 w
->window_end_valid
= w
->buffer
;
1246 w
->update_mode_line
= Qnil
;
1247 if (!NILP (w
->buffer
))
1248 XBUFFER (w
->buffer
)->clip_changed
= 0;
1250 if (!NILP (w
->vchild
))
1251 mark_window_display_accurate (w
->vchild
, flag
);
1252 if (!NILP (w
->hchild
))
1253 mark_window_display_accurate (w
->hchild
, flag
);
1258 last_arrow_position
= Voverlay_arrow_position
;
1259 last_arrow_string
= Voverlay_arrow_string
;
1263 /* t is unequal to any useful value of Voverlay_arrow_... */
1264 last_arrow_position
= Qt
;
1265 last_arrow_string
= Qt
;
1269 /* Update the menu bar item list for frame F.
1270 This has to be done before we start to fill in any display lines,
1271 because it can call eval.
1273 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1276 update_menu_bar (f
, save_match_data
)
1278 int save_match_data
;
1280 struct buffer
*old
= current_buffer
;
1282 register struct window
*w
;
1284 window
= FRAME_SELECTED_WINDOW (f
);
1285 w
= XWINDOW (window
);
1287 if (update_mode_lines
)
1288 w
->update_mode_line
= Qt
;
1292 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1293 FRAME_EXTERNAL_MENU_BAR (f
)
1295 FRAME_MENU_BAR_LINES (f
) > 0
1297 : FRAME_MENU_BAR_LINES (f
) > 0)
1299 /* If the user has switched buffers or windows, we need to
1300 recompute to reflect the new bindings. But we'll
1301 recompute when update_mode_lines is set too; that means
1302 that people can use force-mode-line-update to request
1303 that the menu bar be recomputed. The adverse effect on
1304 the rest of the redisplay algorithm is about the same as
1305 windows_or_buffers_changed anyway. */
1306 if (windows_or_buffers_changed
1307 || !NILP (w
->update_mode_line
)
1308 || (XFASTINT (w
->last_modified
) < MODIFF
1309 && (XFASTINT (w
->last_modified
)
1310 <= BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))))
1311 || ((!NILP (Vtransient_mark_mode
)
1312 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
1313 != !NILP (w
->region_showing
)))
1315 struct buffer
*prev
= current_buffer
;
1316 int count
= specpdl_ptr
- specpdl
;
1318 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1319 if (save_match_data
)
1320 record_unwind_protect (Fstore_match_data
, Fmatch_data ());
1321 if (NILP (Voverriding_local_map_menu_flag
))
1323 specbind (Qoverriding_terminal_local_map
, Qnil
);
1324 specbind (Qoverriding_local_map
, Qnil
);
1327 /* Run the Lucid hook. */
1328 call1 (Vrun_hooks
, Qactivate_menubar_hook
);
1329 /* If it has changed current-menubar from previous value,
1330 really recompute the menubar from the value. */
1331 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1332 call0 (Qrecompute_lucid_menubar
);
1333 call1 (Vrun_hooks
, Qmenu_bar_update_hook
);
1334 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1335 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1337 set_frame_menubar (f
, 0, 0);
1338 #endif /* USE_X_TOOLKIT || HAVE_NTGUI */
1340 unbind_to (count
, Qnil
);
1341 set_buffer_internal_1 (prev
);
1348 /* Redisplay WINDOW and its subwindows and siblings. */
1351 redisplay_windows (window
)
1354 for (; !NILP (window
); window
= XWINDOW (window
)->next
)
1355 redisplay_window (window
, 0);
1358 /* Redisplay window WINDOW and its subwindows. */
1361 redisplay_window (window
, just_this_one
)
1365 register struct window
*w
= XWINDOW (window
);
1366 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1368 register int lpoint
= PT
;
1369 struct buffer
*old
= current_buffer
;
1370 register int width
= window_internal_width (w
) - 1;
1371 register int startp
;
1372 register int hscroll
= XINT (w
->hscroll
);
1373 struct position pos
;
1376 int update_mode_line
;
1377 struct Lisp_Char_Table
*dp
= window_display_table (w
);
1379 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1381 /* If this is a combination window, do its children; that's all. */
1383 if (!NILP (w
->vchild
))
1385 redisplay_windows (w
->vchild
);
1388 if (!NILP (w
->hchild
))
1390 redisplay_windows (w
->hchild
);
1393 if (NILP (w
->buffer
))
1396 height
= window_internal_height (w
);
1397 update_mode_line
= (!NILP (w
->update_mode_line
) || update_mode_lines
);
1398 if (XBUFFER (w
->buffer
)->clip_changed
)
1399 update_mode_line
= 1;
1401 if (MINI_WINDOW_P (w
))
1403 if (w
== XWINDOW (echo_area_window
) && echo_area_glyphs
)
1404 /* We've already displayed the echo area glyphs in this window. */
1405 goto finish_scroll_bars
;
1406 else if (w
!= XWINDOW (minibuf_window
))
1408 /* This is a minibuffer, but it's not the currently active one,
1410 int vpos
= XFASTINT (w
->top
);
1413 for (i
= 0; i
< height
; i
++)
1415 get_display_line (f
, vpos
+ i
, 0);
1416 display_string (w
, vpos
+ i
, "", 0, 0, 0, 1, 0, width
);
1419 goto finish_scroll_bars
;
1423 /* Otherwise set up data on this window; select its buffer and point value */
1425 if (update_mode_line
)
1426 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1428 set_buffer_temp (XBUFFER (w
->buffer
));
1432 /* If %c is in mode line, update it if needed. */
1433 if (!NILP (w
->column_number_displayed
)
1434 /* This alternative quickly identifies a common case
1435 where no change is needed. */
1436 && !(PT
== XFASTINT (w
->last_point
)
1437 && XFASTINT (w
->last_modified
) >= MODIFF
)
1438 && XFASTINT (w
->column_number_displayed
) != current_column ())
1439 update_mode_line
= 1;
1441 /* Count number of windows showing the selected buffer.
1442 An indirect buffer counts as its base buffer. */
1446 struct buffer
*current_base
, *window_base
;
1447 current_base
= current_buffer
;
1448 window_base
= XBUFFER (XWINDOW (selected_window
)->buffer
);
1449 if (current_base
->base_buffer
)
1450 current_base
= current_base
->base_buffer
;
1451 if (window_base
->base_buffer
)
1452 window_base
= window_base
->base_buffer
;
1453 if (current_base
== window_base
)
1457 /* POINT refers normally to the selected window.
1458 For any other window, set up appropriate value. */
1460 if (!EQ (window
, selected_window
))
1462 int new_pt
= marker_position (w
->pointm
);
1466 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1468 else if (new_pt
> (ZV
- 1))
1471 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1473 /* We don't use SET_PT so that the point-motion hooks don't run. */
1474 BUF_PT (current_buffer
) = new_pt
;
1477 /* If any of the character widths specified in the display table
1478 have changed, invalidate the width run cache. It's true that this
1479 may be a bit late to catch such changes, but the rest of
1480 redisplay goes (non-fatally) haywire when the display table is
1481 changed, so why should we worry about doing any better? */
1482 if (current_buffer
->width_run_cache
)
1484 struct Lisp_Char_Table
*disptab
= buffer_display_table ();
1486 if (! disptab_matches_widthtab (disptab
,
1487 XVECTOR (current_buffer
->width_table
)))
1489 invalidate_region_cache (current_buffer
,
1490 current_buffer
->width_run_cache
,
1492 recompute_width_table (current_buffer
, disptab
);
1496 /* If window-start is screwed up, choose a new one. */
1497 if (XMARKER (w
->start
)->buffer
!= current_buffer
)
1500 startp
= marker_position (w
->start
);
1502 /* Handle case where place to start displaying has been specified,
1503 unless the specified location is outside the accessible range. */
1504 if (!NILP (w
->force_start
))
1506 w
->force_start
= Qnil
;
1507 /* Forget any recorded base line for line number display. */
1508 w
->base_line_number
= Qnil
;
1509 /* Redisplay the mode line. Select the buffer properly for that.
1510 Also, run the hook window-scroll-functions
1511 because we have scrolled. */
1512 /* Note, we do this after clearing force_start because
1513 if there's an error, it is better to forget about force_start
1514 than to get into an infinite loop calling the hook functions
1515 and having them get more errors. */
1516 if (!update_mode_line
1517 || ! NILP (Vwindow_scroll_functions
))
1519 Lisp_Object temp
[3];
1521 set_buffer_temp (old
);
1522 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1523 update_mode_line
= 1;
1524 w
->update_mode_line
= Qt
;
1525 if (! NILP (Vwindow_scroll_functions
))
1526 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1527 make_number (startp
));
1529 XSETFASTINT (w
->last_modified
, 0);
1530 if (startp
< BEGV
) startp
= BEGV
;
1531 if (startp
> ZV
) startp
= ZV
;
1532 try_window (window
, startp
);
1533 if (cursor_vpos
< 0)
1535 /* If point does not appear, move point so it does appear */
1536 pos
= *compute_motion (startp
, 0,
1537 (((EQ (window
, minibuf_window
)
1539 ? minibuf_prompt_width
: 0)
1540 + (hscroll
? 1 - hscroll
: 0)),
1543 - (1 << (BITS_PER_SHORT
- 1)),
1544 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1545 BUF_PT (current_buffer
) = pos
.bufpos
;
1546 if (w
!= XWINDOW (selected_window
))
1547 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
1550 if (current_buffer
== old
)
1552 FRAME_CURSOR_X (f
) = (XFASTINT (w
->left
)
1553 + minmax (0, pos
.hpos
, width
));
1554 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1556 /* If we are highlighting the region,
1557 then we just changed the region, so redisplay to show it. */
1558 if (!NILP (Vtransient_mark_mode
)
1559 && !NILP (current_buffer
->mark_active
))
1561 cancel_my_columns (XWINDOW (window
));
1562 try_window (window
, startp
);
1568 /* Handle case where text has not changed, only point,
1569 and it has not moved off the frame. */
1571 /* This code is not used for minibuffer for the sake of
1572 the case of redisplaying to replace an echo area message;
1573 since in that case the minibuffer contents per se are usually unchanged.
1574 This code is of no real use in the minibuffer since
1575 the handling of this_line_bufpos, etc.,
1576 in redisplay handles the same cases. */
1578 if (XFASTINT (w
->last_modified
) >= MODIFF
1579 && PT
>= startp
&& !current_buffer
->clip_changed
1580 && (just_this_one
|| XFASTINT (w
->width
) == FRAME_WIDTH (f
))
1581 /* If force-mode-line-update was called, really redisplay;
1582 that's how redisplay is forced after e.g. changing
1583 buffer-invisibility-spec. */
1584 && NILP (w
->update_mode_line
)
1585 /* Can't use this case if highlighting a region. */
1586 && !(!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1587 && NILP (w
->region_showing
)
1588 /* If end pos is out of date, scroll bar and percentage will be wrong */
1589 && INTEGERP (w
->window_end_vpos
)
1590 && XFASTINT (w
->window_end_vpos
) < XFASTINT (w
->height
)
1591 && !EQ (window
, minibuf_window
))
1593 pos
= *compute_motion (startp
, 0, (hscroll
? 1 - hscroll
: 0), 0,
1594 PT
, height
, 0, width
, hscroll
,
1595 pos_tab_offset (w
, startp
), w
);
1597 if (pos
.vpos
< height
)
1599 /* Ok, point is still on frame */
1600 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
1602 /* These variables are supposed to be origin 1 */
1603 FRAME_CURSOR_X (f
) = (XFASTINT (w
->left
)
1604 + minmax (0, pos
.hpos
, width
));
1605 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1607 /* This doesn't do the trick, because if a window to the right of
1608 this one must be redisplayed, this does nothing because there
1609 is nothing in DesiredFrame yet, and then the other window is
1610 redisplayed, making likes that are empty in this window's columns.
1611 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1612 preserve_my_columns (w);
1616 /* Don't bother trying redisplay with same start;
1617 we already know it will lose */
1619 /* If current starting point was originally the beginning of a line
1620 but no longer is, find a new starting point. */
1621 else if (!NILP (w
->start_at_line_beg
)
1623 || FETCH_CHAR (startp
- 1) == '\n'))
1627 else if (just_this_one
&& !MINI_WINDOW_P (w
)
1629 && XFASTINT (w
->last_modified
)
1630 /* or else vmotion on first line won't work. */
1631 && ! NILP (w
->start_at_line_beg
)
1632 && ! EQ (w
->window_end_valid
, Qnil
)
1633 && do_id
&& !current_buffer
->clip_changed
1634 && !blank_end_of_window
1635 && XFASTINT (w
->width
) == FRAME_WIDTH (f
)
1636 /* Can't use this case if highlighting a region. */
1637 && !(!NILP (Vtransient_mark_mode
)
1638 && !NILP (current_buffer
->mark_active
))
1639 /* Don't use try_window_id if newline
1640 doesn't display as the end of a line. */
1641 && !(dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, '\n')))
1642 && NILP (w
->region_showing
)
1643 && EQ (last_arrow_position
, Voverlay_arrow_position
)
1644 && EQ (last_arrow_string
, Voverlay_arrow_string
)
1645 && (tem
= try_window_id (FRAME_SELECTED_WINDOW (f
)))
1648 /* tem > 0 means success. tem == -1 means choose new start.
1649 tem == -2 means try again with same start,
1650 and nothing but whitespace follows the changed stuff.
1651 tem == 0 means try again with same start. */
1655 else if (startp
>= BEGV
&& startp
<= ZV
1656 /* Avoid starting display at end of buffer! */
1657 && (startp
< ZV
|| startp
== BEGV
1658 || (XFASTINT (w
->last_modified
) >= MODIFF
)))
1660 /* Try to redisplay starting at same place as before */
1661 /* If point has not moved off frame, accept the results */
1662 try_window (window
, startp
);
1663 if (cursor_vpos
>= 0)
1665 if (!just_this_one
|| current_buffer
->clip_changed
1666 || beg_unchanged
< startp
)
1667 /* Forget any recorded base line for line number display. */
1668 w
->base_line_number
= Qnil
;
1672 cancel_my_columns (w
);
1675 XSETFASTINT (w
->last_modified
, 0);
1676 /* Redisplay the mode line. Select the buffer properly for that. */
1677 if (!update_mode_line
)
1679 set_buffer_temp (old
);
1680 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1681 update_mode_line
= 1;
1682 w
->update_mode_line
= Qt
;
1685 /* Try to scroll by specified few lines */
1687 if (scroll_step
&& !current_buffer
->clip_changed
1688 && startp
>= BEGV
&& startp
<= ZV
)
1692 pos
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), scroll_step
, w
);
1693 if (pos
.vpos
>= height
)
1697 pos
= *vmotion (startp
, (PT
< startp
? - scroll_step
: scroll_step
), w
);
1699 if (PT
>= pos
.bufpos
)
1701 if (! NILP (Vwindow_scroll_functions
))
1702 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1703 make_number (pos
.bufpos
));
1704 try_window (window
, pos
.bufpos
);
1705 if (cursor_vpos
>= 0)
1707 if (!just_this_one
|| current_buffer
->clip_changed
1708 || beg_unchanged
< startp
)
1709 /* Forget any recorded base line for line number display. */
1710 w
->base_line_number
= Qnil
;
1714 cancel_my_columns (w
);
1719 /* Finally, just choose place to start which centers point */
1722 /* Forget any previously recorded base line for line number display. */
1723 w
->base_line_number
= Qnil
;
1725 pos
= *vmotion (PT
, - (height
/ 2), w
);
1726 /* Set startp here explicitly in case that helps avoid an infinite loop
1727 in case the window-scroll-functions functions get errors. */
1728 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
1729 if (! NILP (Vwindow_scroll_functions
))
1730 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1731 make_number (pos
.bufpos
));
1732 try_window (window
, pos
.bufpos
);
1734 startp
= marker_position (w
->start
);
1735 w
->start_at_line_beg
1736 = (startp
== BEGV
|| FETCH_CHAR (startp
- 1) == '\n') ? Qt
: Qnil
;
1739 if ((update_mode_line
1740 /* If window not full width, must redo its mode line
1741 if the window to its side is being redone */
1742 || (!just_this_one
&& width
< FRAME_WIDTH (f
) - 1)
1743 || INTEGERP (w
->base_line_pos
)
1744 || (!NILP (w
->column_number_displayed
)
1745 && XFASTINT (w
->column_number_displayed
) != current_column ()))
1746 && height
!= XFASTINT (w
->height
))
1747 display_mode_line (w
);
1748 if (! line_number_displayed
1749 && ! BUFFERP (w
->base_line_pos
))
1751 w
->base_line_pos
= Qnil
;
1752 w
->base_line_number
= Qnil
;
1755 /* When we reach a frame's selected window, redo the frame's menu bar. */
1756 if (update_mode_line
1759 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1760 FRAME_EXTERNAL_MENU_BAR (f
)
1762 FRAME_MENU_BAR_LINES (f
) > 0
1764 : FRAME_MENU_BAR_LINES (f
) > 0)
1765 && EQ (FRAME_SELECTED_WINDOW (f
), window
))
1766 display_menu_bar (w
);
1769 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1771 int start
, end
, whole
;
1773 /* Calculate the start and end positions for the current window.
1774 At some point, it would be nice to choose between scrollbars
1775 which reflect the whole buffer size, with special markers
1776 indicating narrowing, and scrollbars which reflect only the
1779 Note that minibuffers sometimes aren't displaying any text. */
1780 if (! MINI_WINDOW_P (w
)
1781 || (w
== XWINDOW (minibuf_window
) && ! echo_area_glyphs
))
1784 start
= marker_position (w
->start
) - BEGV
;
1785 /* I don't think this is guaranteed to be right. For the
1786 moment, we'll pretend it is. */
1787 end
= (Z
- XINT (w
->window_end_pos
)) - BEGV
;
1789 if (end
< start
) end
= start
;
1790 if (whole
< (end
- start
)) whole
= end
- start
;
1793 start
= end
= whole
= 0;
1795 /* Indicate what this scroll bar ought to be displaying now. */
1796 (*set_vertical_scroll_bar_hook
) (w
, end
- start
, whole
, start
);
1798 /* Note that we actually used the scroll bar attached to this window,
1799 so it shouldn't be deleted at the end of redisplay. */
1800 (*redeem_scroll_bar_hook
) (w
);
1803 BUF_PT (current_buffer
) = opoint
;
1804 if (update_mode_line
)
1805 set_buffer_internal_1 (old
);
1807 set_buffer_temp (old
);
1808 BUF_PT (current_buffer
) = lpoint
;
1811 /* Do full redisplay on one window, starting at position `pos'. */
1814 try_window (window
, pos
)
1818 register struct window
*w
= XWINDOW (window
);
1819 register int height
= window_internal_height (w
);
1820 register int vpos
= XFASTINT (w
->top
);
1821 register int last_text_vpos
= vpos
;
1822 int tab_offset
= pos_tab_offset (w
, pos
);
1823 FRAME_PTR f
= XFRAME (w
->frame
);
1824 int width
= window_internal_width (w
) - 1;
1825 struct position val
;
1827 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1829 overlay_arrow_seen
= 0;
1830 zv_strings_seen
= 0;
1831 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
1833 while (--height
>= 0)
1835 val
= *display_text_line (w
, pos
, vpos
, val
.hpos
, tab_offset
);
1836 tab_offset
+= width
;
1837 /* For the first line displayed, display_text_line
1838 subtracts the prompt width from the tab offset.
1839 But it does not affect the value of our variable tab_offset.
1840 So we do the subtraction again,
1841 for the sake of continuation lines of that first line. */
1842 if (MINI_WINDOW_P (w
) && vpos
== XFASTINT (w
->top
))
1843 tab_offset
-= minibuf_prompt_width
;
1845 if (val
.vpos
) tab_offset
= 0;
1847 if (pos
!= val
.bufpos
)
1850 #ifdef USE_TEXT_PROPERTIES
1851 Lisp_Object invis_prop
;
1852 invis_prop
= Fget_char_property (val
.bufpos
-1, Qinvisible
, window
);
1853 invis
= TEXT_PROP_MEANS_INVISIBLE (invis_prop
);
1857 /* Next line, unless prev line ended in end of buffer with no cr */
1859 && (FETCH_CHAR (val
.bufpos
- 1) != '\n' || invis
));
1864 /* If last line is continued in middle of character,
1865 include the split character in the text considered on the frame */
1866 if (val
.hpos
< (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
1869 /* If bottom just moved off end of frame, change mode line percentage. */
1870 if (XFASTINT (w
->window_end_pos
) == 0
1872 w
->update_mode_line
= Qt
;
1874 /* Say where last char on frame will be, once redisplay is finished. */
1875 XSETFASTINT (w
->window_end_pos
, Z
- pos
);
1876 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
- XFASTINT (w
->top
));
1877 /* But that is not valid info until redisplay finishes. */
1878 w
->window_end_valid
= Qnil
;
1881 /* Try to redisplay when buffer is modified locally,
1882 computing insert/delete line to preserve text outside
1883 the bounds of the changes.
1884 Return 1 if successful, 0 if if cannot tell what to do,
1885 or -1 to tell caller to find a new window start,
1886 or -2 to tell caller to do normal redisplay with same window start. */
1889 try_window_id (window
)
1893 register struct window
*w
= XWINDOW (window
);
1894 register int height
= window_internal_height (w
);
1895 FRAME_PTR f
= XFRAME (w
->frame
);
1896 int top
= XFASTINT (w
->top
);
1897 int start
= marker_position (w
->start
);
1898 int width
= window_internal_width (w
) - 1;
1899 int hscroll
= XINT (w
->hscroll
);
1900 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1903 register int i
, tem
;
1904 int last_text_vpos
= 0;
1906 int selective
= (INTEGERP (current_buffer
->selective_display
)
1907 ? XINT (current_buffer
->selective_display
)
1908 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1910 struct position val
, bp
, ep
, xp
, pp
;
1911 int scroll_amount
= 0;
1913 int tab_offset
, epto
, old_tick
;
1915 if (GPT
- BEG
< beg_unchanged
)
1916 beg_unchanged
= GPT
- BEG
;
1917 if (Z
- GPT
< end_unchanged
)
1918 end_unchanged
= Z
- GPT
;
1920 if (beg_unchanged
+ BEG
< start
)
1921 return 0; /* Give up if changes go above top of window */
1923 /* Find position before which nothing is changed. */
1924 bp
= *compute_motion (start
, 0, lmargin
, 0,
1925 min (ZV
, beg_unchanged
+ BEG
), height
, 0,
1926 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1927 if (bp
.vpos
>= height
)
1931 /* All changes are beyond the window end, and point is on the screen.
1932 We don't need to change the text at all.
1933 But we need to update window_end_pos to account for
1934 any change in buffer size. */
1935 bp
= *compute_motion (start
, 0, lmargin
, 0,
1937 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1938 XSETFASTINT (w
->window_end_vpos
, height
);
1939 XSETFASTINT (w
->window_end_pos
, Z
- bp
.bufpos
);
1947 /* Find beginning of that frame line. Must display from there. */
1948 bp
= *vmotion (bp
.bufpos
, 0, w
);
1956 /* If about to start displaying at the beginning of a continuation line,
1957 really start with previous frame line, in case it was not
1958 continued when last redisplayed */
1959 if ((bp
.contin
&& bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0)
1961 /* Likewise if we have to worry about selective display. */
1962 (selective
> 0 && bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0))
1964 bp
= *vmotion (bp
.bufpos
, -1, w
);
1969 if (bp
.contin
&& bp
.hpos
!= lmargin
)
1971 val
.hpos
= bp
.prevhpos
- width
+ lmargin
;
1978 /* Find first visible newline after which no more is changed. */
1979 tem
= find_next_newline (Z
- max (end_unchanged
, Z
- ZV
), 1);
1981 while (tem
< ZV
- 1 && (indented_beyond_p (tem
, selective
)))
1982 tem
= find_next_newline (tem
, 1);
1984 /* Compute the cursor position after that newline. */
1985 ep
= *compute_motion (pos
, vpos
, val
.hpos
, did_motion
, tem
,
1986 height
, - (1 << (BITS_PER_SHORT
- 1)),
1987 width
, hscroll
, pos_tab_offset (w
, bp
.bufpos
), w
);
1989 /* If changes reach past the text available on the frame,
1990 just display rest of frame. */
1991 if (ep
.bufpos
> Z
- XFASTINT (w
->window_end_pos
))
1994 stop_vpos
= ep
.vpos
;
1996 /* If no newline before ep, the line ep is on includes some changes
1997 that must be displayed. Make sure we don't stop before it. */
1998 /* Also, if changes reach all the way until ep.bufpos,
1999 it is possible that something was deleted after the
2000 newline before it, so the following line must be redrawn. */
2001 if (stop_vpos
== ep
.vpos
2002 && (ep
.bufpos
== BEGV
2003 || FETCH_CHAR (ep
.bufpos
- 1) != '\n'
2004 || ep
.bufpos
== Z
- end_unchanged
))
2005 stop_vpos
= ep
.vpos
+ 1;
2008 overlay_arrow_seen
= 0;
2009 zv_strings_seen
= 0;
2011 /* If changes do not reach to bottom of window,
2012 figure out how much to scroll the rest of the window */
2013 if (stop_vpos
< height
)
2015 /* Now determine how far up or down the rest of the window has moved */
2016 epto
= pos_tab_offset (w
, ep
.bufpos
);
2017 xp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
2018 Z
- XFASTINT (w
->window_end_pos
),
2019 10000, 0, width
, hscroll
, epto
, w
);
2020 scroll_amount
= xp
.vpos
- XFASTINT (w
->window_end_vpos
);
2022 /* Is everything on frame below the changes whitespace?
2023 If so, no scrolling is really necessary. */
2024 for (i
= ep
.bufpos
; i
< xp
.bufpos
; i
++)
2026 tem
= FETCH_CHAR (i
);
2027 if (tem
!= ' ' && tem
!= '\n' && tem
!= '\t')
2033 XSETFASTINT (w
->window_end_vpos
,
2034 XFASTINT (w
->window_end_vpos
) + scroll_amount
);
2036 /* Before doing any scrolling, verify that point will be on frame. */
2037 if (PT
> ep
.bufpos
&& !(PT
<= xp
.bufpos
&& xp
.bufpos
< height
))
2039 if (PT
<= xp
.bufpos
)
2041 pp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
2042 PT
, height
, - (1 << (BITS_PER_SHORT
- 1)),
2043 width
, hscroll
, epto
, w
);
2047 pp
= *compute_motion (xp
.bufpos
, xp
.vpos
, xp
.hpos
, 1,
2048 PT
, height
, - (1 << (BITS_PER_SHORT
- 1)),
2050 pos_tab_offset (w
, xp
.bufpos
), w
);
2052 if (pp
.bufpos
< PT
|| pp
.vpos
== height
)
2054 cursor_vpos
= pp
.vpos
+ top
;
2055 cursor_hpos
= XFASTINT (w
->left
) + minmax (0, pp
.hpos
, width
);
2058 if (stop_vpos
- scroll_amount
>= height
2059 || ep
.bufpos
== xp
.bufpos
)
2061 if (scroll_amount
< 0)
2062 stop_vpos
-= scroll_amount
;
2064 /* In this path, we have altered window_end_vpos
2065 and not left it negative.
2066 We must make sure that, in case display is preempted
2067 before the frame changes to reflect what we do here,
2068 further updates will not come to try_window_id
2069 and assume the frame and window_end_vpos match. */
2070 blank_end_of_window
= 1;
2072 else if (!scroll_amount
)
2074 /* Even if we don't need to scroll, we must adjust the
2075 charstarts of subsequent lines (that we won't redisplay)
2076 according to the amount of text inserted or deleted. */
2077 int oldpos
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2078 int adjust
= ep
.bufpos
- oldpos
;
2079 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1, adjust
);
2081 else if (bp
.bufpos
== Z
- end_unchanged
)
2083 /* If reprinting everything is nearly as fast as scrolling,
2084 don't bother scrolling. Can happen if lines are short. */
2085 if (scroll_cost (f
, bp
.vpos
+ top
- scroll_amount
,
2086 top
+ height
- max (0, scroll_amount
),
2088 > xp
.bufpos
- bp
.bufpos
- 20)
2089 /* Return "try normal display with same window-start."
2090 Too bad we can't prevent further scroll-thinking. */
2092 /* If pure deletion, scroll up as many lines as possible.
2093 In common case of killing a line, this can save the
2094 following line from being overwritten by scrolling
2095 and therefore having to be redrawn. */
2096 tem
= scroll_frame_lines (f
, bp
.vpos
+ top
- scroll_amount
,
2097 top
+ height
- max (0, scroll_amount
),
2098 scroll_amount
, bp
.bufpos
);
2103 /* scroll_frame_lines did not properly adjust subsequent
2104 lines' charstarts in the case where the text of the
2105 screen line at bp.vpos has changed.
2106 (This can happen in a deletion that ends in mid-line.)
2107 To adjust properly, we need to make things consistent
2109 So do a second adjust to make that happen.
2110 Note that stop_vpos >= ep.vpos, so it is sufficient
2111 to update the charstarts for lines at ep.vpos and below. */
2113 = FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2114 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1,
2115 ep
.bufpos
- oldstart
);
2118 else if (scroll_amount
)
2120 /* If reprinting everything is nearly as fast as scrolling,
2121 don't bother scrolling. Can happen if lines are short. */
2122 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2123 overestimate of cost of reprinting, since xp.bufpos
2124 would end up below the bottom of the window. */
2125 if (scroll_cost (f
, ep
.vpos
+ top
- scroll_amount
,
2126 top
+ height
- max (0, scroll_amount
),
2128 > xp
.bufpos
- ep
.bufpos
- 20)
2129 /* Return "try normal display with same window-start."
2130 Too bad we can't prevent further scroll-thinking. */
2132 tem
= scroll_frame_lines (f
, ep
.vpos
+ top
- scroll_amount
,
2133 top
+ height
- max (0, scroll_amount
),
2134 scroll_amount
, ep
.bufpos
);
2135 if (!tem
) stop_vpos
= height
;
2139 /* In any case, do not display past bottom of window */
2140 if (stop_vpos
>= height
)
2146 /* Handle case where pos is before w->start --
2147 can happen if part of line had been clipped and is not clipped now */
2148 if (vpos
== 0 && pos
< marker_position (w
->start
))
2149 Fset_marker (w
->start
, make_number (pos
), Qnil
);
2151 /* Redisplay the lines where the text was changed */
2152 last_text_vpos
= vpos
;
2153 tab_offset
= pos_tab_offset (w
, pos
);
2154 /* If we are starting display in mid-character, correct tab_offset
2155 to account for passing the line that that character really starts in. */
2156 if (val
.hpos
< lmargin
)
2157 tab_offset
+= width
;
2159 while (vpos
< stop_vpos
)
2161 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
2162 /* If display_text_line ran a hook and changed some text,
2163 redisplay all the way to bottom of buffer
2164 So that we show the changes. */
2165 if (old_tick
!= MODIFF
)
2167 tab_offset
+= width
;
2168 if (val
.vpos
) tab_offset
= 0;
2169 if (pos
!= val
.bufpos
)
2171 /* Next line, unless prev line ended in end of buffer with no cr */
2172 = vpos
- (val
.vpos
&& FETCH_CHAR (val
.bufpos
- 1) != '\n');
2176 /* There are two cases:
2177 1) we have displayed down to the bottom of the window
2178 2) we have scrolled lines below stop_vpos by scroll_amount */
2182 /* If last line is continued in middle of character,
2183 include the split character in the text considered on the frame */
2184 if (val
.hpos
< lmargin
)
2186 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
);
2187 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2190 /* If scrolling made blank lines at window bottom,
2191 redisplay to fill those lines */
2192 if (scroll_amount
< 0)
2194 /* Don't consider these lines for general-purpose scrolling.
2195 That will save time in the scrolling computation. */
2196 FRAME_SCROLL_BOTTOM_VPOS (f
) = xp
.vpos
;
2201 vpos
= height
+ scroll_amount
;
2202 else if (xp
.contin
&& xp
.hpos
!= lmargin
)
2204 val
.hpos
= xp
.prevhpos
- width
+ lmargin
;
2208 blank_end_of_window
= 1;
2209 tab_offset
= pos_tab_offset (w
, pos
);
2210 /* If we are starting display in mid-character, correct tab_offset
2211 to account for passing the line that that character starts in. */
2212 if (val
.hpos
< lmargin
)
2213 tab_offset
+= width
;
2215 while (vpos
< height
)
2217 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
2218 tab_offset
+= width
;
2219 if (val
.vpos
) tab_offset
= 0;
2223 /* Here is a case where display_text_line sets cursor_vpos wrong.
2224 Make it be fixed up, below. */
2230 /* If bottom just moved off end of frame, change mode line percentage. */
2231 if (XFASTINT (w
->window_end_pos
) == 0
2233 w
->update_mode_line
= Qt
;
2235 /* Attempt to adjust end-of-text positions to new bottom line */
2238 delta
= height
- xp
.vpos
;
2240 || (delta
> 0 && xp
.bufpos
<= ZV
)
2241 || (delta
== 0 && xp
.hpos
))
2243 val
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), delta
, w
);
2244 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2245 XSETFASTINT (w
->window_end_vpos
,
2246 XFASTINT (w
->window_end_vpos
) + val
.vpos
);
2250 w
->window_end_valid
= Qnil
;
2252 /* If point was not in a line that was displayed, find it */
2253 if (cursor_vpos
< 0)
2256 val
= *compute_motion (start
, 0, lmargin
, 0, PT
, 10000, 10000,
2257 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2258 /* Admit failure if point is off frame now */
2259 if (val
.vpos
>= height
)
2261 for (vpos
= 0; vpos
< height
; vpos
++)
2262 cancel_line (vpos
+ top
, f
);
2265 cursor_vpos
= val
.vpos
+ top
;
2266 cursor_hpos
= XFASTINT (w
->left
) + minmax (0, val
.hpos
, width
);
2269 FRAME_CURSOR_X (f
) = cursor_hpos
;
2270 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2274 val
= *compute_motion (start
, 0, lmargin
, 0, ZV
,
2275 height
, - (1 << (BITS_PER_SHORT
- 1)),
2276 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2277 if (val
.vpos
!= XFASTINT (w
->window_end_vpos
))
2279 if (XFASTINT (w
->window_end_pos
)
2287 /* Mark a section of BUF as modified, but only for the sake of redisplay.
2288 This is useful for recording changes to overlays.
2290 We increment the buffer's modification timestamp and set the
2291 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
2292 as if the region of text between START and END had been modified;
2293 the redisplay code will check this against the windows' timestamps,
2294 and redraw the appropriate area of the buffer.
2296 However, if the buffer is unmodified, we bump the last-save
2297 timestamp as well, so that incrementing the timestamp doesn't fool
2298 Emacs into thinking that the buffer's text has been modified.
2300 Tweaking the timestamps shouldn't hurt the first-modification
2301 timestamps recorded in the undo records; those values aren't
2302 written until just before a real text modification is made, so they
2303 will never catch the timestamp value just before this function gets
2307 redisplay_region (buf
, start
, end
)
2317 start
= end
; end
= temp
;
2320 /* If this is a buffer not in the selected window,
2321 we must do other windows. */
2322 if (buf
!= XBUFFER (XWINDOW (selected_window
)->buffer
))
2323 windows_or_buffers_changed
= 1;
2324 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
2325 else if (buf
!= current_buffer
)
2326 windows_or_buffers_changed
= 1;
2327 /* If multiple windows show this buffer, we must do other windows. */
2328 else if (buffer_shared
> 1)
2329 windows_or_buffers_changed
= 1;
2332 if (unchanged_modified
== MODIFF
)
2334 beg_unchanged
= start
- BEG
;
2335 end_unchanged
= Z
- end
;
2339 if (Z
- end
< end_unchanged
)
2340 end_unchanged
= Z
- end
;
2341 if (start
- BEG
< beg_unchanged
)
2342 beg_unchanged
= start
- BEG
;
2346 /* Increment the buffer's time stamp, but also increment the save
2347 and autosave timestamps, so as not to screw up that timekeeping. */
2348 if (BUF_MODIFF (buf
) == BUF_SAVE_MODIFF (buf
))
2349 BUF_SAVE_MODIFF (buf
)++;
2350 if (BUF_MODIFF (buf
) == buf
->auto_save_modified
)
2351 buf
->auto_save_modified
++;
2353 BUF_MODIFF (buf
) ++;
2357 /* Copy LEN glyphs starting address FROM to the rope TO.
2358 But don't actually copy the parts that would come in before S.
2359 Value is TO, advanced past the copied data.
2360 F is the frame we are displaying in. */
2363 copy_part_of_rope (f
, to
, s
, from
, len
, face
)
2365 register GLYPH
*to
; /* Copy to here. */
2366 register GLYPH
*s
; /* Starting point. */
2367 Lisp_Object
*from
; /* Data to copy. */
2369 int face
; /* Face to apply to glyphs which don't specify one. */
2372 register Lisp_Object
*fp
= from
;
2373 /* These cache the results of the last call to compute_glyph_face. */
2375 int last_merged
= 0;
2378 if (! FRAME_TERMCAP_P (f
))
2381 int glyph
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2384 if (FAST_GLYPH_FACE (glyph
) == 0)
2385 /* If GLYPH has no face code, use FACE. */
2387 else if (FAST_GLYPH_FACE (glyph
) == last_code
)
2388 /* If it's same as previous glyph, use same result. */
2389 facecode
= last_merged
;
2392 /* Merge this glyph's face and remember the result. */
2393 last_code
= FAST_GLYPH_FACE (glyph
);
2394 last_merged
= facecode
= compute_glyph_face (f
, last_code
, face
);
2398 *to
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), facecode
);
2406 if (to
>= s
) *to
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2413 /* Correct a glyph by replacing its specified user-level face code
2414 with a displayable computed face code. */
2417 fix_glyph (f
, glyph
, cface
)
2423 if (! FRAME_TERMCAP_P (f
))
2425 if (FAST_GLYPH_FACE (glyph
) != 0)
2426 cface
= compute_glyph_face (f
, FAST_GLYPH_FACE (glyph
), cface
);
2427 glyph
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), cface
);
2433 /* Display one line of window W, starting at position START in W's buffer.
2435 Display starting at horizontal position HPOS, expressed relative to
2436 W's left edge. In situations where the text at START shouldn't
2437 start at the left margin (i.e. when the window is hscrolled, or
2438 we're continuing a line which left off in the midst of a
2439 multi-column character), HPOS should be negative; we throw away
2440 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2443 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2445 Display on position VPOS on the frame. It is origin 0, relative to
2446 the top of the frame, not W.
2448 Returns a STRUCT POSITION giving character to start next line with
2449 and where to display it, including a zero or negative hpos.
2450 The vpos field is not really a vpos; it is 1 unless the line is continued */
2452 struct position val_display_text_line
;
2454 static struct position
*
2455 display_text_line (w
, start
, vpos
, hpos
, taboffset
)
2462 register int pos
= start
;
2466 register unsigned char *p
;
2468 register GLYPH
*leftmargin
;
2469 register GLYPH
*p1prev
;
2470 register GLYPH
*p1start
;
2473 FRAME_PTR f
= XFRAME (w
->frame
);
2474 int tab_width
= XINT (current_buffer
->tab_width
);
2475 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
2476 int width
= window_internal_width (w
) - 1;
2477 struct position val
;
2480 int last_invis_skip
= 0;
2481 Lisp_Object last_invis_prop
;
2482 int hscroll
= XINT (w
->hscroll
);
2483 int truncate
= (hscroll
2484 || (truncate_partial_width_windows
2485 && XFASTINT (w
->width
) < FRAME_WIDTH (f
))
2486 || !NILP (current_buffer
->truncate_lines
));
2488 /* 1 if we should highlight the region. */
2489 int highlight_region
2490 = !NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
);
2491 int region_beg
, region_end
;
2493 int selective
= (INTEGERP (current_buffer
->selective_display
)
2494 ? XINT (current_buffer
->selective_display
)
2495 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2496 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
2497 register struct Lisp_Char_Table
*dp
= window_display_table (w
);
2499 Lisp_Object default_invis_vector
[3];
2500 /* Number of characters of ellipsis to display after an invisible line
2501 if it calls for an ellipsis.
2502 Note that this value can be nonzero regardless of whether
2503 selective display is enabled--you must check that separately. */
2505 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2506 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
2507 : !NILP (current_buffer
->selective_display_ellipses
) ? 3 : 0);
2508 /* This is the sequence of Lisp objects to display
2509 when there are invisible lines. */
2510 Lisp_Object
*invis_vector_contents
2511 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2512 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->contents
2513 : default_invis_vector
);
2515 GLYPH truncator
= (dp
== 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp
))
2516 ? '$' : XINT (DISP_TRUNC_GLYPH (dp
)));
2517 GLYPH continuer
= (dp
== 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp
))
2518 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp
)));
2520 /* The next buffer location at which the face should change, due
2521 to overlays or text property changes. */
2522 int next_face_change
;
2524 /* The next location where the `invisible' property changes, or an
2525 overlay starts or ends. */
2528 /* The face we're currently using. */
2529 int current_face
= 0;
2532 XSETFASTINT (default_invis_vector
[2], '.');
2533 default_invis_vector
[0] = default_invis_vector
[1] = default_invis_vector
[2];
2535 hpos
+= XFASTINT (w
->left
);
2536 get_display_line (f
, vpos
, XFASTINT (w
->left
));
2537 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
2539 /* Show where to highlight the region. */
2540 if (highlight_region
&& XMARKER (current_buffer
->mark
)->buffer
!= 0
2541 /* Maybe highlight only in selected window. */
2542 && (highlight_nonselected_windows
2543 || w
== XWINDOW (selected_window
)))
2545 region_beg
= marker_position (current_buffer
->mark
);
2546 if (PT
< region_beg
)
2548 region_end
= region_beg
;
2553 w
->region_showing
= Qt
;
2556 region_beg
= region_end
= -1;
2558 if (MINI_WINDOW_P (w
)
2560 && vpos
== XFASTINT (w
->top
))
2562 if (! NILP (minibuf_prompt
))
2564 minibuf_prompt_width
2565 = (display_string (w
, vpos
, XSTRING (minibuf_prompt
)->data
,
2566 XSTRING (minibuf_prompt
)->size
, hpos
,
2567 /* Display a space if we truncate. */
2570 /* Truncate the prompt a little before the
2571 margin, so user input can at least start
2572 on the first line. */
2573 w
->width
> 10 ? w
->width
- 4 : -1)
2575 hpos
+= minibuf_prompt_width
;
2576 taboffset
-= minibuf_prompt_width
;
2579 minibuf_prompt_width
= 0;
2582 /* If we're hscrolled at all, use compute_motion to skip over any
2583 text off the left edge of the window. compute_motion may know
2584 tricks to do this faster than we can. */
2587 struct position
*left_edge
2588 = compute_motion (pos
, vpos
, hpos
, 0,
2590 width
, hscroll
, taboffset
, w
);
2592 /* Retrieve the buffer position and column provided by
2593 compute_motion. We can't assume that the column will be
2594 zero, because you may have multi-column characters crossing
2597 compute_motion may have moved us past the screen position we
2598 requested, if we hit a multi-column character, or the end of
2599 the line. If so, back up. */
2600 if (left_edge
->vpos
> vpos
2601 || left_edge
->hpos
> 0)
2603 pos
= left_edge
->bufpos
- 1;
2604 hpos
= left_edge
->prevhpos
;
2608 pos
= left_edge
->bufpos
;
2609 hpos
= left_edge
->hpos
;
2613 desired_glyphs
->bufp
[vpos
] = start
;
2614 p1
= desired_glyphs
->glyphs
[vpos
] + hpos
;
2616 charstart
= desired_glyphs
->charstarts
[vpos
] + hpos
;
2617 /* In case we don't ever write anything into it... */
2618 desired_glyphs
->charstarts
[vpos
][XFASTINT (w
->left
)] = -1;
2619 leftmargin
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
2620 endp
= leftmargin
+ width
;
2622 /* Arrange the overlays nicely for our purposes. Usually, we call
2623 display_text_line on only one line at a time, in which case this
2624 can't really hurt too much, or we call it on lines which appear
2625 one after another in the buffer, in which case all calls to
2626 recenter_overlay_lists but the first will be pretty cheap. */
2627 recenter_overlay_lists (current_buffer
, pos
);
2629 /* Loop generating characters.
2630 Stop at end of buffer, before newline,
2631 if reach or pass continuation column,
2632 or at face change. */
2634 next_face_change
= pos
;
2635 next_boundary
= pos
;
2644 while (pos
== next_boundary
)
2646 Lisp_Object position
, limit
, prop
, ww
;
2648 /* Display the overlay strings here, unless we're at ZV
2649 and have already displayed the appropriate strings
2650 on an earlier line. */
2651 if (pos
< ZV
|| !zv_strings_seen
++)
2655 ovlen
= overlay_strings (pos
, w
, &ovstr
);
2656 for (; ovlen
; ovlen
--, ovstr
++)
2658 if (p1
>= leftmargin
&& p1
< endp
)
2659 *p1
= MAKE_GLYPH (f
, *ovstr
, current_face
);
2664 /* Did we reach point? Record the cursor location. */
2665 if (pos
== PT
&& cursor_vpos
< 0)
2668 cursor_hpos
= p1
- leftmargin
;
2674 XSETFASTINT (position
, pos
);
2675 limit
= Fnext_overlay_change (position
);
2676 #ifdef USE_TEXT_PROPERTIES
2677 /* This is just an estimate to give reasonable
2678 performance; nothing should go wrong if it is too small. */
2679 if (XFASTINT (limit
) > pos
+ 50)
2680 XSETFASTINT (limit
, pos
+ 50);
2681 limit
= Fnext_single_property_change (position
, Qinvisible
,
2682 Fcurrent_buffer (), limit
);
2684 next_boundary
= XFASTINT (limit
);
2685 /* if the `invisible' property is set, we can skip to
2686 the next property change. */
2688 prop
= Fget_char_property (position
, Qinvisible
, ww
);
2689 if (TEXT_PROP_MEANS_INVISIBLE (prop
))
2691 if (pos
< PT
&& next_boundary
>= PT
)
2694 cursor_hpos
= p1
- leftmargin
;
2696 pos
= next_boundary
;
2697 last_invis_skip
= pos
;
2698 last_invis_prop
= prop
;
2702 /* Did we reach point? Record the cursor location. */
2703 if (pos
== PT
&& cursor_vpos
< 0)
2706 cursor_hpos
= p1
- leftmargin
;
2709 /* Did we hit the end of the visible region of the buffer?
2713 /* Update charstarts for the end of this line. */
2714 /* Do nothing if off the left edge or at the right edge. */
2715 if (p1
>= leftmargin
&& p1
+ 1 != endp
)
2717 int *p2x
= &charstart
[(p1
< leftmargin
2725 /* Figure out where (if at all) the
2726 redisplay_end_trigger-hook should run. */
2727 if (MARKERP (w
->redisplay_end_trigger
)
2728 && XMARKER (w
->redisplay_end_trigger
)->buffer
!= 0)
2729 e_t_h
= marker_position (w
->redisplay_end_trigger
);
2730 else if (INTEGERP (w
->redisplay_end_trigger
))
2731 e_t_h
= XINT (w
->redisplay_end_trigger
);
2735 /* If we've gone past the place to run a hook,
2737 if (pos
>= e_t_h
&& e_t_h
!= ZV
)
2739 Lisp_Object args
[3];
2741 args
[0] = Qredisplay_end_trigger_functions
;
2742 XSETWINDOW (args
[1], w
);
2743 XSETINT (args
[2], e_t_h
);
2745 /* Since we are *trying* to run these functions,
2746 don't try to run them again, even if they get an error. */
2747 w
->redisplay_end_trigger
= Qnil
;
2748 Frun_hook_with_args (3, args
);
2751 /* Notice if it changed the face of this character. */
2752 next_face_change
= pos
;
2756 /* Did we hit a face change? Figure out what face we should
2757 use now. We also hit this the first time through the
2758 loop, to see what face we should start with. */
2759 if (pos
>= next_face_change
&& (FRAME_WINDOW_P (f
)))
2760 current_face
= compute_char_face (f
, w
, pos
,
2761 region_beg
, region_end
,
2762 &next_face_change
, pos
+ 50, 0);
2765 /* Compute the next place we need to stop
2766 and do something special; set PAUSE. */
2770 if (pos
< next_boundary
&& next_boundary
< pause
)
2771 pause
= next_boundary
;
2772 if (pos
< next_face_change
&& next_face_change
< pause
)
2773 pause
= next_face_change
;
2778 /* Wouldn't you hate to read the next line to someone over
2780 if (pos
< PT
&& PT
< pause
)
2782 if (pos
< GPT
&& GPT
< pause
)
2785 p
= &FETCH_CHAR (pos
);
2794 /* Let a display table override all standard display methods. */
2795 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
2797 p1
= copy_part_of_rope (f
, p1
, leftmargin
,
2798 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
2799 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
2802 else if (c
>= 040 && c
< 0177)
2804 if (p1
>= leftmargin
)
2805 *p1
= MAKE_GLYPH (f
, c
, current_face
);
2811 if (last_invis_skip
== pos
2812 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop
))
2816 && indented_beyond_p (pos
+ 1, selective
))
2819 pos
= find_next_newline (pos
+ 1, 1);
2820 if (FETCH_CHAR (pos
- 1) == '\n')
2823 if (invis
&& selective_rlen
> 0 && p1
>= leftmargin
)
2825 p1
+= selective_rlen
;
2826 if (p1
- leftmargin
> width
)
2828 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2829 (p1
- p1prev
), current_face
);
2832 /* Draw the face of the newline character as extending all the
2833 way to the end of the frame line. */
2836 if (p1
< leftmargin
)
2839 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2843 /* Update charstarts for the newline that ended this line. */
2844 /* Do nothing here for a char that's entirely off the left edge
2845 or if it starts at the right edge. */
2846 if (p1
>= leftmargin
&& p1prev
!= endp
)
2848 /* Store the newline's position into charstarts
2849 for the column where the newline starts.
2850 Store -1 for the rest of the glyphs it occupies. */
2851 int *p2x
= &charstart
[(p1prev
< leftmargin
2852 ? leftmargin
: p1prev
)
2854 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2867 if (p1
>= leftmargin
&& p1
< endp
)
2868 *p1
= MAKE_GLYPH (f
, ' ', current_face
);
2871 while ((p1
- leftmargin
+ taboffset
+ hscroll
- (hscroll
> 0))
2874 else if (c
== Ctl ('M') && selective
== -1)
2876 pos
= find_next_newline (pos
, 1);
2877 if (FETCH_CHAR (pos
- 1) == '\n')
2879 if (selective_rlen
> 0)
2881 p1
+= selective_rlen
;
2882 if (p1
- leftmargin
> width
)
2884 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2885 (p1
- p1prev
), current_face
);
2888 /* Draw the face of the newline character as extending all the
2889 way to the end of the frame line. */
2892 if (p1
< leftmargin
)
2895 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2899 /* Update charstarts for the ^M that ended this line. */
2900 /* Do nothing here for a char that's entirely off the left edge
2901 or if it starts at the right edge. */
2902 if (p1
>= leftmargin
&& p1prev
!= endp
)
2904 /* Store the newline's position into charstarts
2905 for the column where the newline starts.
2906 Store -1 for the rest of the glyphs it occupies. */
2907 int *p2x
= &charstart
[(p1prev
< leftmargin
2908 ? leftmargin
: p1prev
)
2910 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2918 else if (c
< 0200 && ctl_arrow
)
2920 if (p1
>= leftmargin
)
2921 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
2922 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
2925 if (p1
>= leftmargin
&& p1
< endp
)
2926 *p1
= MAKE_GLYPH (f
, c
^ 0100, current_face
);
2931 if (p1
>= leftmargin
)
2932 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
2933 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
2936 if (p1
>= leftmargin
&& p1
< endp
)
2937 *p1
= MAKE_GLYPH (f
, (c
>> 6) + '0', current_face
);
2939 if (p1
>= leftmargin
&& p1
< endp
)
2940 *p1
= MAKE_GLYPH (f
, (7 & (c
>> 3)) + '0', current_face
);
2942 if (p1
>= leftmargin
&& p1
< endp
)
2943 *p1
= MAKE_GLYPH (f
, (7 & c
) + '0', current_face
);
2950 /* Update charstarts for the character just output. */
2952 /* Do nothing here for a char that's entirely off the left edge. */
2953 if (p1
>= leftmargin
)
2955 /* Store the char's position into charstarts
2956 for the first glyph occupied by this char.
2957 Store -1 for the rest of the glyphs it occupies. */
2960 int *p2x
= &charstart
[(p1prev
< leftmargin
2961 ? leftmargin
: p1prev
)
2963 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2973 val
.hpos
= - XINT (w
->hscroll
);
2981 /* Store 0 in this charstart line for the positions where
2982 there is no character. But do leave what was recorded
2983 for the character that ended the line. */
2984 /* Add 1 in the endtest to compensate for the fact that ENDP was
2985 made from WIDTH, which is 1 less than the window's actual
2987 i
= p1
- p1start
+ 1;
2988 if (p1
< leftmargin
)
2989 i
+= leftmargin
- p1
;
2990 for (; i
< endp
- p1start
+ 1; i
++)
2993 /* Handle continuation in middle of a character */
2994 /* by backing up over it */
2997 /* Don't back up if we never actually displayed any text.
2998 This occurs when the minibuffer prompt takes up the whole line. */
3001 /* Start the next line with that same character */
3003 /* but at negative hpos, to skip the columns output on this line. */
3004 val
.hpos
+= p1prev
- endp
;
3007 /* Keep in this line everything up to the continuation column. */
3011 /* Finish deciding which character to start the next line on,
3012 and what hpos to start it at.
3013 Also set `lastpos' to the last position which counts as "on this line"
3014 for cursor-positioning. */
3018 if (FETCH_CHAR (pos
) == '\n')
3020 /* If stopped due to a newline, start next line after it */
3022 /* Check again for hidden lines, in case the newline occurred exactly
3023 at the right margin. */
3024 while (pos
< ZV
&& selective
> 0
3025 && indented_beyond_p (pos
, selective
))
3026 pos
= find_next_newline (pos
, 1);
3029 /* Stopped due to right margin of window */
3033 *p1
++ = fix_glyph (f
, truncator
, 0);
3034 /* Truncating => start next line after next newline,
3035 and point is on this line if it is before the newline,
3036 and skip none of first char of next line */
3038 pos
= find_next_newline (pos
, 1);
3039 while (pos
< ZV
&& selective
> 0
3040 && indented_beyond_p (pos
, selective
));
3041 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
3043 lastpos
= pos
- (FETCH_CHAR (pos
- 1) == '\n');
3047 *p1
++ = fix_glyph (f
, continuer
, 0);
3054 /* If point is at eol or in invisible text at eol,
3055 record its frame location now. */
3057 if (start
<= PT
&& PT
<= lastpos
&& cursor_vpos
< 0)
3060 cursor_hpos
= p1
- leftmargin
;
3063 if (cursor_vpos
== vpos
)
3065 if (cursor_hpos
< 0) cursor_hpos
= 0;
3066 if (cursor_hpos
> width
) cursor_hpos
= width
;
3067 cursor_hpos
+= XFASTINT (w
->left
);
3068 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
3070 if (!(cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f
)
3071 && EQ (FRAME_MINIBUF_WINDOW (f
), minibuf_window
)))
3073 FRAME_CURSOR_Y (f
) = cursor_vpos
;
3074 FRAME_CURSOR_X (f
) = cursor_hpos
;
3077 if (w
== XWINDOW (selected_window
))
3079 /* Line is not continued and did not start
3080 in middle of character */
3081 if ((hpos
- XFASTINT (w
->left
)
3082 == (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
3085 this_line_bufpos
= start
;
3086 this_line_buffer
= current_buffer
;
3087 this_line_vpos
= cursor_vpos
;
3088 this_line_start_hpos
= hpos
;
3089 this_line_endpos
= Z
- lastpos
;
3092 this_line_bufpos
= 0;
3097 /* If hscroll and line not empty, insert truncation-at-left marker */
3098 if (hscroll
&& lastpos
!= start
)
3100 *leftmargin
= fix_glyph (f
, truncator
, 0);
3101 if (p1
<= leftmargin
)
3102 p1
= leftmargin
+ 1;
3105 if (XFASTINT (w
->width
) + XFASTINT (w
->left
) != FRAME_WIDTH (f
))
3108 if (p1
< leftmargin
) p1
= leftmargin
;
3109 while (p1
< endp
) *p1
++ = SPACEGLYPH
;
3111 /* Don't draw vertical bars if we're using scroll bars. They're
3112 covered up by the scroll bars, and it's distracting to see
3113 them when the scroll bar windows are flickering around to be
3115 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3118 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
3122 *p1
++ = (dp
&& INTEGERP (DISP_BORDER_GLYPH (dp
))
3123 ? DISP_BORDER_GLYPH (dp
)
3126 desired_glyphs
->used
[vpos
] = max (desired_glyphs
->used
[vpos
],
3127 p1
- desired_glyphs
->glyphs
[vpos
]);
3128 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
3130 /* If the start of this line is the overlay arrow-position,
3131 then put the arrow string into the display-line. */
3133 if (MARKERP (Voverlay_arrow_position
)
3134 && current_buffer
== XMARKER (Voverlay_arrow_position
)->buffer
3135 && start
== marker_position (Voverlay_arrow_position
)
3136 && STRINGP (Voverlay_arrow_string
)
3137 && ! overlay_arrow_seen
)
3139 unsigned char *p
= XSTRING (Voverlay_arrow_string
)->data
;
3141 int len
= XSTRING (Voverlay_arrow_string
)->size
;
3147 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string
)->intervals
))
3149 /* If the arrow string has text props, obey them when displaying. */
3150 for (i
= 0; i
< len
; i
++)
3153 Lisp_Object face
, ilisp
;
3156 XSETFASTINT (ilisp
, i
);
3157 face
= Fget_text_property (ilisp
, Qface
, Voverlay_arrow_string
);
3158 newface
= compute_glyph_face_1 (f
, face
, 0);
3159 leftmargin
[i
] = FAST_MAKE_GLYPH (c
, newface
);
3163 #endif /* HAVE_FACES */
3165 for (i
= 0; i
< len
; i
++)
3166 leftmargin
[i
] = p
[i
];
3169 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
3170 arrow_end
= (leftmargin
- desired_glyphs
->glyphs
[vpos
]) + len
;
3171 if (desired_glyphs
->used
[vpos
] < arrow_end
)
3172 desired_glyphs
->used
[vpos
] = arrow_end
;
3174 overlay_arrow_seen
= 1;
3178 val_display_text_line
= val
;
3179 return &val_display_text_line
;
3182 /* Redisplay the menu bar in the frame for window W. */
3185 display_menu_bar (w
)
3188 Lisp_Object items
, tail
;
3189 register int vpos
= 0;
3190 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3191 int maxendcol
= FRAME_WIDTH (f
);
3199 #ifdef USE_X_TOOLKIT
3202 #endif /* USE_X_TOOLKIT */
3204 get_display_line (f
, vpos
, 0);
3206 items
= FRAME_MENU_BAR_ITEMS (f
);
3207 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 3)
3209 Lisp_Object pos
, string
;
3210 string
= XVECTOR (items
)->contents
[i
+ 1];
3214 XSETFASTINT (XVECTOR (items
)->contents
[i
+ 2], hpos
);
3216 if (hpos
< maxendcol
)
3217 hpos
= display_string (XWINDOW (FRAME_ROOT_WINDOW (f
)), vpos
,
3218 XSTRING (string
)->data
,
3219 XSTRING (string
)->size
,
3220 hpos
, 0, 0, hpos
, maxendcol
);
3221 /* Put a space between items. */
3222 if (hpos
< maxendcol
)
3224 int hpos1
= hpos
+ 1;
3225 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0,
3226 min (hpos1
, maxendcol
), maxendcol
);
3230 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3231 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3233 /* Fill out the line with spaces. */
3234 if (maxendcol
> hpos
)
3235 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0, maxendcol
, maxendcol
);
3237 /* Clear the rest of the lines allocated to the menu bar. */
3239 while (vpos
< FRAME_MENU_BAR_LINES (f
))
3240 get_display_line (f
, vpos
++, 0);
3243 /* Display the mode line for window w */
3246 display_mode_line (w
)
3249 register int vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
3250 register int left
= XFASTINT (w
->left
);
3251 register int right
= XFASTINT (w
->width
) + left
;
3252 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3254 line_number_displayed
= 0;
3255 w
->column_number_displayed
= Qnil
;
3257 get_display_line (f
, vpos
, left
);
3259 /* Temporarily make frame F's kboard the current kboard
3260 so that kboard-local variables in the mode_line_format
3261 will get the right values. */
3262 push_frame_kboard (f
);
3264 display_mode_element (w
, vpos
, left
, 0, right
, right
,
3265 current_buffer
->mode_line_format
);
3267 pop_frame_kboard ();
3269 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3271 /* Make the mode line inverse video if the entire line
3272 is made of mode lines.
3273 I.e. if this window is full width,
3274 or if it is the child of a full width window
3275 (which implies that that window is split side-by-side
3276 and the rest of this line is mode lines of the sibling windows). */
3277 if (XFASTINT (w
->width
) == FRAME_WIDTH (f
)
3278 || XFASTINT (XWINDOW (w
->parent
)->width
) == FRAME_WIDTH (f
))
3279 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3281 else if (! FRAME_TERMCAP_P (f
) && mode_line_inverse_video
)
3283 /* For a partial width window, explicitly set face of each glyph. */
3285 GLYPH
*ptr
= FRAME_DESIRED_GLYPHS (f
)->glyphs
[vpos
];
3286 for (i
= left
; i
< right
; ++i
)
3287 ptr
[i
] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr
[i
]), 1);
3292 /* Contribute ELT to the mode line for window W.
3293 How it translates into text depends on its data type.
3295 VPOS is the position of the mode line being displayed.
3297 HPOS is the position (absolute on frame) where this element's text
3298 should start. The output is truncated automatically at the right
3301 DEPTH is the depth in recursion. It is used to prevent
3302 infinite recursion here.
3304 MINENDCOL is the hpos before which the element may not end.
3305 The element is padded at the right with spaces if nec
3306 to reach this column.
3308 MAXENDCOL is the hpos past which this element may not extend.
3309 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3310 (This is necessary to make nested padding and truncation work.)
3312 Returns the hpos of the end of the text generated by ELT.
3313 The next element will receive that value as its HPOS arg,
3314 so as to concatenate the elements. */
3317 display_mode_element (w
, vpos
, hpos
, depth
, minendcol
, maxendcol
, elt
)
3319 register int vpos
, hpos
;
3322 register int maxendcol
;
3323 register Lisp_Object elt
;
3331 switch (SWITCH_ENUM_CAST (XTYPE (elt
)))
3335 /* A string: output it and check for %-constructs within it. */
3336 register unsigned char c
;
3337 register unsigned char *this = XSTRING (elt
)->data
;
3339 while (hpos
< maxendcol
&& *this)
3341 unsigned char *last
= this;
3342 while ((c
= *this++) != '\0' && c
!= '%')
3344 if (this - 1 != last
)
3346 register int lim
= --this - last
+ hpos
;
3347 if (frame_title_ptr
)
3348 hpos
= store_frame_title (last
, hpos
, min (lim
, maxendcol
));
3350 hpos
= display_string (w
, vpos
, last
, -1, hpos
, 0, 1,
3351 hpos
, min (lim
, maxendcol
));
3355 register int minendcol
;
3356 register int spec_width
= 0;
3358 /* We can't allow -ve args due to the "%-" construct */
3359 /* Argument specifies minwidth but not maxwidth
3360 (maxwidth can be specified by
3361 (<negative-number> . <stuff>) mode-line elements) */
3363 while ((c
= *this++) >= '0' && c
<= '9')
3365 spec_width
= spec_width
* 10 + (c
- '0');
3368 minendcol
= hpos
+ spec_width
;
3369 if (minendcol
> maxendcol
)
3371 spec_width
= maxendcol
- hpos
;
3372 minendcol
= maxendcol
;
3376 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
3377 spec_width
, maxendcol
,
3378 Vglobal_mode_string
);
3381 char *spec
= decode_mode_spec (w
, c
, spec_width
,
3383 if (frame_title_ptr
)
3384 hpos
= store_frame_title (spec
, minendcol
, maxendcol
);
3386 hpos
= display_string (w
, vpos
, spec
, -1,
3388 minendcol
, maxendcol
);
3396 /* A symbol: process the value of the symbol recursively
3397 as if it appeared here directly. Avoid error if symbol void.
3398 Special case: if value of symbol is a string, output the string
3401 register Lisp_Object tem
;
3402 tem
= Fboundp (elt
);
3405 tem
= Fsymbol_value (elt
);
3406 /* If value is a string, output that string literally:
3407 don't check for % within it. */
3410 if (frame_title_ptr
)
3411 hpos
= store_frame_title (XSTRING (tem
)->data
,
3412 minendcol
, maxendcol
);
3414 hpos
= display_string (w
, vpos
, XSTRING (tem
)->data
,
3415 XSTRING (tem
)->size
,
3416 hpos
, 0, 1, minendcol
, maxendcol
);
3418 /* Give up right away for nil or t. */
3419 else if (!EQ (tem
, elt
))
3420 { elt
= tem
; goto tail_recurse
; }
3427 register Lisp_Object car
, tem
;
3429 /* A cons cell: three distinct cases.
3430 If first element is a string or a cons, process all the elements
3431 and effectively concatenate them.
3432 If first element is a negative number, truncate displaying cdr to
3433 at most that many characters. If positive, pad (with spaces)
3434 to at least that many characters.
3435 If first element is a symbol, process the cadr or caddr recursively
3436 according to whether the symbol's value is non-nil or nil. */
3437 car
= XCONS (elt
)->car
;
3440 tem
= Fboundp (car
);
3441 elt
= XCONS (elt
)->cdr
;
3444 /* elt is now the cdr, and we know it is a cons cell.
3445 Use its car if CAR has a non-nil value. */
3448 tem
= Fsymbol_value (car
);
3450 { elt
= XCONS (elt
)->car
; goto tail_recurse
; }
3452 /* Symbol's value is nil (or symbol is unbound)
3453 Get the cddr of the original list
3454 and if possible find the caddr and use that. */
3455 elt
= XCONS (elt
)->cdr
;
3458 else if (!CONSP (elt
))
3460 elt
= XCONS (elt
)->car
;
3463 else if (INTEGERP (car
))
3465 register int lim
= XINT (car
);
3466 elt
= XCONS (elt
)->cdr
;
3468 /* Negative int means reduce maximum width.
3469 DO NOT change MINENDCOL here!
3470 (20 -10 . foo) should truncate foo to 10 col
3471 and then pad to 20. */
3472 maxendcol
= min (maxendcol
, hpos
- lim
);
3475 /* Padding specified. Don't let it be more than
3478 if (lim
> maxendcol
)
3480 /* If that's more padding than already wanted, queue it.
3481 But don't reduce padding already specified even if
3482 that is beyond the current truncation point. */
3483 if (lim
> minendcol
)
3488 else if (STRINGP (car
) || CONSP (car
))
3490 register int limit
= 50;
3491 /* LIMIT is to protect against circular lists. */
3492 while (CONSP (elt
) && --limit
> 0
3493 && hpos
< maxendcol
)
3495 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
3498 elt
= XCONS (elt
)->cdr
;
3506 if (frame_title_ptr
)
3507 hpos
= store_frame_title ("*invalid*", minendcol
, maxendcol
);
3509 hpos
= display_string (w
, vpos
, "*invalid*", -1, hpos
, 0, 1,
3510 minendcol
, maxendcol
);
3514 if (minendcol
> hpos
)
3515 if (frame_title_ptr
)
3516 hpos
= store_frame_title ("", minendcol
, maxendcol
);
3518 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 1, minendcol
, maxendcol
);
3522 /* Write a null-terminated, right justified decimal representation of
3523 the positive integer D to BUF using a minimal field width WIDTH. */
3526 pint2str (buf
, width
, d
)
3531 register char *p
= buf
;
3538 *p
++ = d
% 10 + '0';
3541 for (width
-= (int) (p
- buf
); width
> 0; --width
) *p
++ = ' ';
3551 /* Return a string for the output of a mode line %-spec for window W,
3552 generated by character C. SPEC_WIDTH is the field width when
3553 padding to the left (%c, %l). The value returned from this
3554 function will later be truncated to width MAXWIDTH. */
3556 static char lots_of_dashes
[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3559 decode_mode_spec (w
, c
, spec_width
, maxwidth
)
3562 register int spec_width
;
3563 register int maxwidth
;
3566 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3567 char *decode_mode_spec_buf
= (char *) FRAME_TEMP_GLYPHS (f
)->total_contents
;
3568 struct buffer
*b
= XBUFFER (w
->buffer
);
3571 if (maxwidth
> FRAME_WIDTH (f
))
3572 maxwidth
= FRAME_WIDTH (f
);
3577 if (!NILP (b
->read_only
))
3579 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3584 /* This differs from %* only for a modified read-only buffer. */
3585 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3587 if (!NILP (b
->read_only
))
3592 /* This differs from %* in ignoring read-only-ness. */
3593 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3605 if (command_loop_level
> 5)
3607 p
= decode_mode_spec_buf
;
3608 for (i
= 0; i
< command_loop_level
; i
++)
3611 return decode_mode_spec_buf
;
3619 if (command_loop_level
> 5)
3621 p
= decode_mode_spec_buf
;
3622 for (i
= 0; i
< command_loop_level
; i
++)
3625 return decode_mode_spec_buf
;
3633 if (maxwidth
< sizeof (lots_of_dashes
))
3634 return lots_of_dashes
;
3637 for (p
= decode_mode_spec_buf
, i
= maxwidth
; i
> 0; i
--)
3641 return decode_mode_spec_buf
;
3647 if (maxwidth
>= 3 && XSTRING (obj
)->size
> maxwidth
)
3649 bcopy (XSTRING (obj
)->data
, decode_mode_spec_buf
, maxwidth
- 1);
3650 decode_mode_spec_buf
[maxwidth
- 1] = '\\';
3651 decode_mode_spec_buf
[maxwidth
] = '\0';
3652 return decode_mode_spec_buf
;
3659 int col
= current_column ();
3660 XSETFASTINT (w
->column_number_displayed
, col
);
3661 pint2str (decode_mode_spec_buf
, spec_width
, col
);
3662 return decode_mode_spec_buf
;
3666 /* %F displays the frame name. */
3668 return (char *) XSTRING (selected_frame
->name
)->data
;
3678 else if (STRINGP (obj
) && XSTRING (obj
)->size
> maxwidth
)
3680 bcopy ("...", decode_mode_spec_buf
, 3);
3681 bcopy (XSTRING (obj
)->data
+ XSTRING (obj
)->size
- maxwidth
+ 3,
3682 decode_mode_spec_buf
+ 3, maxwidth
- 3);
3683 return decode_mode_spec_buf
;
3690 int startpos
= marker_position (w
->start
);
3691 int line
, linepos
, topline
;
3694 int height
= XFASTINT (w
->height
);
3696 /* If we decided that this buffer isn't suitable for line numbers,
3697 don't forget that too fast. */
3698 if (EQ (w
->base_line_pos
, w
->buffer
))
3701 /* If the buffer is very big, don't waste time. */
3702 if (BUF_ZV (b
) - BUF_BEGV (b
) > line_number_display_limit
)
3704 w
->base_line_pos
= Qnil
;
3705 w
->base_line_number
= Qnil
;
3709 if (!NILP (w
->base_line_number
)
3710 && !NILP (w
->base_line_pos
)
3711 && XFASTINT (w
->base_line_pos
) <= marker_position (w
->start
))
3713 line
= XFASTINT (w
->base_line_number
);
3714 linepos
= XFASTINT (w
->base_line_pos
);
3719 linepos
= BUF_BEGV (b
);
3722 /* Count lines from base line to window start position. */
3723 nlines
= display_count_lines (linepos
, startpos
, startpos
, &junk
);
3725 topline
= nlines
+ line
;
3727 /* Determine a new base line, if the old one is too close
3728 or too far away, or if we did not have one.
3729 "Too close" means it's plausible a scroll-down would
3731 if (startpos
== BUF_BEGV (b
))
3733 XSETFASTINT (w
->base_line_number
, topline
);
3734 XSETFASTINT (w
->base_line_pos
, BUF_BEGV (b
));
3736 else if (nlines
< height
+ 25 || nlines
> height
* 3 + 50
3737 || linepos
== BUF_BEGV (b
))
3739 int limit
= BUF_BEGV (b
);
3741 int distance
= (height
* 2 + 30) * 200;
3743 if (startpos
- distance
> limit
)
3744 limit
= startpos
- distance
;
3746 nlines
= display_count_lines (startpos
, limit
,
3749 /* If we couldn't find the lines we wanted within
3751 give up on line numbers for this window. */
3752 if (position
== startpos
- distance
)
3754 w
->base_line_pos
= w
->buffer
;
3755 w
->base_line_number
= Qnil
;
3759 XSETFASTINT (w
->base_line_number
, topline
- nlines
);
3760 XSETFASTINT (w
->base_line_pos
, position
);
3763 /* Now count lines from the start pos to point. */
3764 nlines
= display_count_lines (startpos
, PT
, PT
, &junk
);
3766 /* Record that we did display the line number. */
3767 line_number_displayed
= 1;
3769 /* Make the string to show. */
3770 pint2str (decode_mode_spec_buf
, spec_width
, topline
+ nlines
);
3771 return decode_mode_spec_buf
;
3774 char* p
= decode_mode_spec_buf
;
3775 for (spec_width
-= 2; spec_width
> 0; --spec_width
) *p
++ = ' ';
3777 return decode_mode_spec_buf
;
3787 if (BUF_BEGV (b
) > BUF_BEG (b
) || BUF_ZV (b
) < BUF_Z (b
))
3793 int pos
= marker_position (w
->start
);
3794 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3796 if (XFASTINT (w
->window_end_pos
) <= BUF_Z (b
) - BUF_ZV (b
))
3798 if (pos
<= BUF_BEGV (b
))
3803 else if (pos
<= BUF_BEGV (b
))
3807 if (total
> 1000000)
3808 /* Do it differently for a large value, to avoid overflow. */
3809 total
= ((pos
- BUF_BEGV (b
)) + (total
/ 100) - 1) / (total
/ 100);
3811 total
= ((pos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3812 /* We can't normally display a 3-digit number,
3813 so get us a 2-digit number that is close. */
3816 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3817 return decode_mode_spec_buf
;
3821 /* Display percentage of size above the bottom of the screen. */
3824 int toppos
= marker_position (w
->start
);
3825 int botpos
= BUF_Z (b
) - XFASTINT (w
->window_end_pos
);
3826 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3828 if (botpos
>= BUF_ZV (b
))
3830 if (toppos
<= BUF_BEGV (b
))
3837 if (total
> 1000000)
3838 /* Do it differently for a large value, to avoid overflow. */
3839 total
= ((botpos
- BUF_BEGV (b
)) + (total
/ 100) - 1) / (total
/ 100);
3841 total
= ((botpos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3842 /* We can't normally display a 3-digit number,
3843 so get us a 2-digit number that is close. */
3846 if (toppos
<= BUF_BEGV (b
))
3847 sprintf (decode_mode_spec_buf
, "Top%2d%%", total
);
3849 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3850 return decode_mode_spec_buf
;
3855 /* status of process */
3856 obj
= Fget_buffer_process (w
->buffer
);
3858 return "no process";
3860 obj
= Fsymbol_name (Fprocess_status (obj
));
3864 case 't': /* indicate TEXT or BINARY */
3865 #ifdef MODE_LINE_BINARY_TEXT
3866 return MODE_LINE_BINARY_TEXT (b
);
3873 return (char *) XSTRING (obj
)->data
;
3878 /* Search for COUNT instances of a line boundary, which means either a
3879 newline or (if selective display enabled) a carriage return.
3880 Start at START. If COUNT is negative, search backwards.
3882 If we find COUNT instances, set *SHORTAGE to zero, and return the
3883 position after the COUNTth match. Note that for reverse motion
3884 this is not the same as the usual convention for Emacs motion commands.
3886 If we don't find COUNT instances before reaching the end of the
3887 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3888 the number of line boundaries left unfound, and return the end of the
3889 buffer we bumped up against. */
3892 display_scan_buffer (start
, count
, shortage
)
3893 int *shortage
, start
;
3896 int limit
= ((count
> 0) ? ZV
- 1 : BEGV
);
3897 int direction
= ((count
> 0) ? 1 : -1);
3899 register unsigned char *cursor
;
3900 unsigned char *base
;
3902 register int ceiling
;
3903 register unsigned char *ceiling_addr
;
3905 /* If we are not in selective display mode,
3906 check only for newlines. */
3907 if (! (!NILP (current_buffer
->selective_display
)
3908 && !INTEGERP (current_buffer
->selective_display
)))
3909 return scan_buffer ('\n', start
, 0, count
, shortage
, 0);
3911 /* The code that follows is like scan_buffer
3912 but checks for either newline or carriage return. */
3918 while (start
!= limit
+ 1)
3920 ceiling
= BUFFER_CEILING_OF (start
);
3921 ceiling
= min (limit
, ceiling
);
3922 ceiling_addr
= &FETCH_CHAR (ceiling
) + 1;
3923 base
= (cursor
= &FETCH_CHAR (start
));
3926 while (*cursor
!= '\n' && *cursor
!= 015 && ++cursor
!= ceiling_addr
)
3928 if (cursor
!= ceiling_addr
)
3933 return (start
+ cursor
- base
+ 1);
3936 if (++cursor
== ceiling_addr
)
3942 start
+= cursor
- base
;
3946 start
--; /* first character we scan */
3947 while (start
> limit
- 1)
3948 { /* we WILL scan under start */
3949 ceiling
= BUFFER_FLOOR_OF (start
);
3950 ceiling
= max (limit
, ceiling
);
3951 ceiling_addr
= &FETCH_CHAR (ceiling
) - 1;
3952 base
= (cursor
= &FETCH_CHAR (start
));
3956 while (--cursor
!= ceiling_addr
3957 && *cursor
!= '\n' && *cursor
!= 015)
3959 if (cursor
!= ceiling_addr
)
3964 return (start
+ cursor
- base
+ 1);
3970 start
+= cursor
- base
;
3975 *shortage
= count
* direction
;
3976 return (start
+ ((direction
== 1 ? 0 : 1)));
3979 /* Count up to N lines starting from FROM.
3980 But don't go beyond LIMIT.
3981 Return the number of lines thus found (always positive).
3982 Store the position after what was found into *POS_PTR. */
3985 display_count_lines (from
, limit
, n
, pos_ptr
)
3998 *pos_ptr
= display_scan_buffer (from
, n
, &shortage
);
4004 /* When scanning backwards, scan_buffer stops *after* the last newline
4005 it finds, but does count it. Compensate for that. */
4006 return - n
- shortage
- (*pos_ptr
!= limit
);
4007 return n
- shortage
;
4010 /* Display STRING on one line of window W, starting at HPOS.
4011 Display at position VPOS. Caller should have done get_display_line.
4012 If VPOS == -1, display it as the current frame's title.
4013 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
4015 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
4017 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
4018 MAXCOL is the last column ok to end at. Truncate here.
4019 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
4020 Both count from the left edge of the frame, as does HPOS.
4021 The right edge of W is an implicit maximum.
4022 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
4024 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
4025 at the place where the current window ends in this line
4026 and not display anything beyond there. Otherwise, only MAXCOL
4027 controls where to stop output.
4029 Returns ending hpos. */
4032 display_string (w
, vpos
, string
, length
, hpos
, truncate
,
4033 obey_window_width
, mincol
, maxcol
)
4035 unsigned char *string
;
4039 int obey_window_width
;
4045 int hscroll
= XINT (w
->hscroll
);
4046 int tab_width
= XINT (XBUFFER (w
->buffer
)->tab_width
);
4047 register GLYPH
*start
;
4048 register GLYPH
*end
;
4049 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
4050 struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
4051 GLYPH
*p1start
= desired_glyphs
->glyphs
[vpos
] + hpos
;
4052 int window_width
= XFASTINT (w
->width
);
4054 /* Use the standard display table, not the window's display table.
4055 We don't want the mode line in rot13. */
4056 register struct Lisp_Char_Table
*dp
= 0;
4059 if (DISP_TABLE_P (Vstandard_display_table
))
4060 dp
= XCHAR_TABLE (Vstandard_display_table
);
4062 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
4065 start
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
4067 if (obey_window_width
)
4069 end
= start
+ window_width
- (truncate
!= 0);
4071 if ((window_width
+ XFASTINT (w
->left
)) != FRAME_WIDTH (f
))
4073 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4077 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
4085 if (! obey_window_width
4086 || (maxcol
>= 0 && end
- desired_glyphs
->glyphs
[vpos
] > maxcol
))
4087 end
= desired_glyphs
->glyphs
[vpos
] + maxcol
;
4089 /* Store 0 in charstart for these columns. */
4090 for (i
= (hpos
>= 0 ? hpos
: 0); i
< end
- p1start
+ hpos
; i
++)
4091 desired_glyphs
->charstarts
[vpos
][i
] = 0;
4093 if (maxcol
>= 0 && mincol
> maxcol
)
4096 /* We set truncated to 1 if we get stopped by trying to pass END
4097 (that is, trying to pass MAXCOL.) */
4104 /* Specified length. */
4107 /* Unspecified length (null-terminated string). */
4117 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
4119 p1
= copy_part_of_rope (f
, p1
, start
,
4120 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
4121 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
4124 else if (c
>= 040 && c
< 0177)
4134 if (p1
>= start
&& p1
< end
)
4138 while ((p1
- start
+ hscroll
- (hscroll
> 0)) % tab_width
);
4140 else if (c
< 0200 && ! NILP (buffer_defaults
.ctl_arrow
))
4143 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
4144 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
4147 if (p1
>= start
&& p1
< end
)
4154 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
4155 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
4158 if (p1
>= start
&& p1
< end
)
4159 *p1
= (c
>> 6) + '0';
4161 if (p1
>= start
&& p1
< end
)
4162 *p1
= (7 & (c
>> 3)) + '0';
4164 if (p1
>= start
&& p1
< end
)
4165 *p1
= (7 & c
) + '0';
4173 if (truncate
) *p1
++ = fix_glyph (f
, truncate
, 0);
4175 else if (mincol
>= 0)
4177 end
= desired_glyphs
->glyphs
[vpos
] + mincol
;
4183 register int len
= p1
- desired_glyphs
->glyphs
[vpos
];
4185 if (len
> desired_glyphs
->used
[vpos
])
4186 desired_glyphs
->used
[vpos
] = len
;
4187 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
4193 /* This is like a combination of memq and assq.
4194 Return 1 if PROPVAL appears as an element of LIST
4195 or as the car of an element of LIST.
4196 If PROPVAL is a list, compare each element against LIST
4197 in that way, and return 1 if any element of PROPVAL is found in LIST.
4199 This function cannot quit. */
4202 invisible_p (propval
, list
)
4203 register Lisp_Object propval
;
4206 register Lisp_Object tail
, proptail
;
4207 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4209 register Lisp_Object tem
;
4210 tem
= XCONS (tail
)->car
;
4211 if (EQ (propval
, tem
))
4213 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4216 if (CONSP (propval
))
4217 for (proptail
= propval
; CONSP (proptail
);
4218 proptail
= XCONS (proptail
)->cdr
)
4220 Lisp_Object propelt
;
4221 propelt
= XCONS (proptail
)->car
;
4222 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4224 register Lisp_Object tem
;
4225 tem
= XCONS (tail
)->car
;
4226 if (EQ (propelt
, tem
))
4228 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4235 /* Return 1 if PROPVAL appears as the car of an element of LIST
4236 and the cdr of that element is non-nil.
4237 If PROPVAL is a list, check each element of PROPVAL in that way,
4238 and the first time some element is found,
4239 return 1 if the cdr of that element is non-nil.
4241 This function cannot quit. */
4244 invisible_ellipsis_p (propval
, list
)
4245 register Lisp_Object propval
;
4248 register Lisp_Object tail
, proptail
;
4249 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4251 register Lisp_Object tem
;
4252 tem
= XCONS (tail
)->car
;
4253 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4254 return ! NILP (XCONS (tem
)->cdr
);
4256 if (CONSP (propval
))
4257 for (proptail
= propval
; CONSP (proptail
);
4258 proptail
= XCONS (proptail
)->cdr
)
4260 Lisp_Object propelt
;
4261 propelt
= XCONS (proptail
)->car
;
4262 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4264 register Lisp_Object tem
;
4265 tem
= XCONS (tail
)->car
;
4266 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4267 return ! NILP (XCONS (tem
)->cdr
);
4276 staticpro (&Qmenu_bar_update_hook
);
4277 Qmenu_bar_update_hook
= intern ("menu-bar-update-hook");
4279 staticpro (&Qoverriding_terminal_local_map
);
4280 Qoverriding_terminal_local_map
= intern ("overriding-terminal-local-map");
4282 staticpro (&Qoverriding_local_map
);
4283 Qoverriding_local_map
= intern ("overriding-local-map");
4285 staticpro (&Qwindow_scroll_functions
);
4286 Qwindow_scroll_functions
= intern ("window-scroll-functions");
4288 staticpro (&Qredisplay_end_trigger_functions
);
4289 Qredisplay_end_trigger_functions
= intern ("redisplay-end-trigger-functions");
4291 staticpro (&last_arrow_position
);
4292 staticpro (&last_arrow_string
);
4293 last_arrow_position
= Qnil
;
4294 last_arrow_string
= Qnil
;
4296 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
,
4297 "String (or mode line construct) included (normally) in `mode-line-format'.");
4298 Vglobal_mode_string
= Qnil
;
4300 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
,
4301 "Marker for where to display an arrow on top of the buffer text.\n\
4302 This must be the beginning of a line in order to work.\n\
4303 See also `overlay-arrow-string'.");
4304 Voverlay_arrow_position
= Qnil
;
4306 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
,
4307 "String to display as an arrow. See also `overlay-arrow-position'.");
4308 Voverlay_arrow_string
= Qnil
;
4310 DEFVAR_INT ("scroll-step", &scroll_step
,
4311 "*The number of lines to try scrolling a window by when point moves out.\n\
4312 If that fails to bring point back on frame, point is centered instead.\n\
4313 If this is zero, point is always centered after it moves off frame.");
4315 DEFVAR_INT ("debug-end-pos", &debug_end_pos
, "Don't ask");
4317 DEFVAR_BOOL ("truncate-partial-width-windows",
4318 &truncate_partial_width_windows
,
4319 "*Non-nil means truncate lines in all windows less than full frame wide.");
4320 truncate_partial_width_windows
= 1;
4322 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
,
4323 "*Non-nil means use inverse video for the mode line.");
4324 mode_line_inverse_video
= 1;
4326 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit
,
4327 "*Maximum buffer size for which line number should be displayed.");
4328 line_number_display_limit
= 1000000;
4330 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
,
4331 "*Non-nil means highlight region even in nonselected windows.");
4332 highlight_nonselected_windows
= 1;
4334 DEFVAR_BOOL ("multiple-frames", &multiple_frames
,
4335 "Non-nil if more than one frame is visible on this display.\n\
4336 Minibuffer-only frames don't count, but iconified frames do.\n\
4337 This variable is not guaranteed to be accurate except while processing\n\
4338 `frame-title-format' and `icon-title-format'.");
4340 DEFVAR_LISP ("frame-title-format", &Vframe_title_format
,
4341 "Template for displaying the titlebar of visible frames.\n\
4342 \(Assuming the window manager supports this feature.)\n\
4343 This variable has the same structure as `mode-line-format' (which see),\n\
4344 and is used only on frames for which no explicit name has been set\n\
4345 \(see `modify-frame-parameters').");
4346 DEFVAR_LISP ("icon-title-format", &Vicon_title_format
,
4347 "Template for displaying the titlebar of an iconified frame.\n\
4348 \(Assuming the window manager supports this feature.)\n\
4349 This variable has the same structure as `mode-line-format' (which see),\n\
4350 and is used only on frames for which no explicit name has been set\n\
4351 \(see `modify-frame-parameters').");
4353 = Vframe_title_format
4354 = Fcons (intern ("multiple-frames"),
4355 Fcons (build_string ("%b"),
4356 Fcons (Fcons (build_string (""),
4357 Fcons (intern ("invocation-name"),
4358 Fcons (build_string ("@"),
4359 Fcons (intern ("system-name"),
4363 DEFVAR_LISP ("message-log-max", &Vmessage_log_max
,
4364 "Maximum number of lines to keep in the message log buffer.\n\
4365 If nil, disable message logging. If t, log messages but don't truncate\n\
4366 the buffer when it becomes large.");
4367 XSETFASTINT (Vmessage_log_max
, 50);
4369 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions
,
4370 "Functions called before redisplay, if window sizes have changed.\n\
4371 The value should be a list of functions that take one argument.\n\
4372 Just before redisplay, for each frame, if any of its windows have changed\n\
4373 size since the last redisplay, or have been split or deleted,\n\
4374 all the functions in the list are called, with the frame as argument.");
4375 Vwindow_size_change_functions
= Qnil
;
4377 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions
,
4378 "List of Functions to call before redisplaying a window with scrolling.\n\
4379 Each function is called with two arguments, the window\n\
4380 and its new display-start position. Note that the value of `window-end'\n\
4381 is not valid when these functions are called.");
4382 Vwindow_scroll_functions
= Qnil
;
4385 /* initialize the window system */
4388 Lisp_Object root_window
;
4389 #ifndef COMPILER_REGISTER_BUG
4391 #endif /* COMPILER_REGISTER_BUG */
4392 struct window
*mini_w
;
4394 this_line_bufpos
= 0;
4396 mini_w
= XWINDOW (minibuf_window
);
4397 root_window
= FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w
)));
4399 echo_area_glyphs
= 0;
4400 previous_echo_glyphs
= 0;
4402 if (!noninteractive
)
4404 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (root_window
)));
4405 XSETFASTINT (XWINDOW (root_window
)->top
, 0);
4406 set_window_height (root_window
, FRAME_HEIGHT (f
) - 1, 0);
4407 XSETFASTINT (mini_w
->top
, FRAME_HEIGHT (f
) - 1);
4408 set_window_height (minibuf_window
, 1, 0);
4410 XSETFASTINT (XWINDOW (root_window
)->width
, FRAME_WIDTH (f
));
4411 XSETFASTINT (mini_w
->width
, FRAME_WIDTH (f
));