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
;
785 register struct window
*w
= XWINDOW (selected_window
);
789 register int tlbufpos
, tlendpos
;
795 /* Set the visible flags for all frames.
796 Do this before checking for resized or garbaged frames; they want
797 to know if their frames are visible.
798 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
800 Lisp_Object tail
, frame
;
802 FOR_EACH_FRAME (tail
, frame
)
804 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
806 /* Clear out all the display lines in which we will generate the
807 glyphs to display. */
808 init_desired_glyphs (XFRAME (frame
));
812 /* Notice any pending interrupt request to change frame size. */
813 do_pending_window_change ();
817 redraw_garbaged_frames ();
821 prepare_menu_bars ();
823 if (windows_or_buffers_changed
)
826 /* Detect case that we need to write a star in the mode line. */
827 if (XFASTINT (w
->last_modified
) < MODIFF
828 && XFASTINT (w
->last_modified
) <= SAVE_MODIFF
)
830 w
->update_mode_line
= Qt
;
831 if (buffer_shared
> 1)
835 /* If %c is in use, update it if needed. */
836 if (!NILP (w
->column_number_displayed
)
837 /* This alternative quickly identifies a common case
838 where no change is needed. */
839 && !(PT
== XFASTINT (w
->last_point
)
840 && XFASTINT (w
->last_modified
) >= MODIFF
)
841 && XFASTINT (w
->column_number_displayed
) != current_column ())
842 w
->update_mode_line
= Qt
;
844 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w
->frame
)) = -1;
846 all_windows
= update_mode_lines
|| buffer_shared
> 1;
848 /* If specs for an arrow have changed, do thorough redisplay
849 to ensure we remove any arrow that should no longer exist. */
850 if (! EQ (Voverlay_arrow_position
, last_arrow_position
)
851 || ! EQ (Voverlay_arrow_string
, last_arrow_string
))
854 /* Normally the message* functions will have already displayed and
855 updated the echo area, but the frame may have been trashed, or
856 the update may have been preempted, so display the echo area
858 if (echo_area_glyphs
|| previous_echo_glyphs
)
860 echo_area_display ();
864 /* If showing region, and mark has changed, must redisplay whole window. */
865 if (((!NILP (Vtransient_mark_mode
)
866 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
867 != !NILP (w
->region_showing
))
868 || (!NILP (w
->region_showing
)
869 && !EQ (w
->region_showing
,
870 Fmarker_position (XBUFFER (w
->buffer
)->mark
))))
871 this_line_bufpos
= -1;
873 tlbufpos
= this_line_bufpos
;
874 tlendpos
= this_line_endpos
;
875 if (!all_windows
&& tlbufpos
> 0 && NILP (w
->update_mode_line
)
876 && !current_buffer
->clip_changed
877 && FRAME_VISIBLE_P (XFRAME (w
->frame
))
878 /* Make sure recorded data applies to current buffer, etc */
879 && this_line_buffer
== current_buffer
880 && current_buffer
== XBUFFER (w
->buffer
)
881 && NILP (w
->force_start
)
882 /* Point must be on the line that we have info recorded about */
884 && PT
<= Z
- tlendpos
885 /* All text outside that line, including its final newline,
887 && (XFASTINT (w
->last_modified
) >= MODIFF
888 || (beg_unchanged
>= tlbufpos
- 1
890 /* If selective display, can't optimize
891 if the changes start at the beginning of the line. */
892 && ((INTEGERP (current_buffer
->selective_display
)
893 && XINT (current_buffer
->selective_display
) > 0
894 ? (beg_unchanged
>= tlbufpos
897 && end_unchanged
>= tlendpos
898 && Z
- GPT
>= tlendpos
)))
900 if (tlbufpos
> BEGV
&& FETCH_CHAR (tlbufpos
- 1) != '\n'
902 || FETCH_CHAR (tlbufpos
) == '\n'))
903 /* Former continuation line has disappeared by becoming empty */
905 else if (XFASTINT (w
->last_modified
) < MODIFF
906 || MINI_WINDOW_P (w
))
909 overlay_arrow_seen
= 0;
911 display_text_line (w
, tlbufpos
, this_line_vpos
, this_line_start_hpos
,
912 pos_tab_offset (w
, tlbufpos
));
913 /* If line contains point, is not continued,
914 and ends at same distance from eob as before, we win */
915 if (cursor_vpos
>= 0 && this_line_bufpos
916 && this_line_endpos
== tlendpos
)
918 /* If this is not the window's last line,
919 we must adjust the charstarts of the lines below. */
920 if (this_line_vpos
+ 1
921 < XFASTINT (w
->top
) + window_internal_height (w
))
923 int left
= XFASTINT (w
->left
);
924 int *charstart_next_line
925 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w
)))->charstarts
[this_line_vpos
+ 1];
928 if (Z
- tlendpos
== ZV
)
929 /* This line ends at end of (accessible part of) buffer.
930 There is no newline to count. */
931 adjust
= Z
- tlendpos
- charstart_next_line
[left
];
933 /* This line ends in a newline.
934 Must take account of the newline and the rest of the
935 text that follows. */
936 adjust
= Z
- tlendpos
+ 1 - charstart_next_line
[left
];
938 adjust_window_charstarts (w
, this_line_vpos
, adjust
);
941 if (XFASTINT (w
->width
) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w
))))
942 preserve_other_columns (w
);
948 else if (PT
== XFASTINT (w
->last_point
)
949 /* Make sure the cursor was last displayed
950 in this window. Otherwise we have to reposition it. */
951 && XINT (w
->top
) <= FRAME_CURSOR_Y (selected_frame
)
952 && (XINT (w
->top
) + XINT (w
->height
)
953 > FRAME_CURSOR_Y (selected_frame
)))
957 do_pending_window_change ();
962 /* If highlighting the region, or if the cursor is in the echo area,
963 then we can't just move the cursor. */
964 else if (! (!NILP (Vtransient_mark_mode
)
965 && !NILP (current_buffer
->mark_active
))
966 && NILP (w
->region_showing
)
967 && !cursor_in_echo_area
)
969 pos
= *compute_motion (tlbufpos
, 0,
970 XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0,
972 PT
, 2, - (1 << (SHORTBITS
- 1)),
973 window_internal_width (w
) - 1,
975 pos_tab_offset (w
, tlbufpos
), w
);
978 int width
= window_internal_width (w
) - 1;
979 FRAME_CURSOR_X (selected_frame
)
980 = XFASTINT (w
->left
) + minmax (0, pos
.hpos
, width
);
981 FRAME_CURSOR_Y (selected_frame
) = this_line_vpos
;
988 /* Text changed drastically or point moved off of line */
989 cancel_line (this_line_vpos
, selected_frame
);
992 this_line_bufpos
= 0;
993 all_windows
|= buffer_shared
> 1;
995 clear_face_cache_count
++;
999 Lisp_Object tail
, frame
;
1002 /* Clear the face cache, only when we do a full redisplay
1003 and not too often either. */
1004 if (clear_face_cache_count
> 1000)
1006 clear_face_cache ();
1007 clear_face_cache_count
= 0;
1011 /* Recompute # windows showing selected buffer.
1012 This will be incremented each time such a window is displayed. */
1015 FOR_EACH_FRAME (tail
, frame
)
1017 FRAME_PTR f
= XFRAME (frame
);
1018 if (! FRAME_TERMCAP_P (f
) || f
== selected_frame
)
1021 /* Mark all the scroll bars to be removed; we'll redeem the ones
1022 we want when we redisplay their windows. */
1023 if (condemn_scroll_bars_hook
)
1024 (*condemn_scroll_bars_hook
) (f
);
1026 if (FRAME_VISIBLE_P (f
))
1027 redisplay_windows (FRAME_ROOT_WINDOW (f
));
1029 /* Any scroll bars which redisplay_windows should have nuked
1030 should now go away. */
1031 if (judge_scroll_bars_hook
)
1032 (*judge_scroll_bars_hook
) (f
);
1036 else if (FRAME_VISIBLE_P (selected_frame
))
1038 redisplay_window (selected_window
, 1);
1039 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
1040 preserve_other_columns (w
);
1044 /* Prevent various kinds of signals during display update.
1045 stdio is not robust about handling signals,
1046 which can cause an apparent I/O error. */
1047 if (interrupt_input
)
1058 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1062 if (!FRAMEP (XCONS (tail
)->car
))
1065 f
= XFRAME (XCONS (tail
)->car
);
1067 if ((! FRAME_TERMCAP_P (f
) || f
== selected_frame
)
1068 && FRAME_VISIBLE_P (f
))
1070 pause
|= update_frame (f
, 0, 0);
1073 mark_window_display_accurate (f
->root_window
, 1);
1074 if (frame_up_to_date_hook
!= 0)
1075 (*frame_up_to_date_hook
) (f
);
1081 #endif /* MULTI_FRAME */
1083 if (FRAME_VISIBLE_P (selected_frame
))
1084 pause
= update_frame (selected_frame
, 0, 0);
1088 /* We may have called echo_area_display at the top of this
1089 function. If the echo area is on another frame, that may
1090 have put text on a frame other than the selected one, so the
1091 above call to update_frame would not have caught it. Catch
1094 FRAME_PTR mini_frame
1095 = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window
)));
1097 if (mini_frame
!= selected_frame
)
1098 pause
|= update_frame (mini_frame
, 0, 0);
1102 /* If frame does not match, prevent doing single-line-update next time.
1103 Also, don't forget to check every line to update the arrow. */
1106 this_line_bufpos
= 0;
1107 if (!NILP (last_arrow_position
))
1109 last_arrow_position
= Qt
;
1110 last_arrow_string
= Qt
;
1112 /* If we pause after scrolling, some lines in current_frame
1113 may be null, so preserve_other_columns won't be able to
1114 preserve all the vertical-bar separators. So, avoid using it
1116 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
1117 update_mode_lines
= 1;
1120 /* Now text on frame agrees with windows, so
1121 put info into the windows for partial redisplay to follow */
1125 register struct buffer
*b
= XBUFFER (w
->buffer
);
1127 blank_end_of_window
= 0;
1128 unchanged_modified
= BUF_MODIFF (b
);
1129 beg_unchanged
= BUF_GPT (b
) - BUF_BEG (b
);
1130 end_unchanged
= BUF_Z (b
) - BUF_GPT (b
);
1132 XSETFASTINT (w
->last_point
, BUF_PT (b
));
1133 XSETFASTINT (w
->last_point_x
, FRAME_CURSOR_X (selected_frame
));
1134 XSETFASTINT (w
->last_point_y
, FRAME_CURSOR_Y (selected_frame
));
1137 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame
), 1);
1140 b
->clip_changed
= 0;
1141 w
->update_mode_line
= Qnil
;
1142 XSETFASTINT (w
->last_modified
, BUF_MODIFF (b
));
1143 w
->window_end_valid
= w
->buffer
;
1144 last_arrow_position
= Voverlay_arrow_position
;
1145 last_arrow_string
= Voverlay_arrow_string
;
1146 if (do_verify_charstarts
)
1147 verify_charstarts (w
);
1148 if (frame_up_to_date_hook
!= 0)
1149 (*frame_up_to_date_hook
) (selected_frame
);
1151 update_mode_lines
= 0;
1152 windows_or_buffers_changed
= 0;
1155 /* Start SIGIO interrupts coming again.
1156 Having them off during the code above
1157 makes it less likely one will discard output,
1158 but not impossible, since there might be stuff
1159 in the system buffer here.
1160 But it is much hairier to try to do anything about that. */
1162 if (interrupt_input
)
1166 /* Change frame size now if a change is pending. */
1167 do_pending_window_change ();
1169 /* If we just did a pending size change, redisplay again
1170 for the new size. */
1171 if (windows_or_buffers_changed
&& !pause
)
1175 /* Redisplay, but leave alone any recent echo area message
1176 unless another message has been requested in its place.
1178 This is useful in situations where you need to redisplay but no
1179 user action has occurred, making it inappropriate for the message
1180 area to be cleared. See tracking_off and
1181 wait_reading_process_input for examples of these situations. */
1183 redisplay_preserve_echo_area ()
1185 if (echo_area_glyphs
== 0 && previous_echo_glyphs
!= 0)
1187 echo_area_glyphs
= previous_echo_glyphs
;
1189 echo_area_glyphs
= 0;
1196 mark_window_display_accurate (window
, flag
)
1200 register struct window
*w
;
1202 for (;!NILP (window
); window
= w
->next
)
1204 if (!WINDOWP (window
)) abort ();
1205 w
= XWINDOW (window
);
1207 if (!NILP (w
->buffer
))
1209 XSETFASTINT (w
->last_modified
,
1210 !flag
? 0 : BUF_MODIFF (XBUFFER (w
->buffer
)));
1212 /* Record if we are showing a region, so can make sure to
1213 update it fully at next redisplay. */
1214 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
1215 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
1216 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
1220 w
->window_end_valid
= w
->buffer
;
1221 w
->update_mode_line
= Qnil
;
1222 if (!NILP (w
->buffer
))
1223 XBUFFER (w
->buffer
)->clip_changed
= 0;
1225 if (!NILP (w
->vchild
))
1226 mark_window_display_accurate (w
->vchild
, flag
);
1227 if (!NILP (w
->hchild
))
1228 mark_window_display_accurate (w
->hchild
, flag
);
1233 last_arrow_position
= Voverlay_arrow_position
;
1234 last_arrow_string
= Voverlay_arrow_string
;
1238 /* t is unequal to any useful value of Voverlay_arrow_... */
1239 last_arrow_position
= Qt
;
1240 last_arrow_string
= Qt
;
1244 /* Update the menu bar item list for frame F.
1245 This has to be done before we start to fill in any display lines,
1246 because it can call eval.
1248 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1251 update_menu_bar (f
, save_match_data
)
1253 int save_match_data
;
1255 struct buffer
*old
= current_buffer
;
1257 register struct window
*w
;
1259 window
= FRAME_SELECTED_WINDOW (f
);
1260 w
= XWINDOW (window
);
1262 if (update_mode_lines
)
1263 w
->update_mode_line
= Qt
;
1266 #ifdef USE_X_TOOLKIT
1267 FRAME_EXTERNAL_MENU_BAR (f
)
1269 FRAME_MENU_BAR_LINES (f
) > 0
1273 /* If the user has switched buffers or windows, we need to
1274 recompute to reflect the new bindings. But we'll
1275 recompute when update_mode_lines is set too; that means
1276 that people can use force-mode-line-update to request
1277 that the menu bar be recomputed. The adverse effect on
1278 the rest of the redisplay algorithm is about the same as
1279 windows_or_buffers_changed anyway. */
1280 if (windows_or_buffers_changed
1281 || !NILP (w
->update_mode_line
)
1282 || (XFASTINT (w
->last_modified
) < MODIFF
1283 && (XFASTINT (w
->last_modified
)
1284 <= BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))))
1285 || ((!NILP (Vtransient_mark_mode
)
1286 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
1287 != !NILP (w
->region_showing
)))
1289 struct buffer
*prev
= current_buffer
;
1290 int count
= specpdl_ptr
- specpdl
;
1292 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1293 if (save_match_data
)
1294 record_unwind_protect (Fstore_match_data
, Fmatch_data ());
1295 if (NILP (Voverriding_local_map_menu_flag
))
1297 specbind (Qoverriding_terminal_local_map
, Qnil
);
1298 specbind (Qoverriding_local_map
, Qnil
);
1301 /* Run the Lucid hook. */
1302 call1 (Vrun_hooks
, Qactivate_menubar_hook
);
1303 /* If it has changed current-menubar from previous value,
1304 really recompute the menubar from the value. */
1305 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1306 call0 (Qrecompute_lucid_menubar
);
1307 call1 (Vrun_hooks
, Qmenu_bar_update_hook
);
1308 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1309 #ifdef USE_X_TOOLKIT
1310 set_frame_menubar (f
, 0);
1311 #endif /* USE_X_TOOLKIT */
1313 unbind_to (count
, Qnil
);
1314 set_buffer_internal_1 (prev
);
1321 /* Redisplay WINDOW and its subwindows and siblings. */
1324 redisplay_windows (window
)
1327 for (; !NILP (window
); window
= XWINDOW (window
)->next
)
1328 redisplay_window (window
, 0);
1331 /* Redisplay window WINDOW and its subwindows. */
1334 redisplay_window (window
, just_this_one
)
1338 register struct window
*w
= XWINDOW (window
);
1339 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1341 register int lpoint
= PT
;
1342 struct buffer
*old
= current_buffer
;
1343 register int width
= window_internal_width (w
) - 1;
1344 register int startp
;
1345 register int hscroll
= XINT (w
->hscroll
);
1346 struct position pos
;
1349 int update_mode_line
;
1350 struct Lisp_Vector
*dp
= window_display_table (w
);
1352 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1354 /* If this is a combination window, do its children; that's all. */
1356 if (!NILP (w
->vchild
))
1358 redisplay_windows (w
->vchild
);
1361 if (!NILP (w
->hchild
))
1363 redisplay_windows (w
->hchild
);
1366 if (NILP (w
->buffer
))
1369 height
= window_internal_height (w
);
1370 update_mode_line
= (!NILP (w
->update_mode_line
) || update_mode_lines
);
1371 if (XBUFFER (w
->buffer
)->clip_changed
)
1372 update_mode_line
= 1;
1374 if (MINI_WINDOW_P (w
))
1376 if (w
== XWINDOW (echo_area_window
) && echo_area_glyphs
)
1377 /* We've already displayed the echo area glyphs in this window. */
1378 goto finish_scroll_bars
;
1379 else if (w
!= XWINDOW (minibuf_window
))
1381 /* This is a minibuffer, but it's not the currently active one,
1383 int vpos
= XFASTINT (w
->top
);
1386 for (i
= 0; i
< height
; i
++)
1388 get_display_line (f
, vpos
+ i
, 0);
1389 display_string (w
, vpos
+ i
, "", 0, 0, 0, 1, 0, width
);
1392 goto finish_scroll_bars
;
1396 /* Otherwise set up data on this window; select its buffer and point value */
1398 if (update_mode_line
)
1399 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1401 set_buffer_temp (XBUFFER (w
->buffer
));
1405 /* If %c is in mode line, update it if needed. */
1406 if (!NILP (w
->column_number_displayed
)
1407 /* This alternative quickly identifies a common case
1408 where no change is needed. */
1409 && !(PT
== XFASTINT (w
->last_point
)
1410 && XFASTINT (w
->last_modified
) >= MODIFF
)
1411 && XFASTINT (w
->column_number_displayed
) != current_column ())
1412 update_mode_line
= 1;
1414 /* Count number of windows showing the selected buffer.
1415 An indirect buffer counts as its base buffer. */
1419 struct buffer
*current_base
, *window_base
;
1420 current_base
= current_buffer
;
1421 window_base
= XBUFFER (XWINDOW (selected_window
)->buffer
);
1422 if (current_base
->base_buffer
)
1423 current_base
= current_base
->base_buffer
;
1424 if (window_base
->base_buffer
)
1425 window_base
= window_base
->base_buffer
;
1426 if (current_base
== window_base
)
1430 /* POINT refers normally to the selected window.
1431 For any other window, set up appropriate value. */
1433 if (!EQ (window
, selected_window
))
1435 int new_pt
= marker_position (w
->pointm
);
1439 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1441 else if (new_pt
> (ZV
- 1))
1444 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1446 /* We don't use SET_PT so that the point-motion hooks don't run. */
1447 BUF_PT (current_buffer
) = new_pt
;
1450 /* If any of the character widths specified in the display table
1451 have changed, invalidate the width run cache. It's true that this
1452 may be a bit late to catch such changes, but the rest of
1453 redisplay goes (non-fatally) haywire when the display table is
1454 changed, so why should we worry about doing any better? */
1455 if (current_buffer
->width_run_cache
)
1457 struct Lisp_Vector
*disptab
= buffer_display_table ();
1459 if (! disptab_matches_widthtab (disptab
,
1460 XVECTOR (current_buffer
->width_table
)))
1462 invalidate_region_cache (current_buffer
,
1463 current_buffer
->width_run_cache
,
1465 recompute_width_table (current_buffer
, disptab
);
1469 /* If window-start is screwed up, choose a new one. */
1470 if (XMARKER (w
->start
)->buffer
!= current_buffer
)
1473 startp
= marker_position (w
->start
);
1475 /* Handle case where place to start displaying has been specified,
1476 unless the specified location is outside the accessible range. */
1477 if (!NILP (w
->force_start
))
1479 /* Forget any recorded base line for line number display. */
1480 w
->base_line_number
= Qnil
;
1481 /* Redisplay the mode line. Select the buffer properly for that. */
1482 if (!update_mode_line
)
1484 set_buffer_temp (old
);
1485 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1486 update_mode_line
= 1;
1487 w
->update_mode_line
= Qt
;
1489 w
->force_start
= Qnil
;
1490 XSETFASTINT (w
->last_modified
, 0);
1491 if (startp
< BEGV
) startp
= BEGV
;
1492 if (startp
> ZV
) startp
= ZV
;
1493 try_window (window
, startp
);
1494 if (cursor_vpos
< 0)
1496 /* If point does not appear, move point so it does appear */
1497 pos
= *compute_motion (startp
, 0,
1498 (((EQ (window
, minibuf_window
)
1500 ? minibuf_prompt_width
: 0)
1501 + (hscroll
? 1 - hscroll
: 0)),
1504 - (1 << (SHORTBITS
- 1)),
1505 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1506 BUF_PT (current_buffer
) = pos
.bufpos
;
1507 if (w
!= XWINDOW (selected_window
))
1508 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
1511 if (current_buffer
== old
)
1513 FRAME_CURSOR_X (f
) = (XFASTINT (w
->left
)
1514 + minmax (0, pos
.hpos
, width
));
1515 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1517 /* If we are highlighting the region,
1518 then we just changed the region, so redisplay to show it. */
1519 if (!NILP (Vtransient_mark_mode
)
1520 && !NILP (current_buffer
->mark_active
))
1522 cancel_my_columns (XWINDOW (window
));
1523 try_window (window
, startp
);
1529 /* Handle case where text has not changed, only point,
1530 and it has not moved off the frame */
1532 /* This code is not used for minibuffer for the sake of
1533 the case of redisplaying to replace an echo area message;
1534 since in that case the minibuffer contents per se are usually unchanged.
1535 This code is of no real use in the minibuffer since
1536 the handling of this_line_bufpos, etc.,
1537 in redisplay handles the same cases. */
1539 if (XFASTINT (w
->last_modified
) >= MODIFF
1540 && PT
>= startp
&& !current_buffer
->clip_changed
1541 && (just_this_one
|| XFASTINT (w
->width
) == FRAME_WIDTH (f
))
1542 /* If force-mode-line-update was called, really redisplay;
1543 that's how redisplay is forced after e.g. changing
1544 buffer-invisibility-spec. */
1545 && NILP (w
->update_mode_line
)
1546 /* Can't use this case if highlighting a region. */
1547 && !(!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1548 && NILP (w
->region_showing
)
1549 /* If end pos is out of date, scroll bar and percentage will be wrong */
1550 && INTEGERP (w
->window_end_vpos
)
1551 && XFASTINT (w
->window_end_vpos
) < XFASTINT (w
->height
)
1552 && !EQ (window
, minibuf_window
))
1554 pos
= *compute_motion (startp
, 0, (hscroll
? 1 - hscroll
: 0), 0,
1555 PT
, height
, 0, width
, hscroll
,
1556 pos_tab_offset (w
, startp
), w
);
1558 if (pos
.vpos
< height
)
1560 /* Ok, point is still on frame */
1561 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
1563 /* These variables are supposed to be origin 1 */
1564 FRAME_CURSOR_X (f
) = (XFASTINT (w
->left
)
1565 + minmax (0, pos
.hpos
, width
));
1566 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1568 /* This doesn't do the trick, because if a window to the right of
1569 this one must be redisplayed, this does nothing because there
1570 is nothing in DesiredFrame yet, and then the other window is
1571 redisplayed, making likes that are empty in this window's columns.
1572 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1573 preserve_my_columns (w);
1577 /* Don't bother trying redisplay with same start;
1578 we already know it will lose */
1580 /* If current starting point was originally the beginning of a line
1581 but no longer is, find a new starting point. */
1582 else if (!NILP (w
->start_at_line_beg
)
1584 || FETCH_CHAR (startp
- 1) == '\n'))
1588 else if (just_this_one
&& !MINI_WINDOW_P (w
)
1590 && XFASTINT (w
->last_modified
)
1591 /* or else vmotion on first line won't work. */
1592 && ! NILP (w
->start_at_line_beg
)
1593 && ! EQ (w
->window_end_valid
, Qnil
)
1594 && do_id
&& !current_buffer
->clip_changed
1595 && !blank_end_of_window
1596 && XFASTINT (w
->width
) == FRAME_WIDTH (f
)
1597 /* Can't use this case if highlighting a region. */
1598 && !(!NILP (Vtransient_mark_mode
)
1599 && !NILP (current_buffer
->mark_active
))
1600 /* Don't use try_window_id if newline
1601 doesn't display as the end of a line. */
1602 && !(dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, '\n')))
1603 && NILP (w
->region_showing
)
1604 && EQ (last_arrow_position
, Voverlay_arrow_position
)
1605 && EQ (last_arrow_string
, Voverlay_arrow_string
)
1606 && (tem
= try_window_id (FRAME_SELECTED_WINDOW (f
)))
1609 /* tem > 0 means success. tem == -1 means choose new start.
1610 tem == -2 means try again with same start,
1611 and nothing but whitespace follows the changed stuff.
1612 tem == 0 means try again with same start. */
1616 else if (startp
>= BEGV
&& startp
<= ZV
1617 /* Avoid starting display at end of buffer! */
1618 && (startp
< ZV
|| startp
== BEGV
1619 || (XFASTINT (w
->last_modified
) >= MODIFF
)))
1621 /* Try to redisplay starting at same place as before */
1622 /* If point has not moved off frame, accept the results */
1623 try_window (window
, startp
);
1624 if (cursor_vpos
>= 0)
1626 if (!just_this_one
|| current_buffer
->clip_changed
1627 || beg_unchanged
< startp
)
1628 /* Forget any recorded base line for line number display. */
1629 w
->base_line_number
= Qnil
;
1633 cancel_my_columns (w
);
1636 XSETFASTINT (w
->last_modified
, 0);
1637 /* Redisplay the mode line. Select the buffer properly for that. */
1638 if (!update_mode_line
)
1640 set_buffer_temp (old
);
1641 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1642 update_mode_line
= 1;
1643 w
->update_mode_line
= Qt
;
1646 /* Try to scroll by specified few lines */
1648 if (scroll_step
&& !current_buffer
->clip_changed
)
1652 pos
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), scroll_step
, w
);
1653 if (pos
.vpos
>= height
)
1657 pos
= *vmotion (startp
, (PT
< startp
? - scroll_step
: scroll_step
), w
);
1659 if (PT
>= pos
.bufpos
)
1661 try_window (window
, pos
.bufpos
);
1662 if (cursor_vpos
>= 0)
1664 if (!just_this_one
|| current_buffer
->clip_changed
1665 || beg_unchanged
< startp
)
1666 /* Forget any recorded base line for line number display. */
1667 w
->base_line_number
= Qnil
;
1671 cancel_my_columns (w
);
1676 /* Finally, just choose place to start which centers point */
1679 /* Forget any previously recorded base line for line number display. */
1680 w
->base_line_number
= Qnil
;
1682 pos
= *vmotion (PT
, - (height
/ 2), w
);
1683 try_window (window
, pos
.bufpos
);
1685 startp
= marker_position (w
->start
);
1686 w
->start_at_line_beg
1687 = (startp
== BEGV
|| FETCH_CHAR (startp
- 1) == '\n') ? Qt
: Qnil
;
1690 if ((update_mode_line
1691 /* If window not full width, must redo its mode line
1692 if the window to its side is being redone */
1693 || (!just_this_one
&& width
< FRAME_WIDTH (f
) - 1)
1694 || INTEGERP (w
->base_line_pos
)
1695 || (!NILP (w
->column_number_displayed
)
1696 && XFASTINT (w
->column_number_displayed
) != current_column ()))
1697 && height
!= XFASTINT (w
->height
))
1698 display_mode_line (w
);
1699 if (! line_number_displayed
1700 && ! BUFFERP (w
->base_line_pos
))
1702 w
->base_line_pos
= Qnil
;
1703 w
->base_line_number
= Qnil
;
1706 /* When we reach a frame's selected window, redo the frame's menu bar. */
1707 if (update_mode_line
1708 #ifdef USE_X_TOOLKIT
1709 && FRAME_EXTERNAL_MENU_BAR (f
)
1711 && FRAME_MENU_BAR_LINES (f
) > 0
1713 && EQ (FRAME_SELECTED_WINDOW (f
), window
))
1714 display_menu_bar (w
);
1717 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1719 int start
, end
, whole
;
1721 /* Calculate the start and end positions for the current window.
1722 At some point, it would be nice to choose between scrollbars
1723 which reflect the whole buffer size, with special markers
1724 indicating narrowing, and scrollbars which reflect only the
1727 Note that minibuffers sometimes aren't displaying any text. */
1728 if (! MINI_WINDOW_P (w
)
1729 || (w
== XWINDOW (minibuf_window
) && ! echo_area_glyphs
))
1732 start
= marker_position (w
->start
) - BEGV
;
1733 /* I don't think this is guaranteed to be right. For the
1734 moment, we'll pretend it is. */
1735 end
= (Z
- XINT (w
->window_end_pos
)) - BEGV
;
1737 if (end
< start
) end
= start
;
1738 if (whole
< (end
- start
)) whole
= end
- start
;
1741 start
= end
= whole
= 0;
1743 /* Indicate what this scroll bar ought to be displaying now. */
1744 (*set_vertical_scroll_bar_hook
) (w
, end
- start
, whole
, start
);
1746 /* Note that we actually used the scroll bar attached to this window,
1747 so it shouldn't be deleted at the end of redisplay. */
1748 (*redeem_scroll_bar_hook
) (w
);
1751 BUF_PT (current_buffer
) = opoint
;
1752 if (update_mode_line
)
1753 set_buffer_internal_1 (old
);
1755 set_buffer_temp (old
);
1756 BUF_PT (current_buffer
) = lpoint
;
1759 /* Do full redisplay on one window, starting at position `pos'. */
1762 try_window (window
, pos
)
1766 register struct window
*w
= XWINDOW (window
);
1767 register int height
= window_internal_height (w
);
1768 register int vpos
= XFASTINT (w
->top
);
1769 register int last_text_vpos
= vpos
;
1770 int tab_offset
= pos_tab_offset (w
, pos
);
1771 FRAME_PTR f
= XFRAME (w
->frame
);
1772 int width
= window_internal_width (w
) - 1;
1773 struct position val
;
1775 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1777 overlay_arrow_seen
= 0;
1778 zv_strings_seen
= 0;
1779 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
1781 while (--height
>= 0)
1783 val
= *display_text_line (w
, pos
, vpos
, val
.hpos
, tab_offset
);
1784 tab_offset
+= width
;
1785 /* For the first line displayed, display_text_line
1786 subtracts the prompt width from the tab offset.
1787 But it does not affect the value of our variable tab_offset.
1788 So we do the subtraction again,
1789 for the sake of continuation lines of that first line. */
1790 if (MINI_WINDOW_P (w
) && vpos
== XFASTINT (w
->top
))
1791 tab_offset
-= minibuf_prompt_width
;
1793 if (val
.vpos
) tab_offset
= 0;
1795 if (pos
!= val
.bufpos
)
1798 #ifdef USE_TEXT_PROPERTIES
1799 Lisp_Object invis_prop
;
1800 invis_prop
= Fget_char_property (val
.bufpos
-1, Qinvisible
, window
);
1801 invis
= TEXT_PROP_MEANS_INVISIBLE (invis_prop
);
1805 /* Next line, unless prev line ended in end of buffer with no cr */
1807 && (FETCH_CHAR (val
.bufpos
- 1) != '\n' || invis
));
1812 /* If last line is continued in middle of character,
1813 include the split character in the text considered on the frame */
1814 if (val
.hpos
< (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
1817 /* If bottom just moved off end of frame, change mode line percentage. */
1818 if (XFASTINT (w
->window_end_pos
) == 0
1820 w
->update_mode_line
= Qt
;
1822 /* Say where last char on frame will be, once redisplay is finished. */
1823 XSETFASTINT (w
->window_end_pos
, Z
- pos
);
1824 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
- XFASTINT (w
->top
));
1825 /* But that is not valid info until redisplay finishes. */
1826 w
->window_end_valid
= Qnil
;
1829 /* Try to redisplay when buffer is modified locally,
1830 computing insert/delete line to preserve text outside
1831 the bounds of the changes.
1832 Return 1 if successful, 0 if if cannot tell what to do,
1833 or -1 to tell caller to find a new window start,
1834 or -2 to tell caller to do normal redisplay with same window start. */
1837 try_window_id (window
)
1841 register struct window
*w
= XWINDOW (window
);
1842 register int height
= window_internal_height (w
);
1843 FRAME_PTR f
= XFRAME (w
->frame
);
1844 int top
= XFASTINT (w
->top
);
1845 int start
= marker_position (w
->start
);
1846 int width
= window_internal_width (w
) - 1;
1847 int hscroll
= XINT (w
->hscroll
);
1848 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1851 register int i
, tem
;
1852 int last_text_vpos
= 0;
1854 int selective
= (INTEGERP (current_buffer
->selective_display
)
1855 ? XINT (current_buffer
->selective_display
)
1856 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1858 struct position val
, bp
, ep
, xp
, pp
;
1859 int scroll_amount
= 0;
1861 int tab_offset
, epto
;
1863 if (GPT
- BEG
< beg_unchanged
)
1864 beg_unchanged
= GPT
- BEG
;
1865 if (Z
- GPT
< end_unchanged
)
1866 end_unchanged
= Z
- GPT
;
1868 if (beg_unchanged
+ BEG
< start
)
1869 return 0; /* Give up if changes go above top of window */
1871 /* Find position before which nothing is changed. */
1872 bp
= *compute_motion (start
, 0, lmargin
, 0,
1873 min (ZV
, beg_unchanged
+ BEG
), height
, 0,
1874 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1875 if (bp
.vpos
>= height
)
1879 /* All changes are below the frame, and point is on the frame.
1880 We don't need to change the frame at all.
1881 But we need to update window_end_pos to account for
1882 any change in buffer size. */
1883 bp
= *compute_motion (start
, 0, lmargin
, 0,
1885 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1886 XSETFASTINT (w
->window_end_vpos
, height
);
1887 XSETFASTINT (w
->window_end_pos
, Z
- bp
.bufpos
);
1895 /* Find beginning of that frame line. Must display from there. */
1896 bp
= *vmotion (bp
.bufpos
, 0, w
);
1904 /* If about to start displaying at the beginning of a continuation line,
1905 really start with previous frame line, in case it was not
1906 continued when last redisplayed */
1907 if ((bp
.contin
&& bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0)
1909 /* Likewise if we have to worry about selective display. */
1910 (selective
> 0 && bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0))
1912 bp
= *vmotion (bp
.bufpos
, -1, w
);
1917 if (bp
.contin
&& bp
.hpos
!= lmargin
)
1919 val
.hpos
= bp
.prevhpos
- width
+ lmargin
;
1926 /* Find first visible newline after which no more is changed. */
1927 tem
= find_next_newline (Z
- max (end_unchanged
, Z
- ZV
), 1);
1929 while (tem
< ZV
- 1 && (indented_beyond_p (tem
, selective
)))
1930 tem
= find_next_newline (tem
, 1);
1932 /* Compute the cursor position after that newline. */
1933 ep
= *compute_motion (pos
, vpos
, val
.hpos
, did_motion
, tem
,
1934 height
, - (1 << (SHORTBITS
- 1)),
1935 width
, hscroll
, pos_tab_offset (w
, bp
.bufpos
), w
);
1937 /* If changes reach past the text available on the frame,
1938 just display rest of frame. */
1939 if (ep
.bufpos
> Z
- XFASTINT (w
->window_end_pos
))
1942 stop_vpos
= ep
.vpos
;
1944 /* If no newline before ep, the line ep is on includes some changes
1945 that must be displayed. Make sure we don't stop before it. */
1946 /* Also, if changes reach all the way until ep.bufpos,
1947 it is possible that something was deleted after the
1948 newline before it, so the following line must be redrawn. */
1949 if (stop_vpos
== ep
.vpos
1950 && (ep
.bufpos
== BEGV
1951 || FETCH_CHAR (ep
.bufpos
- 1) != '\n'
1952 || ep
.bufpos
== Z
- end_unchanged
))
1953 stop_vpos
= ep
.vpos
+ 1;
1956 overlay_arrow_seen
= 0;
1957 zv_strings_seen
= 0;
1959 /* If changes do not reach to bottom of window,
1960 figure out how much to scroll the rest of the window */
1961 if (stop_vpos
< height
)
1963 /* Now determine how far up or down the rest of the window has moved */
1964 epto
= pos_tab_offset (w
, ep
.bufpos
);
1965 xp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
1966 Z
- XFASTINT (w
->window_end_pos
),
1967 10000, 0, width
, hscroll
, epto
, w
);
1968 scroll_amount
= xp
.vpos
- XFASTINT (w
->window_end_vpos
);
1970 /* Is everything on frame below the changes whitespace?
1971 If so, no scrolling is really necessary. */
1972 for (i
= ep
.bufpos
; i
< xp
.bufpos
; i
++)
1974 tem
= FETCH_CHAR (i
);
1975 if (tem
!= ' ' && tem
!= '\n' && tem
!= '\t')
1981 XSETFASTINT (w
->window_end_vpos
,
1982 XFASTINT (w
->window_end_vpos
) + scroll_amount
);
1984 /* Before doing any scrolling, verify that point will be on frame. */
1985 if (PT
> ep
.bufpos
&& !(PT
<= xp
.bufpos
&& xp
.bufpos
< height
))
1987 if (PT
<= xp
.bufpos
)
1989 pp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
1990 PT
, height
, - (1 << (SHORTBITS
- 1)),
1991 width
, hscroll
, epto
, w
);
1995 pp
= *compute_motion (xp
.bufpos
, xp
.vpos
, xp
.hpos
, 1,
1996 PT
, height
, - (1 << (SHORTBITS
- 1)),
1998 pos_tab_offset (w
, xp
.bufpos
), w
);
2000 if (pp
.bufpos
< PT
|| pp
.vpos
== height
)
2002 cursor_vpos
= pp
.vpos
+ top
;
2003 cursor_hpos
= XFASTINT (w
->left
) + minmax (0, pp
.hpos
, width
);
2006 if (stop_vpos
- scroll_amount
>= height
2007 || ep
.bufpos
== xp
.bufpos
)
2009 if (scroll_amount
< 0)
2010 stop_vpos
-= scroll_amount
;
2012 /* In this path, we have altered window_end_vpos
2013 and not left it negative.
2014 We must make sure that, in case display is preempted
2015 before the frame changes to reflect what we do here,
2016 further updates will not come to try_window_id
2017 and assume the frame and window_end_vpos match. */
2018 blank_end_of_window
= 1;
2020 else if (!scroll_amount
)
2022 /* Even if we don't need to scroll, we must adjust the
2023 charstarts of subsequent lines (that we won't redisplay)
2024 according to the amount of text inserted or deleted. */
2025 int oldpos
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2026 int adjust
= ep
.bufpos
- oldpos
;
2027 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1, adjust
);
2029 else if (bp
.bufpos
== Z
- end_unchanged
)
2031 /* If reprinting everything is nearly as fast as scrolling,
2032 don't bother scrolling. Can happen if lines are short. */
2033 if (scroll_cost (f
, bp
.vpos
+ top
- scroll_amount
,
2034 top
+ height
- max (0, scroll_amount
),
2036 > xp
.bufpos
- bp
.bufpos
- 20)
2037 /* Return "try normal display with same window-start."
2038 Too bad we can't prevent further scroll-thinking. */
2040 /* If pure deletion, scroll up as many lines as possible.
2041 In common case of killing a line, this can save the
2042 following line from being overwritten by scrolling
2043 and therefore having to be redrawn. */
2044 tem
= scroll_frame_lines (f
, bp
.vpos
+ top
- scroll_amount
,
2045 top
+ height
- max (0, scroll_amount
),
2046 scroll_amount
, bp
.bufpos
);
2051 /* scroll_frame_lines did not properly adjust subsequent
2052 lines' charstarts in the case where the text of the
2053 screen line at bp.vpos has changed.
2054 (This can happen in a deletion that ends in mid-line.)
2055 To adjust properly, we need to make things constent at
2057 So do a second adjust to make that happen.
2058 Note that stop_vpos >= ep.vpos, so it is sufficient
2059 to update the charstarts for lines at ep.vpos and below. */
2061 = FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2062 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1,
2063 ep
.bufpos
- oldstart
);
2066 else if (scroll_amount
)
2068 /* If reprinting everything is nearly as fast as scrolling,
2069 don't bother scrolling. Can happen if lines are short. */
2070 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2071 overestimate of cost of reprinting, since xp.bufpos
2072 would end up below the bottom of the window. */
2073 if (scroll_cost (f
, ep
.vpos
+ top
- scroll_amount
,
2074 top
+ height
- max (0, scroll_amount
),
2076 > xp
.bufpos
- ep
.bufpos
- 20)
2077 /* Return "try normal display with same window-start."
2078 Too bad we can't prevent further scroll-thinking. */
2080 tem
= scroll_frame_lines (f
, ep
.vpos
+ top
- scroll_amount
,
2081 top
+ height
- max (0, scroll_amount
),
2082 scroll_amount
, ep
.bufpos
);
2083 if (!tem
) stop_vpos
= height
;
2087 /* In any case, do not display past bottom of window */
2088 if (stop_vpos
>= height
)
2094 /* Handle case where pos is before w->start --
2095 can happen if part of line had been clipped and is not clipped now */
2096 if (vpos
== 0 && pos
< marker_position (w
->start
))
2097 Fset_marker (w
->start
, make_number (pos
), Qnil
);
2099 /* Redisplay the lines where the text was changed */
2100 last_text_vpos
= vpos
;
2101 tab_offset
= pos_tab_offset (w
, pos
);
2102 /* If we are starting display in mid-character, correct tab_offset
2103 to account for passing the line that that character really starts in. */
2104 if (val
.hpos
< lmargin
)
2105 tab_offset
+= width
;
2106 while (vpos
< stop_vpos
)
2108 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
2109 tab_offset
+= width
;
2110 if (val
.vpos
) tab_offset
= 0;
2111 if (pos
!= val
.bufpos
)
2113 /* Next line, unless prev line ended in end of buffer with no cr */
2114 = vpos
- (val
.vpos
&& FETCH_CHAR (val
.bufpos
- 1) != '\n');
2118 /* There are two cases:
2119 1) we have displayed down to the bottom of the window
2120 2) we have scrolled lines below stop_vpos by scroll_amount */
2124 /* If last line is continued in middle of character,
2125 include the split character in the text considered on the frame */
2126 if (val
.hpos
< lmargin
)
2128 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
);
2129 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2132 /* If scrolling made blank lines at window bottom,
2133 redisplay to fill those lines */
2134 if (scroll_amount
< 0)
2136 /* Don't consider these lines for general-purpose scrolling.
2137 That will save time in the scrolling computation. */
2138 FRAME_SCROLL_BOTTOM_VPOS (f
) = xp
.vpos
;
2143 vpos
= height
+ scroll_amount
;
2144 else if (xp
.contin
&& xp
.hpos
!= lmargin
)
2146 val
.hpos
= xp
.prevhpos
- width
+ lmargin
;
2150 blank_end_of_window
= 1;
2151 tab_offset
= pos_tab_offset (w
, pos
);
2152 /* If we are starting display in mid-character, correct tab_offset
2153 to account for passing the line that that character starts in. */
2154 if (val
.hpos
< lmargin
)
2155 tab_offset
+= width
;
2157 while (vpos
< height
)
2159 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
2160 tab_offset
+= width
;
2161 if (val
.vpos
) tab_offset
= 0;
2165 /* Here is a case where display_text_line sets cursor_vpos wrong.
2166 Make it be fixed up, below. */
2172 /* If bottom just moved off end of frame, change mode line percentage. */
2173 if (XFASTINT (w
->window_end_pos
) == 0
2175 w
->update_mode_line
= Qt
;
2177 /* Attempt to adjust end-of-text positions to new bottom line */
2180 delta
= height
- xp
.vpos
;
2182 || (delta
> 0 && xp
.bufpos
<= ZV
)
2183 || (delta
== 0 && xp
.hpos
))
2185 val
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), delta
, w
);
2186 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2187 XSETFASTINT (w
->window_end_vpos
,
2188 XFASTINT (w
->window_end_vpos
) + val
.vpos
);
2192 w
->window_end_valid
= Qnil
;
2194 /* If point was not in a line that was displayed, find it */
2195 if (cursor_vpos
< 0)
2198 val
= *compute_motion (start
, 0, lmargin
, 0, PT
, 10000, 10000,
2199 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2200 /* Admit failure if point is off frame now */
2201 if (val
.vpos
>= height
)
2203 for (vpos
= 0; vpos
< height
; vpos
++)
2204 cancel_line (vpos
+ top
, f
);
2207 cursor_vpos
= val
.vpos
+ top
;
2208 cursor_hpos
= XFASTINT (w
->left
) + minmax (0, val
.hpos
, width
);
2211 FRAME_CURSOR_X (f
) = cursor_hpos
;
2212 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2216 val
= *compute_motion (start
, 0, lmargin
, 0, ZV
,
2217 height
, - (1 << (SHORTBITS
- 1)),
2218 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2219 if (val
.vpos
!= XFASTINT (w
->window_end_vpos
))
2221 if (XFASTINT (w
->window_end_pos
)
2229 /* Mark a section of BUF as modified, but only for the sake of redisplay.
2230 This is useful for recording changes to overlays.
2232 We increment the buffer's modification timestamp and set the
2233 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
2234 as if the region of text between START and END had been modified;
2235 the redisplay code will check this against the windows' timestamps,
2236 and redraw the appropriate area of the buffer.
2238 However, if the buffer is unmodified, we bump the last-save
2239 timestamp as well, so that incrementing the timestamp doesn't fool
2240 Emacs into thinking that the buffer's text has been modified.
2242 Tweaking the timestamps shouldn't hurt the first-modification
2243 timestamps recorded in the undo records; those values aren't
2244 written until just before a real text modification is made, so they
2245 will never catch the timestamp value just before this function gets
2249 redisplay_region (buf
, start
, end
)
2259 start
= end
; end
= temp
;
2262 /* If this is a buffer not in the selected window,
2263 we must do other windows. */
2264 if (buf
!= XBUFFER (XWINDOW (selected_window
)->buffer
))
2265 windows_or_buffers_changed
= 1;
2266 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
2267 else if (buf
!= current_buffer
)
2268 windows_or_buffers_changed
= 1;
2269 /* If multiple windows show this buffer, we must do other windows. */
2270 else if (buffer_shared
> 1)
2271 windows_or_buffers_changed
= 1;
2274 if (unchanged_modified
== MODIFF
)
2276 beg_unchanged
= start
- BEG
;
2277 end_unchanged
= Z
- end
;
2281 if (Z
- end
< end_unchanged
)
2282 end_unchanged
= Z
- end
;
2283 if (start
- BEG
< beg_unchanged
)
2284 beg_unchanged
= start
- BEG
;
2288 /* Increment the buffer's time stamp, but also increment the save
2289 and autosave timestamps, so as not to screw up that timekeeping. */
2290 if (BUF_MODIFF (buf
) == BUF_SAVE_MODIFF (buf
))
2291 BUF_SAVE_MODIFF (buf
)++;
2292 if (BUF_MODIFF (buf
) == buf
->auto_save_modified
)
2293 buf
->auto_save_modified
++;
2295 BUF_MODIFF (buf
) ++;
2299 /* Copy LEN glyphs starting address FROM to the rope TO.
2300 But don't actually copy the parts that would come in before S.
2301 Value is TO, advanced past the copied data.
2302 F is the frame we are displaying in. */
2305 copy_part_of_rope (f
, to
, s
, from
, len
, face
)
2307 register GLYPH
*to
; /* Copy to here. */
2308 register GLYPH
*s
; /* Starting point. */
2309 Lisp_Object
*from
; /* Data to copy. */
2311 int face
; /* Face to apply to glyphs which don't specify one. */
2314 register Lisp_Object
*fp
= from
;
2315 /* These cache the results of the last call to compute_glyph_face. */
2317 int last_merged
= 0;
2320 if (! FRAME_TERMCAP_P (f
))
2323 int glyph
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2326 if (FAST_GLYPH_FACE (glyph
) == 0)
2327 /* If GLYPH has no face code, use FACE. */
2329 else if (FAST_GLYPH_FACE (glyph
) == last_code
)
2330 /* If it's same as previous glyph, use same result. */
2331 facecode
= last_merged
;
2334 /* Merge this glyph's face and remember the result. */
2335 last_code
= FAST_GLYPH_FACE (glyph
);
2336 last_merged
= facecode
= compute_glyph_face (f
, last_code
, face
);
2340 *to
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), facecode
);
2348 if (to
>= s
) *to
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2355 /* Correct a glyph by replacing its specified user-level face code
2356 with a displayable computed face code. */
2359 fix_glyph (f
, glyph
, cface
)
2365 if (! FRAME_TERMCAP_P (f
))
2367 if (FAST_GLYPH_FACE (glyph
) != 0)
2368 cface
= compute_glyph_face (f
, FAST_GLYPH_FACE (glyph
), cface
);
2369 glyph
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), cface
);
2375 /* Display one line of window W, starting at position START in W's buffer.
2377 Display starting at horizontal position HPOS, expressed relative to
2378 W's left edge. In situations where the text at START shouldn't
2379 start at the left margin (i.e. when the window is hscrolled, or
2380 we're continuing a line which left off in the midst of a
2381 multi-column character), HPOS should be negative; we throw away
2382 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2385 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2387 Display on position VPOS on the frame. It is origin 0, relative to
2388 the top of the frame, not W.
2390 Returns a STRUCT POSITION giving character to start next line with
2391 and where to display it, including a zero or negative hpos.
2392 The vpos field is not really a vpos; it is 1 unless the line is continued */
2394 struct position val_display_text_line
;
2396 static struct position
*
2397 display_text_line (w
, start
, vpos
, hpos
, taboffset
)
2404 register int pos
= start
;
2408 register unsigned char *p
;
2410 register GLYPH
*leftmargin
;
2411 register GLYPH
*p1prev
;
2412 register GLYPH
*p1start
;
2415 FRAME_PTR f
= XFRAME (w
->frame
);
2416 int tab_width
= XINT (current_buffer
->tab_width
);
2417 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
2418 int width
= window_internal_width (w
) - 1;
2419 struct position val
;
2422 int last_invis_skip
= 0;
2423 Lisp_Object last_invis_prop
;
2424 int hscroll
= XINT (w
->hscroll
);
2425 int truncate
= (hscroll
2426 || (truncate_partial_width_windows
2427 && XFASTINT (w
->width
) < FRAME_WIDTH (f
))
2428 || !NILP (current_buffer
->truncate_lines
));
2430 /* 1 if we should highlight the region. */
2431 int highlight_region
2432 = !NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
);
2433 int region_beg
, region_end
;
2435 int selective
= (INTEGERP (current_buffer
->selective_display
)
2436 ? XINT (current_buffer
->selective_display
)
2437 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2438 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
2439 register struct Lisp_Vector
*dp
= window_display_table (w
);
2441 Lisp_Object default_invis_vector
[3];
2442 /* Number of characters of ellipsis to display after an invisible line
2443 if it calls for an ellipsis.
2444 Note that this value can be nonzero regardless of whether
2445 selective display is enabled--you must check that separately. */
2447 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2448 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
2449 : !NILP (current_buffer
->selective_display_ellipses
) ? 3 : 0);
2450 /* This is the sequence of Lisp objects to display
2451 when there are invisible lines. */
2452 Lisp_Object
*invis_vector_contents
2453 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2454 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->contents
2455 : default_invis_vector
);
2457 GLYPH truncator
= (dp
== 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp
))
2458 ? '$' : XINT (DISP_TRUNC_GLYPH (dp
)));
2459 GLYPH continuer
= (dp
== 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp
))
2460 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp
)));
2462 /* The next buffer location at which the face should change, due
2463 to overlays or text property changes. */
2464 int next_face_change
;
2466 /* The next location where the `invisible' property changes, or an
2467 overlay starts or ends. */
2470 /* The face we're currently using. */
2471 int current_face
= 0;
2474 XSETFASTINT (default_invis_vector
[2], '.');
2475 default_invis_vector
[0] = default_invis_vector
[1] = default_invis_vector
[2];
2477 hpos
+= XFASTINT (w
->left
);
2478 get_display_line (f
, vpos
, XFASTINT (w
->left
));
2479 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
2481 /* Show where to highlight the region. */
2482 if (highlight_region
&& XMARKER (current_buffer
->mark
)->buffer
!= 0
2483 /* Maybe highlight only in selected window. */
2484 && (highlight_nonselected_windows
2485 || w
== XWINDOW (selected_window
)))
2487 region_beg
= marker_position (current_buffer
->mark
);
2488 if (PT
< region_beg
)
2490 region_end
= region_beg
;
2495 w
->region_showing
= Qt
;
2498 region_beg
= region_end
= -1;
2500 if (MINI_WINDOW_P (w
)
2502 && vpos
== XFASTINT (w
->top
))
2504 if (! NILP (minibuf_prompt
))
2506 minibuf_prompt_width
2507 = (display_string (w
, vpos
, XSTRING (minibuf_prompt
)->data
,
2508 XSTRING (minibuf_prompt
)->size
, hpos
,
2509 /* Display a space if we truncate. */
2512 /* Truncate the prompt a little before the
2513 margin, so user input can at least start
2514 on the first line. */
2515 w
->width
> 10 ? w
->width
- 4 : -1)
2517 hpos
+= minibuf_prompt_width
;
2518 taboffset
-= minibuf_prompt_width
;
2521 minibuf_prompt_width
= 0;
2524 /* If we're hscrolled at all, use compute_motion to skip over any
2525 text off the left edge of the window. compute_motion may know
2526 tricks to do this faster than we can. */
2529 struct position
*left_edge
2530 = compute_motion (pos
, vpos
, hpos
, 0,
2532 width
, hscroll
, taboffset
, w
);
2534 /* Retrieve the buffer position and column provided by
2535 compute_motion. We can't assume that the column will be
2536 zero, because you may have multi-column characters crossing
2539 compute_motion may have moved us past the screen position we
2540 requested, if we hit a multi-column character, or the end of
2541 the line. If so, back up. */
2542 if (left_edge
->vpos
> vpos
2543 || left_edge
->hpos
> 0)
2545 pos
= left_edge
->bufpos
- 1;
2546 hpos
= left_edge
->prevhpos
;
2550 pos
= left_edge
->bufpos
;
2551 hpos
= left_edge
->hpos
;
2555 desired_glyphs
->bufp
[vpos
] = start
;
2556 p1
= desired_glyphs
->glyphs
[vpos
] + hpos
;
2558 charstart
= desired_glyphs
->charstarts
[vpos
] + hpos
;
2559 /* In case we don't ever write anything into it... */
2560 desired_glyphs
->charstarts
[vpos
][XFASTINT (w
->left
)] = -1;
2561 leftmargin
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
2562 endp
= leftmargin
+ width
;
2564 /* Arrange the overlays nicely for our purposes. Usually, we call
2565 display_text_line on only one line at a time, in which case this
2566 can't really hurt too much, or we call it on lines which appear
2567 one after another in the buffer, in which case all calls to
2568 recenter_overlay_lists but the first will be pretty cheap. */
2569 recenter_overlay_lists (current_buffer
, pos
);
2571 /* Loop generating characters.
2572 Stop at end of buffer, before newline,
2573 if reach or pass continuation column,
2574 or at face change. */
2576 next_face_change
= pos
;
2577 next_boundary
= pos
;
2584 while (pos
== next_boundary
)
2586 Lisp_Object position
, limit
, prop
, ww
;
2588 /* Display the overlay strings here, unless we're at ZV
2589 and have already displayed the appropriate strings
2590 on an earlier line. */
2591 if (pos
< ZV
|| !zv_strings_seen
++)
2595 ovlen
= overlay_strings (pos
, w
, &ovstr
);
2596 for (; ovlen
; ovlen
--, ovstr
++)
2598 if (p1
>= leftmargin
&& p1
< endp
)
2599 *p1
= MAKE_GLYPH (f
, *ovstr
, current_face
);
2604 /* Did we reach point? Record the cursor location. */
2605 if (pos
== PT
&& cursor_vpos
< 0)
2608 cursor_hpos
= p1
- leftmargin
;
2614 XSETFASTINT (position
, pos
);
2615 limit
= Fnext_overlay_change (position
);
2616 #ifdef USE_TEXT_PROPERTIES
2617 /* This is just an estimate to give reasonable
2618 performance; nothing should go wrong if it is too small. */
2619 if (XFASTINT (limit
) > pos
+ 50)
2620 XSETFASTINT (limit
, pos
+ 50);
2621 limit
= Fnext_single_property_change (position
, Qinvisible
,
2622 Fcurrent_buffer (), limit
);
2624 next_boundary
= XFASTINT (limit
);
2625 /* if the `invisible' property is set, we can skip to
2626 the next property change. */
2628 prop
= Fget_char_property (position
, Qinvisible
, ww
);
2629 if (TEXT_PROP_MEANS_INVISIBLE (prop
))
2631 if (pos
< PT
&& next_boundary
>= PT
)
2634 cursor_hpos
= p1
- leftmargin
;
2636 pos
= next_boundary
;
2637 last_invis_skip
= pos
;
2638 last_invis_prop
= prop
;
2642 /* Did we reach point? Record the cursor location. */
2643 if (pos
== PT
&& cursor_vpos
< 0)
2646 cursor_hpos
= p1
- leftmargin
;
2649 /* Did we hit the end of the visible region of the buffer?
2653 /* Update charstarts for the end of this line. */
2654 /* Do nothing if off the left edge or at the right edge. */
2655 if (p1
>= leftmargin
&& p1
+ 1 != endp
)
2657 int *p2x
= &charstart
[(p1
< leftmargin
2666 /* Did we hit a face change? Figure out what face we should
2667 use now. We also hit this the first time through the
2668 loop, to see what face we should start with. */
2669 if (pos
>= next_face_change
&& FRAME_X_P (f
))
2670 current_face
= compute_char_face (f
, w
, pos
,
2671 region_beg
, region_end
,
2672 &next_face_change
, pos
+ 50, 0);
2677 if (pos
< next_boundary
&& next_boundary
< pause
)
2678 pause
= next_boundary
;
2679 if (pos
< next_face_change
&& next_face_change
< pause
)
2680 pause
= next_face_change
;
2682 /* Wouldn't you hate to read the next line to someone over
2684 if (pos
< PT
&& PT
< pause
)
2686 if (pos
< GPT
&& GPT
< pause
)
2689 p
= &FETCH_CHAR (pos
);
2698 /* Let a display table override all standard display methods. */
2699 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
2701 p1
= copy_part_of_rope (f
, p1
, leftmargin
,
2702 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
2703 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
2706 else if (c
>= 040 && c
< 0177)
2708 if (p1
>= leftmargin
)
2709 *p1
= MAKE_GLYPH (f
, c
, current_face
);
2715 if (last_invis_skip
== pos
2716 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop
))
2720 && indented_beyond_p (pos
+ 1, selective
))
2723 pos
= find_next_newline (pos
+ 1, 1);
2724 if (FETCH_CHAR (pos
- 1) == '\n')
2727 if (invis
&& selective_rlen
> 0 && p1
>= leftmargin
)
2729 p1
+= selective_rlen
;
2730 if (p1
- leftmargin
> width
)
2732 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2733 (p1
- p1prev
), current_face
);
2736 /* Draw the face of the newline character as extending all the
2737 way to the end of the frame line. */
2740 if (p1
< leftmargin
)
2743 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2747 /* Update charstarts for the newline that ended this line. */
2748 /* Do nothing here for a char that's entirely off the left edge
2749 or if it starts at the right edge. */
2750 if (p1
>= leftmargin
&& p1prev
!= endp
)
2752 /* Store the newline's position into charstarts
2753 for the column where the newline starts.
2754 Store -1 for the rest of the glyphs it occupies. */
2755 int *p2x
= &charstart
[(p1prev
< leftmargin
2756 ? leftmargin
: p1prev
)
2758 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2771 if (p1
>= leftmargin
&& p1
< endp
)
2772 *p1
= MAKE_GLYPH (f
, ' ', current_face
);
2775 while ((p1
- leftmargin
+ taboffset
+ hscroll
- (hscroll
> 0))
2778 else if (c
== Ctl ('M') && selective
== -1)
2780 pos
= find_next_newline (pos
, 1);
2781 if (FETCH_CHAR (pos
- 1) == '\n')
2783 if (selective_rlen
> 0)
2785 p1
+= selective_rlen
;
2786 if (p1
- leftmargin
> width
)
2788 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2789 (p1
- p1prev
), current_face
);
2792 /* Draw the face of the newline character as extending all the
2793 way to the end of the frame line. */
2796 if (p1
< leftmargin
)
2799 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2803 /* Update charstarts for the ^M that ended this line. */
2804 /* Do nothing here for a char that's entirely off the left edge
2805 or if it starts at the right edge. */
2806 if (p1
>= leftmargin
&& p1prev
!= endp
)
2808 /* Store the newline's position into charstarts
2809 for the column where the newline starts.
2810 Store -1 for the rest of the glyphs it occupies. */
2811 int *p2x
= &charstart
[(p1prev
< leftmargin
2812 ? leftmargin
: p1prev
)
2814 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2822 else if (c
< 0200 && ctl_arrow
)
2824 if (p1
>= leftmargin
)
2825 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
2826 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
2829 if (p1
>= leftmargin
&& p1
< endp
)
2830 *p1
= MAKE_GLYPH (f
, c
^ 0100, current_face
);
2835 if (p1
>= leftmargin
)
2836 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
2837 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
2840 if (p1
>= leftmargin
&& p1
< endp
)
2841 *p1
= MAKE_GLYPH (f
, (c
>> 6) + '0', current_face
);
2843 if (p1
>= leftmargin
&& p1
< endp
)
2844 *p1
= MAKE_GLYPH (f
, (7 & (c
>> 3)) + '0', current_face
);
2846 if (p1
>= leftmargin
&& p1
< endp
)
2847 *p1
= MAKE_GLYPH (f
, (7 & c
) + '0', current_face
);
2854 /* Update charstarts for the character just output. */
2856 /* Do nothing here for a char that's entirely off the left edge. */
2857 if (p1
>= leftmargin
)
2859 /* Store the char's position into charstarts
2860 for the first glyph occupied by this char.
2861 Store -1 for the rest of the glyphs it occupies. */
2864 int *p2x
= &charstart
[(p1prev
< leftmargin
2865 ? leftmargin
: p1prev
)
2867 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2877 val
.hpos
= - XINT (w
->hscroll
);
2885 /* Store 0 in this charstart line for the positions where
2886 there is no character. But do leave what was recorded
2887 for the character that ended the line. */
2888 /* Add 1 in the endtest to compensate for the fact that ENDP was
2889 made from WIDTH, which is 1 less than the window's actual
2891 i
= p1
- p1start
+ 1;
2892 if (p1
< leftmargin
)
2893 i
+= leftmargin
- p1
;
2894 for (; i
< endp
- p1start
+ 1; i
++)
2897 /* Handle continuation in middle of a character */
2898 /* by backing up over it */
2901 /* Don't back up if we never actually displayed any text.
2902 This occurs when the minibuffer prompt takes up the whole line. */
2905 /* Start the next line with that same character */
2907 /* but at negative hpos, to skip the columns output on this line. */
2908 val
.hpos
+= p1prev
- endp
;
2911 /* Keep in this line everything up to the continuation column. */
2915 /* Finish deciding which character to start the next line on,
2916 and what hpos to start it at.
2917 Also set `lastpos' to the last position which counts as "on this line"
2918 for cursor-positioning. */
2922 if (FETCH_CHAR (pos
) == '\n')
2924 /* If stopped due to a newline, start next line after it */
2926 /* Check again for hidden lines, in case the newline occurred exactly
2927 at the right margin. */
2928 while (pos
< ZV
&& selective
> 0
2929 && indented_beyond_p (pos
, selective
))
2930 pos
= find_next_newline (pos
, 1);
2933 /* Stopped due to right margin of window */
2937 *p1
++ = fix_glyph (f
, truncator
, 0);
2938 /* Truncating => start next line after next newline,
2939 and point is on this line if it is before the newline,
2940 and skip none of first char of next line */
2942 pos
= find_next_newline (pos
, 1);
2943 while (pos
< ZV
&& selective
> 0
2944 && indented_beyond_p (pos
, selective
));
2945 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
2947 lastpos
= pos
- (FETCH_CHAR (pos
- 1) == '\n');
2951 *p1
++ = fix_glyph (f
, continuer
, 0);
2958 /* If point is at eol or in invisible text at eol,
2959 record its frame location now. */
2961 if (start
<= PT
&& PT
<= lastpos
&& cursor_vpos
< 0)
2964 cursor_hpos
= p1
- leftmargin
;
2967 if (cursor_vpos
== vpos
)
2969 if (cursor_hpos
< 0) cursor_hpos
= 0;
2970 if (cursor_hpos
> width
) cursor_hpos
= width
;
2971 cursor_hpos
+= XFASTINT (w
->left
);
2972 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
2974 if (!(cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f
)
2975 && EQ (FRAME_MINIBUF_WINDOW (f
), minibuf_window
)))
2977 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2978 FRAME_CURSOR_X (f
) = cursor_hpos
;
2981 if (w
== XWINDOW (selected_window
))
2983 /* Line is not continued and did not start
2984 in middle of character */
2985 if ((hpos
- XFASTINT (w
->left
)
2986 == (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
2989 this_line_bufpos
= start
;
2990 this_line_buffer
= current_buffer
;
2991 this_line_vpos
= cursor_vpos
;
2992 this_line_start_hpos
= hpos
;
2993 this_line_endpos
= Z
- lastpos
;
2996 this_line_bufpos
= 0;
3001 /* If hscroll and line not empty, insert truncation-at-left marker */
3002 if (hscroll
&& lastpos
!= start
)
3004 *leftmargin
= fix_glyph (f
, truncator
, 0);
3005 if (p1
<= leftmargin
)
3006 p1
= leftmargin
+ 1;
3009 if (XFASTINT (w
->width
) + XFASTINT (w
->left
) != FRAME_WIDTH (f
))
3012 if (p1
< leftmargin
) p1
= leftmargin
;
3013 while (p1
< endp
) *p1
++ = SPACEGLYPH
;
3015 /* Don't draw vertical bars if we're using scroll bars. They're
3016 covered up by the scroll bars, and it's distracting to see
3017 them when the scroll bar windows are flickering around to be
3019 *p1
++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
3021 : (dp
&& INTEGERP (DISP_BORDER_GLYPH (dp
))
3022 ? DISP_BORDER_GLYPH (dp
)
3025 desired_glyphs
->used
[vpos
] = max (desired_glyphs
->used
[vpos
],
3026 p1
- desired_glyphs
->glyphs
[vpos
]);
3027 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
3029 /* If the start of this line is the overlay arrow-position,
3030 then put the arrow string into the display-line. */
3032 if (MARKERP (Voverlay_arrow_position
)
3033 && current_buffer
== XMARKER (Voverlay_arrow_position
)->buffer
3034 && start
== marker_position (Voverlay_arrow_position
)
3035 && STRINGP (Voverlay_arrow_string
)
3036 && ! overlay_arrow_seen
)
3038 unsigned char *p
= XSTRING (Voverlay_arrow_string
)->data
;
3040 int len
= XSTRING (Voverlay_arrow_string
)->size
;
3046 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string
)->intervals
))
3048 /* If the arrow string has text props, obey them when displaying. */
3049 for (i
= 0; i
< len
; i
++)
3052 Lisp_Object face
, ilisp
;
3055 XSETFASTINT (ilisp
, i
);
3056 face
= Fget_text_property (ilisp
, Qface
, Voverlay_arrow_string
);
3057 newface
= compute_glyph_face_1 (f
, face
, 0);
3058 leftmargin
[i
] = FAST_MAKE_GLYPH (c
, newface
);
3062 #endif /* HAVE_FACES */
3064 for (i
= 0; i
< len
; i
++)
3065 leftmargin
[i
] = p
[i
];
3068 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
3069 arrow_end
= (leftmargin
- desired_glyphs
->glyphs
[vpos
]) + len
;
3070 if (desired_glyphs
->used
[vpos
] < arrow_end
)
3071 desired_glyphs
->used
[vpos
] = arrow_end
;
3073 overlay_arrow_seen
= 1;
3077 val_display_text_line
= val
;
3078 return &val_display_text_line
;
3081 /* Redisplay the menu bar in the frame for window W. */
3084 display_menu_bar (w
)
3087 Lisp_Object items
, tail
;
3088 register int vpos
= 0;
3089 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3090 int maxendcol
= FRAME_WIDTH (f
);
3094 #ifndef USE_X_TOOLKIT
3095 if (FRAME_MENU_BAR_LINES (f
) <= 0)
3098 get_display_line (f
, vpos
, 0);
3100 items
= FRAME_MENU_BAR_ITEMS (f
);
3101 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 3)
3103 Lisp_Object pos
, string
;
3104 string
= XVECTOR (items
)->contents
[i
+ 1];
3108 XSETFASTINT (XVECTOR (items
)->contents
[i
+ 2], hpos
);
3110 if (hpos
< maxendcol
)
3111 hpos
= display_string (XWINDOW (FRAME_ROOT_WINDOW (f
)), vpos
,
3112 XSTRING (string
)->data
,
3113 XSTRING (string
)->size
,
3114 hpos
, 0, 0, hpos
, maxendcol
);
3115 /* Put a space between items. */
3116 if (hpos
< maxendcol
)
3118 int hpos1
= hpos
+ 1;
3119 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0,
3120 min (hpos1
, maxendcol
), maxendcol
);
3124 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3125 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3127 /* Fill out the line with spaces. */
3128 if (maxendcol
> hpos
)
3129 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0, maxendcol
, maxendcol
);
3131 /* Clear the rest of the lines allocated to the menu bar. */
3133 while (vpos
< FRAME_MENU_BAR_LINES (f
))
3134 get_display_line (f
, vpos
++, 0);
3135 #endif /* not USE_X_TOOLKIT */
3138 /* Display the mode line for window w */
3141 display_mode_line (w
)
3144 register int vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
3145 register int left
= XFASTINT (w
->left
);
3146 register int right
= XFASTINT (w
->width
) + left
;
3147 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3149 line_number_displayed
= 0;
3150 w
->column_number_displayed
= Qnil
;
3152 get_display_line (f
, vpos
, left
);
3154 /* Temporarily make frame F's kboard the current kboard
3155 so that kboard-local variables in the mode_line_format
3156 will get the right values. */
3157 push_frame_kboard (f
);
3159 display_mode_element (w
, vpos
, left
, 0, right
, right
,
3160 current_buffer
->mode_line_format
);
3162 pop_frame_kboard ();
3164 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3166 /* Make the mode line inverse video if the entire line
3167 is made of mode lines.
3168 I.e. if this window is full width,
3169 or if it is the child of a full width window
3170 (which implies that that window is split side-by-side
3171 and the rest of this line is mode lines of the sibling windows). */
3172 if (XFASTINT (w
->width
) == FRAME_WIDTH (f
)
3173 || XFASTINT (XWINDOW (w
->parent
)->width
) == FRAME_WIDTH (f
))
3174 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3176 else if (! FRAME_TERMCAP_P (f
) && mode_line_inverse_video
)
3178 /* For a partial width window, explicitly set face of each glyph. */
3180 GLYPH
*ptr
= FRAME_DESIRED_GLYPHS (f
)->glyphs
[vpos
];
3181 for (i
= left
; i
< right
; ++i
)
3182 ptr
[i
] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr
[i
]), 1);
3187 /* Contribute ELT to the mode line for window W.
3188 How it translates into text depends on its data type.
3190 VPOS is the position of the mode line being displayed.
3192 HPOS is the position (absolute on frame) where this element's text
3193 should start. The output is truncated automatically at the right
3196 DEPTH is the depth in recursion. It is used to prevent
3197 infinite recursion here.
3199 MINENDCOL is the hpos before which the element may not end.
3200 The element is padded at the right with spaces if nec
3201 to reach this column.
3203 MAXENDCOL is the hpos past which this element may not extend.
3204 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3205 (This is necessary to make nested padding and truncation work.)
3207 Returns the hpos of the end of the text generated by ELT.
3208 The next element will receive that value as its HPOS arg,
3209 so as to concatenate the elements. */
3212 display_mode_element (w
, vpos
, hpos
, depth
, minendcol
, maxendcol
, elt
)
3214 register int vpos
, hpos
;
3217 register int maxendcol
;
3218 register Lisp_Object elt
;
3226 switch (SWITCH_ENUM_CAST (XTYPE (elt
)))
3230 /* A string: output it and check for %-constructs within it. */
3231 register unsigned char c
;
3232 register unsigned char *this = XSTRING (elt
)->data
;
3234 while (hpos
< maxendcol
&& *this)
3236 unsigned char *last
= this;
3237 while ((c
= *this++) != '\0' && c
!= '%')
3239 if (this - 1 != last
)
3241 register int lim
= --this - last
+ hpos
;
3242 if (frame_title_ptr
)
3243 hpos
= store_frame_title (last
, hpos
, min (lim
, maxendcol
));
3245 hpos
= display_string (w
, vpos
, last
, -1, hpos
, 0, 1,
3246 hpos
, min (lim
, maxendcol
));
3250 register int minendcol
;
3251 register int spec_width
= 0;
3253 /* We can't allow -ve args due to the "%-" construct */
3254 /* Argument specifies minwidth but not maxwidth
3255 (maxwidth can be specified by
3256 (<negative-number> . <stuff>) mode-line elements) */
3258 while ((c
= *this++) >= '0' && c
<= '9')
3260 spec_width
= spec_width
* 10 + (c
- '0');
3263 minendcol
= hpos
+ spec_width
;
3264 if (minendcol
> maxendcol
)
3266 spec_width
= maxendcol
- hpos
;
3267 minendcol
= maxendcol
;
3271 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
3272 spec_width
, maxendcol
,
3273 Vglobal_mode_string
);
3276 char *spec
= decode_mode_spec (w
, c
, spec_width
,
3278 if (frame_title_ptr
)
3279 hpos
= store_frame_title (spec
, minendcol
, maxendcol
);
3281 hpos
= display_string (w
, vpos
, spec
, -1,
3283 minendcol
, maxendcol
);
3291 /* A symbol: process the value of the symbol recursively
3292 as if it appeared here directly. Avoid error if symbol void.
3293 Special case: if value of symbol is a string, output the string
3296 register Lisp_Object tem
;
3297 tem
= Fboundp (elt
);
3300 tem
= Fsymbol_value (elt
);
3301 /* If value is a string, output that string literally:
3302 don't check for % within it. */
3305 if (frame_title_ptr
)
3306 hpos
= store_frame_title (XSTRING (tem
)->data
,
3307 minendcol
, maxendcol
);
3309 hpos
= display_string (w
, vpos
, XSTRING (tem
)->data
,
3310 XSTRING (tem
)->size
,
3311 hpos
, 0, 1, minendcol
, maxendcol
);
3313 /* Give up right away for nil or t. */
3314 else if (!EQ (tem
, elt
))
3315 { elt
= tem
; goto tail_recurse
; }
3322 register Lisp_Object car
, tem
;
3324 /* A cons cell: three distinct cases.
3325 If first element is a string or a cons, process all the elements
3326 and effectively concatenate them.
3327 If first element is a negative number, truncate displaying cdr to
3328 at most that many characters. If positive, pad (with spaces)
3329 to at least that many characters.
3330 If first element is a symbol, process the cadr or caddr recursively
3331 according to whether the symbol's value is non-nil or nil. */
3332 car
= XCONS (elt
)->car
;
3335 tem
= Fboundp (car
);
3336 elt
= XCONS (elt
)->cdr
;
3339 /* elt is now the cdr, and we know it is a cons cell.
3340 Use its car if CAR has a non-nil value. */
3343 tem
= Fsymbol_value (car
);
3345 { elt
= XCONS (elt
)->car
; goto tail_recurse
; }
3347 /* Symbol's value is nil (or symbol is unbound)
3348 Get the cddr of the original list
3349 and if possible find the caddr and use that. */
3350 elt
= XCONS (elt
)->cdr
;
3353 else if (!CONSP (elt
))
3355 elt
= XCONS (elt
)->car
;
3358 else if (INTEGERP (car
))
3360 register int lim
= XINT (car
);
3361 elt
= XCONS (elt
)->cdr
;
3363 /* Negative int means reduce maximum width.
3364 DO NOT change MINENDCOL here!
3365 (20 -10 . foo) should truncate foo to 10 col
3366 and then pad to 20. */
3367 maxendcol
= min (maxendcol
, hpos
- lim
);
3370 /* Padding specified. Don't let it be more than
3373 if (lim
> maxendcol
)
3375 /* If that's more padding than already wanted, queue it.
3376 But don't reduce padding already specified even if
3377 that is beyond the current truncation point. */
3378 if (lim
> minendcol
)
3383 else if (STRINGP (car
) || CONSP (car
))
3385 register int limit
= 50;
3386 /* LIMIT is to protect against circular lists. */
3387 while (CONSP (elt
) && --limit
> 0
3388 && hpos
< maxendcol
)
3390 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
3393 elt
= XCONS (elt
)->cdr
;
3401 if (frame_title_ptr
)
3402 hpos
= store_frame_title ("*invalid*", minendcol
, maxendcol
);
3404 hpos
= display_string (w
, vpos
, "*invalid*", -1, hpos
, 0, 1,
3405 minendcol
, maxendcol
);
3409 if (minendcol
> hpos
)
3410 if (frame_title_ptr
)
3411 hpos
= store_frame_title ("", minendcol
, maxendcol
);
3413 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 1, minendcol
, maxendcol
);
3417 /* Write a null-terminated, right justified decimal representation of
3418 the positive integer D to BUF using a minimal field width WIDTH. */
3421 pint2str (buf
, width
, d
)
3426 register char *p
= buf
;
3433 *p
++ = d
% 10 + '0';
3436 for (width
-= (int) (p
- buf
); width
> 0; --width
) *p
++ = ' ';
3446 /* Return a string for the output of a mode line %-spec for window W,
3447 generated by character C. SPEC_WIDTH is the field width when
3448 padding to the left (%c, %l). The value returned from this
3449 function will later be truncated to width MAXWIDTH. */
3451 static char lots_of_dashes
[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3454 decode_mode_spec (w
, c
, spec_width
, maxwidth
)
3457 register int spec_width
;
3458 register int maxwidth
;
3461 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3462 char *decode_mode_spec_buf
= (char *) FRAME_TEMP_GLYPHS (f
)->total_contents
;
3463 struct buffer
*b
= XBUFFER (w
->buffer
);
3466 if (maxwidth
> FRAME_WIDTH (f
))
3467 maxwidth
= FRAME_WIDTH (f
);
3472 if (!NILP (b
->read_only
))
3474 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3479 /* This differs from %* only for a modified read-only buffer. */
3480 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3482 if (!NILP (b
->read_only
))
3487 /* This differs from %* in ignoring read-only-ness. */
3488 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
3500 if (command_loop_level
> 5)
3502 p
= decode_mode_spec_buf
;
3503 for (i
= 0; i
< command_loop_level
; i
++)
3506 return decode_mode_spec_buf
;
3514 if (command_loop_level
> 5)
3516 p
= decode_mode_spec_buf
;
3517 for (i
= 0; i
< command_loop_level
; i
++)
3520 return decode_mode_spec_buf
;
3528 if (maxwidth
< sizeof (lots_of_dashes
))
3529 return lots_of_dashes
;
3532 for (p
= decode_mode_spec_buf
, i
= maxwidth
; i
> 0; i
--)
3536 return decode_mode_spec_buf
;
3542 if (maxwidth
>= 3 && XSTRING (obj
)->size
> maxwidth
)
3544 bcopy (XSTRING (obj
)->data
, decode_mode_spec_buf
, maxwidth
- 1);
3545 decode_mode_spec_buf
[maxwidth
- 1] = '\\';
3546 decode_mode_spec_buf
[maxwidth
] = '\0';
3547 return decode_mode_spec_buf
;
3554 int col
= current_column ();
3555 XSETFASTINT (w
->column_number_displayed
, col
);
3556 pint2str (decode_mode_spec_buf
, spec_width
, col
);
3557 return decode_mode_spec_buf
;
3561 /* %F displays the frame name. */
3563 return (char *) XSTRING (selected_frame
->name
)->data
;
3573 else if (STRINGP (obj
) && XSTRING (obj
)->size
> maxwidth
)
3575 bcopy ("...", decode_mode_spec_buf
, 3);
3576 bcopy (XSTRING (obj
)->data
+ XSTRING (obj
)->size
- maxwidth
+ 3,
3577 decode_mode_spec_buf
+ 3, maxwidth
- 3);
3578 return decode_mode_spec_buf
;
3585 int startpos
= marker_position (w
->start
);
3586 int line
, linepos
, topline
;
3589 int height
= XFASTINT (w
->height
);
3591 /* If we decided that this buffer isn't suitable for line numbers,
3592 don't forget that too fast. */
3593 if (EQ (w
->base_line_pos
, w
->buffer
))
3596 /* If the buffer is very big, don't waste time. */
3597 if (BUF_ZV (b
) - BUF_BEGV (b
) > line_number_display_limit
)
3599 w
->base_line_pos
= Qnil
;
3600 w
->base_line_number
= Qnil
;
3604 if (!NILP (w
->base_line_number
)
3605 && !NILP (w
->base_line_pos
)
3606 && XFASTINT (w
->base_line_pos
) <= marker_position (w
->start
))
3608 line
= XFASTINT (w
->base_line_number
);
3609 linepos
= XFASTINT (w
->base_line_pos
);
3614 linepos
= BUF_BEGV (b
);
3617 /* Count lines from base line to window start position. */
3618 nlines
= display_count_lines (linepos
, startpos
, startpos
, &junk
);
3620 topline
= nlines
+ line
;
3622 /* Determine a new base line, if the old one is too close
3623 or too far away, or if we did not have one.
3624 "Too close" means it's plausible a scroll-down would
3626 if (startpos
== BUF_BEGV (b
))
3628 XSETFASTINT (w
->base_line_number
, topline
);
3629 XSETFASTINT (w
->base_line_pos
, BUF_BEGV (b
));
3631 else if (nlines
< height
+ 25 || nlines
> height
* 3 + 50
3632 || linepos
== BUF_BEGV (b
))
3634 int limit
= BUF_BEGV (b
);
3636 int distance
= (height
* 2 + 30) * 200;
3638 if (startpos
- distance
> limit
)
3639 limit
= startpos
- distance
;
3641 nlines
= display_count_lines (startpos
, limit
,
3644 /* If we couldn't find the lines we wanted within
3646 give up on line numbers for this window. */
3647 if (position
== startpos
- distance
)
3649 w
->base_line_pos
= w
->buffer
;
3650 w
->base_line_number
= Qnil
;
3654 XSETFASTINT (w
->base_line_number
, topline
- nlines
);
3655 XSETFASTINT (w
->base_line_pos
, position
);
3658 /* Now count lines from the start pos to point. */
3659 nlines
= display_count_lines (startpos
, PT
, PT
, &junk
);
3661 /* Record that we did display the line number. */
3662 line_number_displayed
= 1;
3664 /* Make the string to show. */
3665 pint2str (decode_mode_spec_buf
, spec_width
, topline
+ nlines
);
3666 return decode_mode_spec_buf
;
3669 char* p
= decode_mode_spec_buf
;
3670 for (spec_width
-= 2; spec_width
> 0; --spec_width
) *p
++ = ' ';
3672 return decode_mode_spec_buf
;
3682 if (BUF_BEGV (b
) > BUF_BEG (b
) || BUF_ZV (b
) < BUF_Z (b
))
3688 int pos
= marker_position (w
->start
);
3689 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3691 if (XFASTINT (w
->window_end_pos
) <= BUF_Z (b
) - BUF_ZV (b
))
3693 if (pos
<= BUF_BEGV (b
))
3698 else if (pos
<= BUF_BEGV (b
))
3702 total
= ((pos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3703 /* We can't normally display a 3-digit number,
3704 so get us a 2-digit number that is close. */
3707 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3708 return decode_mode_spec_buf
;
3712 /* Display percentage of size above the bottom of the screen. */
3715 int toppos
= marker_position (w
->start
);
3716 int botpos
= BUF_Z (b
) - XFASTINT (w
->window_end_pos
);
3717 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3719 if (botpos
>= BUF_ZV (b
))
3721 if (toppos
<= BUF_BEGV (b
))
3728 total
= ((botpos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3729 /* We can't normally display a 3-digit number,
3730 so get us a 2-digit number that is close. */
3733 if (toppos
<= BUF_BEGV (b
))
3734 sprintf (decode_mode_spec_buf
, "Top%2d%%", total
);
3736 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3737 return decode_mode_spec_buf
;
3742 /* status of process */
3743 obj
= Fget_buffer_process (w
->buffer
);
3745 return "no process";
3747 obj
= Fsymbol_name (Fprocess_status (obj
));
3751 case 't': /* indicate TEXT or BINARY */
3752 #ifdef MODE_LINE_BINARY_TEXT
3753 return MODE_LINE_BINARY_TEXT (b
);
3760 return (char *) XSTRING (obj
)->data
;
3765 /* Search for COUNT instances of a line boundary, which means either a
3766 newline or (if selective display enabled) a carriage return.
3767 Start at START. If COUNT is negative, search backwards.
3769 If we find COUNT instances, set *SHORTAGE to zero, and return the
3770 position after the COUNTth match. Note that for reverse motion
3771 this is not the same as the usual convention for Emacs motion commands.
3773 If we don't find COUNT instances before reaching the end of the
3774 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3775 the number of line boundaries left unfound, and return the end of the
3776 buffer we bumped up against. */
3779 display_scan_buffer (start
, count
, shortage
)
3780 int *shortage
, start
;
3783 int limit
= ((count
> 0) ? ZV
- 1 : BEGV
);
3784 int direction
= ((count
> 0) ? 1 : -1);
3786 register unsigned char *cursor
;
3787 unsigned char *base
;
3789 register int ceiling
;
3790 register unsigned char *ceiling_addr
;
3792 /* If we are not in selective display mode,
3793 check only for newlines. */
3794 if (! (!NILP (current_buffer
->selective_display
)
3795 && !INTEGERP (current_buffer
->selective_display
)))
3796 return scan_buffer ('\n', start
, 0, count
, shortage
, 0);
3798 /* The code that follows is like scan_buffer
3799 but checks for either newline or carriage return. */
3805 while (start
!= limit
+ 1)
3807 ceiling
= BUFFER_CEILING_OF (start
);
3808 ceiling
= min (limit
, ceiling
);
3809 ceiling_addr
= &FETCH_CHAR (ceiling
) + 1;
3810 base
= (cursor
= &FETCH_CHAR (start
));
3813 while (*cursor
!= '\n' && *cursor
!= 015 && ++cursor
!= ceiling_addr
)
3815 if (cursor
!= ceiling_addr
)
3820 return (start
+ cursor
- base
+ 1);
3823 if (++cursor
== ceiling_addr
)
3829 start
+= cursor
- base
;
3833 start
--; /* first character we scan */
3834 while (start
> limit
- 1)
3835 { /* we WILL scan under start */
3836 ceiling
= BUFFER_FLOOR_OF (start
);
3837 ceiling
= max (limit
, ceiling
);
3838 ceiling_addr
= &FETCH_CHAR (ceiling
) - 1;
3839 base
= (cursor
= &FETCH_CHAR (start
));
3843 while (--cursor
!= ceiling_addr
3844 && *cursor
!= '\n' && *cursor
!= 015)
3846 if (cursor
!= ceiling_addr
)
3851 return (start
+ cursor
- base
+ 1);
3857 start
+= cursor
- base
;
3862 *shortage
= count
* direction
;
3863 return (start
+ ((direction
== 1 ? 0 : 1)));
3866 /* Count up to N lines starting from FROM.
3867 But don't go beyond LIMIT.
3868 Return the number of lines thus found (always positive).
3869 Store the position after what was found into *POS_PTR. */
3872 display_count_lines (from
, limit
, n
, pos_ptr
)
3885 *pos_ptr
= display_scan_buffer (from
, n
, &shortage
);
3891 /* When scanning backwards, scan_buffer stops *after* the last newline
3892 it finds, but does count it. Compensate for that. */
3893 return - n
- shortage
- (*pos_ptr
!= limit
);
3894 return n
- shortage
;
3897 /* Display STRING on one line of window W, starting at HPOS.
3898 Display at position VPOS. Caller should have done get_display_line.
3899 If VPOS == -1, display it as the current frame's title.
3900 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3902 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3904 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3905 MAXCOL is the last column ok to end at. Truncate here.
3906 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3907 Both count from the left edge of the frame, as does HPOS.
3908 The right edge of W is an implicit maximum.
3909 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3911 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3912 at the place where the current window ends in this line
3913 and not display anything beyond there. Otherwise, only MAXCOL
3914 controls where to stop output.
3916 Returns ending hpos. */
3919 display_string (w
, vpos
, string
, length
, hpos
, truncate
,
3920 obey_window_width
, mincol
, maxcol
)
3922 unsigned char *string
;
3926 int obey_window_width
;
3931 int hscroll
= XINT (w
->hscroll
);
3932 int tab_width
= XINT (XBUFFER (w
->buffer
)->tab_width
);
3933 register GLYPH
*start
;
3934 register GLYPH
*end
;
3935 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3936 struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
3937 GLYPH
*p1start
= desired_glyphs
->glyphs
[vpos
] + hpos
;
3938 int window_width
= XFASTINT (w
->width
);
3940 /* Use the standard display table, not the window's display table.
3941 We don't want the mode line in rot13. */
3942 register struct Lisp_Vector
*dp
= 0;
3945 if (VECTORP (Vstandard_display_table
)
3946 && XVECTOR (Vstandard_display_table
)->size
== DISP_TABLE_SIZE
)
3947 dp
= XVECTOR (Vstandard_display_table
);
3949 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
3952 start
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
3954 if (obey_window_width
)
3956 end
= start
+ window_width
- (truncate
!= 0);
3958 if ((window_width
+ XFASTINT (w
->left
)) != FRAME_WIDTH (f
))
3960 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3964 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
3972 if (! obey_window_width
3973 || (maxcol
>= 0 && end
- desired_glyphs
->glyphs
[vpos
] > maxcol
))
3974 end
= desired_glyphs
->glyphs
[vpos
] + maxcol
;
3976 /* Store 0 in charstart for these columns. */
3977 for (i
= (hpos
>= 0 ? hpos
: 0); i
< end
- p1start
+ hpos
; i
++)
3978 desired_glyphs
->charstarts
[vpos
][i
] = 0;
3980 if (maxcol
>= 0 && mincol
> maxcol
)
3988 /* Specified length. */
3991 /* Unspecified length (null-terminated string). */
3995 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
3997 p1
= copy_part_of_rope (f
, p1
, start
,
3998 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
3999 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
4002 else if (c
>= 040 && c
< 0177)
4012 if (p1
>= start
&& p1
< end
)
4016 while ((p1
- start
+ hscroll
- (hscroll
> 0)) % tab_width
);
4018 else if (c
< 0200 && ! NILP (buffer_defaults
.ctl_arrow
))
4021 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
4022 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
4025 if (p1
>= start
&& p1
< end
)
4032 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
4033 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
4036 if (p1
>= start
&& p1
< end
)
4037 *p1
= (c
>> 6) + '0';
4039 if (p1
>= start
&& p1
< end
)
4040 *p1
= (7 & (c
>> 3)) + '0';
4042 if (p1
>= start
&& p1
< end
)
4043 *p1
= (7 & c
) + '0';
4048 if (c
&& length
> 0)
4051 if (truncate
) *p1
++ = fix_glyph (f
, truncate
, 0);
4053 else if (mincol
>= 0)
4055 end
= desired_glyphs
->glyphs
[vpos
] + mincol
;
4061 register int len
= p1
- desired_glyphs
->glyphs
[vpos
];
4063 if (len
> desired_glyphs
->used
[vpos
])
4064 desired_glyphs
->used
[vpos
] = len
;
4065 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
4071 /* This is like a combination of memq and assq.
4072 Return 1 if PROPVAL appears as an element of LIST
4073 or as the car of an element of LIST.
4074 If PROPVAL is a list, compare each element against LIST
4075 in that way, and return 1 if any element of PROPVAL is found in LIST.
4077 This function cannot quit. */
4080 invisible_p (propval
, list
)
4081 register Lisp_Object propval
;
4084 register Lisp_Object tail
, proptail
;
4085 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4087 register Lisp_Object tem
;
4088 tem
= XCONS (tail
)->car
;
4089 if (EQ (propval
, tem
))
4091 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4094 if (CONSP (propval
))
4095 for (proptail
= propval
; CONSP (proptail
);
4096 proptail
= XCONS (proptail
)->cdr
)
4098 Lisp_Object propelt
;
4099 propelt
= XCONS (proptail
)->car
;
4100 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4102 register Lisp_Object tem
;
4103 tem
= XCONS (tail
)->car
;
4104 if (EQ (propelt
, tem
))
4106 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4113 /* Return 1 if PROPVAL appears as the car of an element of LIST
4114 and the cdr of that element is non-nil.
4115 If PROPVAL is a list, check each element of PROPVAL in that way,
4116 and the first time some element is found,
4117 return 1 if the cdr of that element is non-nil.
4119 This function cannot quit. */
4122 invisible_ellipsis_p (propval
, list
)
4123 register Lisp_Object propval
;
4126 register Lisp_Object tail
, proptail
;
4127 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4129 register Lisp_Object tem
;
4130 tem
= XCONS (tail
)->car
;
4131 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4132 return ! NILP (XCONS (tem
)->cdr
);
4134 if (CONSP (propval
))
4135 for (proptail
= propval
; CONSP (proptail
);
4136 proptail
= XCONS (proptail
)->cdr
)
4138 Lisp_Object propelt
;
4139 propelt
= XCONS (proptail
)->car
;
4140 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4142 register Lisp_Object tem
;
4143 tem
= XCONS (tail
)->car
;
4144 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4145 return ! NILP (XCONS (tem
)->cdr
);
4154 staticpro (&Qmenu_bar_update_hook
);
4155 Qmenu_bar_update_hook
= intern ("menu-bar-update-hook");
4157 staticpro (&Qoverriding_terminal_local_map
);
4158 Qoverriding_terminal_local_map
= intern ("overriding-terminal-local-map");
4160 staticpro (&Qoverriding_local_map
);
4161 Qoverriding_local_map
= intern ("overriding-local-map");
4163 staticpro (&last_arrow_position
);
4164 staticpro (&last_arrow_string
);
4165 last_arrow_position
= Qnil
;
4166 last_arrow_string
= Qnil
;
4168 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
,
4169 "String (or mode line construct) included (normally) in `mode-line-format'.");
4170 Vglobal_mode_string
= Qnil
;
4172 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
,
4173 "Marker for where to display an arrow on top of the buffer text.\n\
4174 This must be the beginning of a line in order to work.\n\
4175 See also `overlay-arrow-string'.");
4176 Voverlay_arrow_position
= Qnil
;
4178 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
,
4179 "String to display as an arrow. See also `overlay-arrow-position'.");
4180 Voverlay_arrow_string
= Qnil
;
4182 DEFVAR_INT ("scroll-step", &scroll_step
,
4183 "*The number of lines to try scrolling a window by when point moves out.\n\
4184 If that fails to bring point back on frame, point is centered instead.\n\
4185 If this is zero, point is always centered after it moves off frame.");
4187 DEFVAR_INT ("debug-end-pos", &debug_end_pos
, "Don't ask");
4189 DEFVAR_BOOL ("truncate-partial-width-windows",
4190 &truncate_partial_width_windows
,
4191 "*Non-nil means truncate lines in all windows less than full frame wide.");
4192 truncate_partial_width_windows
= 1;
4194 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
,
4195 "*Non-nil means use inverse video for the mode line.");
4196 mode_line_inverse_video
= 1;
4198 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit
,
4199 "*Maximum buffer size for which line number should be displayed.");
4200 line_number_display_limit
= 1000000;
4202 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
,
4203 "*Non-nil means highlight region even in nonselected windows.");
4204 highlight_nonselected_windows
= 1;
4206 DEFVAR_BOOL ("multiple-frames", &multiple_frames
,
4207 "Non-nil if more than one frame is visible on this display.\n\
4208 Minibuffer-only frames don't count, but iconified frames do.\n\
4209 This variable is not guaranteed to be accurate except while parsing\n\
4210 frame-title-format.");
4212 DEFVAR_LISP ("frame-title-format", &Vframe_title_format
,
4213 "Template for displaying the titlebar of visible frames.\n\
4214 \(Assuming the window manager supports this feature.)\n\
4215 This variable has the same structure as `mode-line-format' (which see),\n\
4216 and is used only on frames for which no explicit name has been set\n\
4217 \(see `modify-frame-parameters').");
4218 DEFVAR_LISP ("icon-title-format", &Vicon_title_format
,
4219 "Template for displaying the titlebar of an iconified frame.\n\
4220 \(Assuming the window manager supports this feature.)\n\
4221 This variable has the same structure as `mode-line-format' (which see),\n\
4222 and is used only on frames for which no explicit name has been set\n\
4223 \(see `modify-frame-parameters').");
4225 = Vframe_title_format
4226 = Fcons (intern ("multiple-frames"),
4227 Fcons (build_string ("%b"),
4228 Fcons (Fcons (build_string (""),
4229 Fcons (intern ("invocation-name"),
4230 Fcons (build_string ("@"),
4231 Fcons (intern ("system-name"),
4235 DEFVAR_LISP ("message-log-max", &Vmessage_log_max
,
4236 "Maximum number of lines to keep in the message log buffer.\n\
4237 If nil, disable message logging. If t, log messages but don't truncate\n\
4238 the buffer when it becomes large.");
4239 XSETFASTINT (Vmessage_log_max
, 50);
4241 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions
,
4242 "Functions called before redisplay, if window sizes have changed.\n\
4243 The value should be a list of functions that take one argument.\n\
4244 Just before redisplay, for each frame, if any of its windows have changed\n\
4245 size since the last redisplay, or have been split or deleted,\n\
4246 all the functions in the list are called, with the frame as argument.");
4247 Vwindow_size_change_functions
= Qnil
;
4250 /* initialize the window system */
4253 Lisp_Object root_window
;
4254 #ifndef COMPILER_REGISTER_BUG
4256 #endif /* COMPILER_REGISTER_BUG */
4257 struct window
*mini_w
;
4259 this_line_bufpos
= 0;
4261 mini_w
= XWINDOW (minibuf_window
);
4262 root_window
= FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w
)));
4264 echo_area_glyphs
= 0;
4265 previous_echo_glyphs
= 0;
4267 if (!noninteractive
)
4269 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (root_window
)));
4270 XSETFASTINT (XWINDOW (root_window
)->top
, 0);
4271 set_window_height (root_window
, FRAME_HEIGHT (f
) - 1, 0);
4272 XSETFASTINT (mini_w
->top
, FRAME_HEIGHT (f
) - 1);
4273 set_window_height (minibuf_window
, 1, 0);
4275 XSETFASTINT (XWINDOW (root_window
)->width
, FRAME_WIDTH (f
));
4276 XSETFASTINT (mini_w
->width
, FRAME_WIDTH (f
));