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