1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 1997
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
25 /*#include <ctype.h>*/
31 #include "dispextern.h"
38 #include "termhooks.h"
39 #include "intervals.h"
44 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
45 extern void set_frame_menubar ();
46 extern int pending_menu_activation
;
49 extern int interrupt_input
;
50 extern int command_loop_level
;
52 extern int minibuffer_auto_raise
;
54 extern Lisp_Object Qface
;
56 extern Lisp_Object Voverriding_local_map
;
57 extern Lisp_Object Voverriding_local_map_menu_flag
;
59 Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
60 Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
61 Lisp_Object Qredisplay_end_trigger_functions
;
63 /* Nonzero means print newline to stdout before next minibuffer message. */
65 int noninteractive_need_newline
;
67 /* Nonzero means print newline to message log before next message. */
69 static int message_log_need_newline
;
71 #define min(a, b) ((a) < (b) ? (a) : (b))
72 #define max(a, b) ((a) > (b) ? (a) : (b))
73 #define minmax(floor, val, ceil) \
74 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
76 /* The buffer position of the first character appearing
77 entirely or partially on the current frame line.
78 Or zero, which disables the optimization for the current frame line. */
79 static int this_line_bufpos
;
81 /* Number of characters past the end of this line,
82 including the terminating newline */
83 static int this_line_endpos
;
85 /* The vertical position of this frame line. */
86 static int this_line_vpos
;
88 /* Hpos value for start of display on this frame line.
89 Usually zero, but negative if first character really began
91 static int this_line_start_hpos
;
93 /* Buffer that this_line variables are describing. */
94 static struct buffer
*this_line_buffer
;
96 /* Value of echo_area_glyphs when it was last acted on.
97 If this is nonzero, there is a message on the frame
98 in the minibuffer and it should be erased as soon
99 as it is no longer requested to appear. */
100 char *previous_echo_glyphs
;
102 /* Nonzero means truncate lines in all windows less wide than the frame */
103 int truncate_partial_width_windows
;
105 /* Nonzero means we have more than one non-minibuffer-only frame.
106 Not guaranteed to be accurate except while parsing frame-title-format. */
109 Lisp_Object Vglobal_mode_string
;
111 /* Marker for where to display an arrow on top of the buffer text. */
112 Lisp_Object Voverlay_arrow_position
;
114 /* String to display for the arrow. */
115 Lisp_Object Voverlay_arrow_string
;
117 /* Values of those variables at last redisplay.
118 However, if Voverlay_arrow_position is a marker,
119 last_arrow_position is its numerical position. */
120 static Lisp_Object last_arrow_position
, last_arrow_string
;
122 /* Like mode-line-format, but for the titlebar on a visible frame. */
123 Lisp_Object Vframe_title_format
;
125 /* Like mode-line-format, but for the titlebar on an iconified frame. */
126 Lisp_Object Vicon_title_format
;
128 /* List of functions to call when a window's size changes. These
129 functions get one arg, a frame on which one or more windows' sizes
131 static Lisp_Object Vwindow_size_change_functions
;
133 Lisp_Object Qmenu_bar_update_hook
;
135 /* Nonzero if overlay arrow has been displayed once in this window. */
136 static int overlay_arrow_seen
;
138 /* Nonzero if visible end of buffer has already been displayed once
139 in this window. (We need this variable in case there are overlay
140 strings that get displayed there.) */
141 static int zv_strings_seen
;
143 /* Nonzero means highlight the region even in nonselected windows. */
144 static int highlight_nonselected_windows
;
146 /* If cursor motion alone moves point off frame,
147 Try scrolling this many lines up or down if that will bring it back. */
148 static int scroll_step
;
150 /* Non-0 means scroll just far enough to bring point back on the screen,
152 static int scroll_conservatively
;
154 /* Recenter the window whenever point gets within this many lines
155 of the top or bottom of the window. */
158 /* Nonzero if try_window_id has made blank lines at window bottom
159 since the last redisplay that paused */
160 static int blank_end_of_window
;
162 /* Number of windows showing the buffer of the selected window
163 (or another buffer with the same base buffer).
164 keyboard.c refers to this. */
167 /* display_text_line sets these to the frame position (origin 0) of point,
168 whether the window is selected or not.
169 Set one to -1 first to determine whether point was found afterwards. */
171 static int cursor_vpos
;
172 static int cursor_hpos
;
174 static int debug_end_pos
;
176 /* Nonzero means display mode line highlighted */
177 int mode_line_inverse_video
;
179 static void redisplay_internal ();
180 static int message_log_check_duplicate ();
181 static void echo_area_display ();
182 void mark_window_display_accurate ();
183 static void redisplay_windows ();
184 static void redisplay_window ();
185 static void update_menu_bar ();
186 static void try_window ();
187 static int try_window_id ();
188 static struct position
*display_text_line ();
189 static void display_mode_line ();
190 static int display_mode_element ();
191 static char *decode_mode_spec ();
192 static int display_string ();
193 static void display_menu_bar ();
194 static int display_count_lines ();
196 /* Prompt to display in front of the minibuffer contents */
197 Lisp_Object minibuf_prompt
;
199 /* Width in columns of current minibuffer prompt. */
200 int minibuf_prompt_width
;
202 /* Message to display instead of minibuffer contents
203 This is what the functions error and message make,
204 and command echoing uses it as well.
205 It overrides the minibuf_prompt as well as the buffer. */
206 char *echo_area_glyphs
;
208 /* This is the length of the message in echo_area_glyphs. */
209 int echo_area_glyphs_length
;
211 /* This is the window where the echo area message was displayed.
212 It is always a minibuffer window, but it may not be the
213 same window currently active as a minibuffer. */
214 Lisp_Object echo_area_window
;
216 /* true iff we should redraw the mode lines on the next redisplay */
217 int update_mode_lines
;
219 /* Smallest number of characters before the gap
220 at any time since last redisplay that finished.
221 Valid for current buffer when try_window_id can be called. */
224 /* Smallest number of characters after the gap
225 at any time since last redisplay that finished.
226 Valid for current buffer when try_window_id can be called. */
229 /* MODIFF as of last redisplay that finished;
230 if it matches MODIFF, and overlay_unchanged_modified
231 matches OVERLAY_MODIFF, that means beg_unchanged and end_unchanged
232 contain no useful information */
233 int unchanged_modified
;
235 /* OVERLAY_MODIFF as of last redisplay that finished. */
236 int overlay_unchanged_modified
;
238 /* Nonzero if window sizes or contents have changed
239 since last redisplay that finished */
240 int windows_or_buffers_changed
;
242 /* Nonzero after display_mode_line if %l was used
243 and it displayed a line number. */
244 int line_number_displayed
;
246 /* Maximum buffer size for which to display line numbers. */
247 static int line_number_display_limit
;
249 /* Number of lines to keep in the message log buffer.
250 t means infinite. nil means don't log at all. */
251 Lisp_Object Vmessage_log_max
;
253 #define COERCE_MARKER(X) \
254 (MARKERP ((X)) ? Fmarker_position (X) : (X))
256 /* Output a newline in the *Messages* buffer if "needs" one. */
259 message_log_maybe_newline ()
261 if (message_log_need_newline
)
262 message_dolog ("", 0, 1);
266 /* Add a string to the message log, optionally terminated with a newline.
267 This function calls low-level routines in order to bypass text property
268 hooks, etc. which might not be safe to run. */
271 message_dolog (m
, len
, nlflag
)
275 if (!NILP (Vmessage_log_max
))
277 struct buffer
*oldbuf
;
278 int oldpoint
, oldbegv
, oldzv
;
279 int old_windows_or_buffers_changed
= windows_or_buffers_changed
;
281 oldbuf
= current_buffer
;
282 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
283 current_buffer
->undo_list
= Qt
;
290 oldpoint
+= len
+ nlflag
;
292 oldzv
+= len
+ nlflag
;
295 insert_1 (m
, len
, 1, 0);
298 int this_bol
, prev_bol
, dup
;
299 insert_1 ("\n", 1, 1, 0);
301 this_bol
= scan_buffer ('\n', Z
, 0, -2, 0, 0);
304 prev_bol
= scan_buffer ('\n', this_bol
, 0, -2, 0, 0);
305 dup
= message_log_check_duplicate (prev_bol
, this_bol
);
308 if (oldpoint
> prev_bol
)
309 oldpoint
-= min (this_bol
, oldpoint
) - prev_bol
;
310 if (oldbegv
> prev_bol
)
311 oldbegv
-= min (this_bol
, oldbegv
) - prev_bol
;
312 if (oldzv
> prev_bol
)
313 oldzv
-= min (this_bol
, oldzv
) - prev_bol
;
314 del_range_1 (prev_bol
, this_bol
, 0);
320 /* If you change this format, don't forget to also
321 change message_log_check_duplicate. */
322 sprintf (dupstr
, " [%d times]", dup
);
323 duplen
= strlen (dupstr
);
329 insert_1 (dupstr
, duplen
, 1, 0);
334 if (NATNUMP (Vmessage_log_max
))
336 int pos
= scan_buffer ('\n', Z
, 0,
337 -XFASTINT (Vmessage_log_max
) - 1, 0, 0);
338 oldpoint
-= min (pos
, oldpoint
) - BEG
;
339 oldbegv
-= min (pos
, oldbegv
) - BEG
;
340 oldzv
-= min (pos
, oldzv
) - BEG
;
341 del_range_1 (BEG
, pos
, 0);
346 TEMP_SET_PT (oldpoint
);
347 set_buffer_internal (oldbuf
);
348 windows_or_buffers_changed
= old_windows_or_buffers_changed
;
349 message_log_need_newline
= !nlflag
;
353 /* We are at the end of the buffer after just having inserted a newline.
354 (Note: We depend on the fact we won't be crossing the gap.)
355 Check to see if the most recent message looks a lot like the previous one.
356 Return 0 if different, 1 if the new one should just replace it, or a
357 value N > 1 if we should also append " [N times]". */
360 message_log_check_duplicate (prev_bol
, this_bol
)
361 int prev_bol
, this_bol
;
364 int len
= Z
- 1 - this_bol
;
366 unsigned char *p1
= BUF_CHAR_ADDRESS (current_buffer
, prev_bol
);
367 unsigned char *p2
= BUF_CHAR_ADDRESS (current_buffer
, this_bol
);
369 for (i
= 0; i
< len
; i
++)
371 if (i
>= 3 && p1
[i
-3] == '.' && p1
[i
-2] == '.' && p1
[i
-1] == '.'
380 if (*p1
++ == ' ' && *p1
++ == '[')
383 while (*p1
>= '0' && *p1
<= '9')
384 n
= n
* 10 + *p1
++ - '0';
385 if (strncmp (p1
, " times]\n", 8) == 0)
391 /* Display an echo area message M with a specified length of LEN chars.
392 The string may include null characters. If M is 0, clear out any
393 existing message, and let the minibuffer text show through.
395 The buffer M must continue to exist until after the echo area
396 gets cleared or some other message gets displayed there.
398 Do not pass text that is stored in a Lisp string.
399 Do not pass text in a buffer that was alloca'd. */
406 /* First flush out any partial line written with print. */
407 message_log_maybe_newline ();
409 message_dolog (m
, len
, 1);
410 message2_nolog (m
, len
);
414 /* The non-logging counterpart of message2. */
417 message2_nolog (m
, len
)
423 if (noninteractive_need_newline
)
425 noninteractive_need_newline
= 0;
427 fwrite (m
, len
, 1, stderr
);
428 if (cursor_in_echo_area
== 0)
429 fprintf (stderr
, "\n");
432 /* A null message buffer means that the frame hasn't really been
433 initialized yet. Error messages get reported properly by
434 cmd_error, so this must be just an informative message; toss it. */
435 else if (INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
437 Lisp_Object mini_window
;
440 /* Get the frame containing the minibuffer
441 that the selected frame is using. */
442 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
443 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
445 FRAME_SAMPLE_VISIBILITY (f
);
446 if (FRAME_VISIBLE_P (selected_frame
)
447 && ! FRAME_VISIBLE_P (f
))
448 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window
)));
452 echo_area_glyphs
= m
;
453 echo_area_glyphs_length
= len
;
455 if (minibuffer_auto_raise
)
456 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window
)));
459 echo_area_glyphs
= previous_echo_glyphs
= 0;
461 do_pending_window_change ();
462 echo_area_display ();
463 update_frame (f
, 1, 1);
464 do_pending_window_change ();
465 if (frame_up_to_date_hook
!= 0 && ! gc_in_progress
)
466 (*frame_up_to_date_hook
) (f
);
470 /* Display a null-terminated echo area message M. If M is 0, clear out any
471 existing message, and let the minibuffer text show through.
473 The buffer M must continue to exist until after the echo area
474 gets cleared or some other message gets displayed there.
476 Do not pass text that is stored in a Lisp string.
477 Do not pass text in a buffer that was alloca'd. */
483 message2 (m
, (m
? strlen (m
) : 0));
490 message2_nolog (m
, (m
? strlen (m
) : 0));
493 /* Truncate what will be displayed in the echo area
494 the next time we display it--but don't redisplay it now. */
497 truncate_echo_area (len
)
500 /* A null message buffer means that the frame hasn't really been
501 initialized yet. Error messages get reported properly by
502 cmd_error, so this must be just an informative message; toss it. */
503 if (!noninteractive
&& INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
504 echo_area_glyphs_length
= len
;
507 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
508 zero if being used by message. */
509 int message_buf_print
;
511 /* Dump an informative message to the minibuf. If M is 0, clear out
512 any existing message, and let the minibuffer text show through. */
516 message (m
, a1
, a2
, a3
)
518 EMACS_INT a1
, a2
, a3
;
524 if (noninteractive_need_newline
)
526 noninteractive_need_newline
= 0;
527 fprintf (stderr
, m
, a1
, a2
, a3
);
528 if (cursor_in_echo_area
== 0)
529 fprintf (stderr
, "\n");
533 else if (INTERACTIVE
)
535 /* The frame whose minibuffer we're going to display the message on.
536 It may be larger than the selected frame, so we need
537 to use its buffer, not the selected frame's buffer. */
538 Lisp_Object mini_window
;
541 /* Get the frame containing the minibuffer
542 that the selected frame is using. */
543 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
544 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
546 /* A null message buffer means that the frame hasn't really been
547 initialized yet. Error messages get reported properly by
548 cmd_error, so this must be just an informative message; toss it. */
549 if (FRAME_MESSAGE_BUF (f
))
560 len
= doprnt (FRAME_MESSAGE_BUF (f
),
561 FRAME_MESSAGE_BUF_SIZE (f
), m
, (char *)0, 3, a
);
563 len
= doprnt (FRAME_MESSAGE_BUF (f
),
564 FRAME_MESSAGE_BUF_SIZE (f
), m
, (char *)0, 3, &a1
);
565 #endif /* NO_ARG_ARRAY */
567 message2 (FRAME_MESSAGE_BUF (f
), len
);
572 /* Print should start at the beginning of the message
574 message_buf_print
= 0;
579 /* The non-logging version of message. */
581 message_nolog (m
, a1
, a2
, a3
)
583 EMACS_INT a1
, a2
, a3
;
585 Lisp_Object old_log_max
;
586 old_log_max
= Vmessage_log_max
;
587 Vmessage_log_max
= Qnil
;
588 message (m
, a1
, a2
, a3
);
589 Vmessage_log_max
= old_log_max
;
595 message2 (echo_area_glyphs
, echo_area_glyphs_length
);
603 Lisp_Object mini_window
;
605 /* Choose the minibuffer window for this display.
606 It is the minibuffer window used by the selected frame. */
607 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
608 /* This is the frame that window is in. */
609 f
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
611 if (! FRAME_VISIBLE_P (f
))
616 redraw_garbaged_frames ();
620 if (echo_area_glyphs
|| minibuf_level
== 0)
624 echo_area_window
= mini_window
;
626 vpos
= XFASTINT (XWINDOW (mini_window
)->top
);
627 get_display_line (f
, vpos
, 0);
629 /* Make sure the columns that overlap a left-hand scroll bar
631 for (i
= 0; i
< FRAME_LEFT_SCROLL_BAR_WIDTH (f
); i
++)
632 f
->desired_glyphs
->glyphs
[vpos
][i
] = SPACEGLYPH
;
634 display_string (XWINDOW (mini_window
), vpos
,
635 echo_area_glyphs
? echo_area_glyphs
: "",
636 echo_area_glyphs
? echo_area_glyphs_length
: -1,
637 FRAME_LEFT_SCROLL_BAR_WIDTH (f
),
639 FRAME_WIDTH (f
) + FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
641 #if 0 /* This just gets in the way. update_frame does the job. */
642 /* If desired cursor location is on this line, put it at end of text */
643 if (cursor_in_echo_area
)
644 FRAME_CURSOR_Y (f
) = vpos
;
645 if (FRAME_CURSOR_Y (f
) == vpos
)
646 FRAME_CURSOR_X (f
) = FRAME_DESIRED_GLYPHS (f
)->used
[vpos
];
649 /* Fill the rest of the minibuffer window with blank lines. */
654 i
< vpos
+ XFASTINT (XWINDOW (mini_window
)->height
); i
++)
656 get_display_line (f
, i
, 0);
657 /* We don't use FRAME_SCROLL_BAR_WIDTH (f) as the starting
658 hpos, because it is good to clear whatever is behind the
659 scroll bar. This does not affect the scroll bar itself. */
660 display_string (XWINDOW (mini_window
), i
,
663 0, FRAME_WIDTH (f
) + FRAME_SCROLL_BAR_WIDTH (f
));
667 else if (!EQ (mini_window
, selected_window
))
668 windows_or_buffers_changed
++;
670 if (EQ (mini_window
, selected_window
))
671 this_line_bufpos
= 0;
673 previous_echo_glyphs
= echo_area_glyphs
;
676 /* Update frame titles. */
678 #ifdef HAVE_WINDOW_SYSTEM
679 static char frame_title_buf
[512];
680 static char *frame_title_ptr
;
683 store_frame_title (str
, mincol
, maxcol
)
688 if (maxcol
< 0 || maxcol
>= sizeof(frame_title_buf
))
689 maxcol
= sizeof (frame_title_buf
);
690 limit
= &frame_title_buf
[maxcol
];
691 while (*str
!= '\0' && frame_title_ptr
< limit
)
692 *frame_title_ptr
++ = *str
++;
693 while (frame_title_ptr
< &frame_title_buf
[mincol
])
694 *frame_title_ptr
++ = ' ';
695 return frame_title_ptr
- frame_title_buf
;
699 x_consider_frame_title (frame
)
705 FRAME_PTR f
= XFRAME (frame
);
707 if (!(FRAME_WINDOW_P (f
) || FRAME_MINIBUF_ONLY_P (f
) || f
->explicit_name
))
710 /* Do we have more than one visible frame on this X display? */
714 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
716 FRAME_PTR tf
= XFRAME (XCONS (tail
)->car
);
718 if (tf
!= f
&& FRAME_KBOARD (tf
) == FRAME_KBOARD (f
)
719 && !FRAME_MINIBUF_ONLY_P (tf
)
720 && (FRAME_VISIBLE_P (tf
) || FRAME_ICONIFIED_P (tf
)))
724 multiple_frames
= CONSP (tail
);
727 obuf
= current_buffer
;
728 Fset_buffer (XWINDOW (f
->selected_window
)->buffer
);
729 fmt
= (FRAME_ICONIFIED_P (f
) ? Vicon_title_format
: Vframe_title_format
);
730 frame_title_ptr
= frame_title_buf
;
731 len
= display_mode_element (XWINDOW (f
->selected_window
), 0, 0, 0,
732 0, sizeof (frame_title_buf
), fmt
);
734 set_buffer_internal (obuf
);
735 /* Set the name only if it's changed. This avoids consing
736 in the common case where it hasn't. (If it turns out that we've
737 already wasted too much time by walking through the list with
738 display_mode_element, then we might need to optimize at a higher
740 if (! STRINGP (f
->name
) || XSTRING (f
->name
)->size
!= len
741 || bcmp (frame_title_buf
, XSTRING (f
->name
)->data
, len
) != 0)
742 x_implicitly_set_name (f
, make_string (frame_title_buf
, len
), Qnil
);
745 #define frame_title_ptr ((char *)0)
746 #define store_frame_title(str, mincol, maxcol) 0
749 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
750 This can call eval. */
755 register struct window
*w
= XWINDOW (selected_window
);
757 struct gcpro gcpro1
, gcpro2
;
759 all_windows
= (update_mode_lines
|| buffer_shared
> 1
760 || windows_or_buffers_changed
);
762 /* Update all frame titles based on their buffer names, etc.
763 We do this before the menu bars so that the buffer-menu
764 will show the up-to-date frame titles.
766 This used to be done after the menu bars, for a reason that
767 was stated as follows but which I do not understand:
768 "We do this after the menu bars so that the frame will first
769 create its menu bar using the name `emacs' if no other name
770 has yet been specified."
771 I think that is no longer a concern. */
772 #ifdef HAVE_WINDOW_SYSTEM
773 if (windows_or_buffers_changed
|| update_mode_lines
)
775 Lisp_Object tail
, frame
;
777 FOR_EACH_FRAME (tail
, frame
)
778 if (FRAME_VISIBLE_P (XFRAME (frame
))
779 || FRAME_ICONIFIED_P (XFRAME (frame
)))
780 x_consider_frame_title (frame
);
784 /* Update the menu bar item lists, if appropriate.
785 This has to be done before any actual redisplay
786 or generation of display lines. */
789 Lisp_Object tail
, frame
;
790 int count
= specpdl_ptr
- specpdl
;
792 record_unwind_protect (Fstore_match_data
, Fmatch_data (Qnil
, Qnil
));
794 FOR_EACH_FRAME (tail
, frame
)
796 /* If a window on this frame changed size,
797 report that to the user and clear the size-change flag. */
798 if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame
)))
800 Lisp_Object functions
;
801 /* Clear flag first in case we get error below. */
802 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame
)) = 0;
803 functions
= Vwindow_size_change_functions
;
804 GCPRO2 (tail
, functions
);
805 while (CONSP (functions
))
807 call1 (XCONS (functions
)->car
, frame
);
808 functions
= XCONS (functions
)->cdr
;
813 update_menu_bar (XFRAME (frame
), 0);
817 unbind_to (count
, Qnil
);
820 update_menu_bar (selected_frame
, 1);
822 /* Motif needs this. See comment in xmenu.c.
823 Turn it off when pending_menu_activation is not defined. */
825 pending_menu_activation
= 0;
829 /* Do a frame update, taking possible shortcuts into account.
830 This is the main external entry point for redisplay.
832 If the last redisplay displayed an echo area message and that
833 message is no longer requested, we clear the echo area
834 or bring back the minibuffer if that is in use.
836 Do not call eval from within this function.
837 Calls to eval after the call to echo_area_display would confuse
838 the display_line mechanism and would cause a crash.
839 Calls to eval before that point will work most of the time,
840 but can still lose, because this function
841 can be called from signal handlers; with alarms set up;
842 or with synchronous processes running.
844 See Fcall_process; if you called it from here, it could be
845 entered recursively. */
847 static int do_verify_charstarts
;
849 /* Counter is used to clear the face cache
850 no more than once ever 1000 redisplays. */
851 static int clear_face_cache_count
;
853 /* Record the previous terminal frame we displayed. */
854 static FRAME_PTR previous_terminal_frame
;
859 redisplay_internal (0);
862 /* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay
863 is not in response to any user action; therefore, we should
864 preserve the echo area. (Actually, our caller does that job.)
865 Perhaps in the future avoid recentering windows
866 if it is not necessary; currently that causes some problems. */
869 redisplay_internal (preserve_echo_area
)
870 int preserve_echo_area
;
872 register struct window
*w
= XWINDOW (selected_window
);
876 register int tlbufpos
, tlendpos
;
878 int number_of_visible_frames
;
884 if (popup_activated ())
890 if (! FRAME_WINDOW_P (selected_frame
)
891 && previous_terminal_frame
!= selected_frame
)
893 /* Since frames on an ASCII terminal share the same display area,
894 displaying a different frame means redisplay the whole thing. */
895 windows_or_buffers_changed
++;
896 SET_FRAME_GARBAGED (selected_frame
);
897 XSETFRAME (Vterminal_frame
, selected_frame
);
899 previous_terminal_frame
= selected_frame
;
901 /* Set the visible flags for all frames.
902 Do this before checking for resized or garbaged frames; they want
903 to know if their frames are visible.
904 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
906 Lisp_Object tail
, frame
;
908 number_of_visible_frames
= 0;
910 FOR_EACH_FRAME (tail
, frame
)
912 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
914 if (FRAME_VISIBLE_P (XFRAME (frame
)))
915 number_of_visible_frames
++;
917 /* Clear out all the display lines in which we will generate the
918 glyphs to display. */
919 init_desired_glyphs (XFRAME (frame
));
923 /* Notice any pending interrupt request to change frame size. */
924 do_pending_window_change ();
928 redraw_garbaged_frames ();
932 prepare_menu_bars ();
934 if (windows_or_buffers_changed
)
937 /* Detect case that we need to write or remove a star in the mode line. */
938 if ((SAVE_MODIFF
< MODIFF
) != !NILP (w
->last_had_star
))
940 w
->update_mode_line
= Qt
;
941 if (buffer_shared
> 1)
945 /* If %c is in use, update it if needed. */
946 if (!NILP (w
->column_number_displayed
)
947 /* This alternative quickly identifies a common case
948 where no change is needed. */
949 && !(PT
== XFASTINT (w
->last_point
)
950 && XFASTINT (w
->last_modified
) >= MODIFF
951 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
)
952 && XFASTINT (w
->column_number_displayed
) != current_column ())
953 w
->update_mode_line
= Qt
;
955 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w
->frame
)) = -1;
957 all_windows
= update_mode_lines
|| buffer_shared
> 1;
959 /* If specs for an arrow have changed, do thorough redisplay
960 to ensure we remove any arrow that should no longer exist. */
961 if (! EQ (COERCE_MARKER (Voverlay_arrow_position
), last_arrow_position
)
962 || ! EQ (Voverlay_arrow_string
, last_arrow_string
))
965 /* Normally the message* functions will have already displayed and
966 updated the echo area, but the frame may have been trashed, or
967 the update may have been preempted, so display the echo area
969 if (echo_area_glyphs
|| previous_echo_glyphs
)
971 echo_area_display ();
975 /* If showing region, and mark has changed, must redisplay whole window. */
976 if (((!NILP (Vtransient_mark_mode
)
977 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
978 != !NILP (w
->region_showing
))
979 || (!NILP (w
->region_showing
)
980 && !EQ (w
->region_showing
,
981 Fmarker_position (XBUFFER (w
->buffer
)->mark
))))
982 this_line_bufpos
= -1;
984 tlbufpos
= this_line_bufpos
;
985 tlendpos
= this_line_endpos
;
986 if (!all_windows
&& tlbufpos
> 0 && NILP (w
->update_mode_line
)
987 && !current_buffer
->clip_changed
988 && FRAME_VISIBLE_P (XFRAME (w
->frame
))
989 && !FRAME_OBSCURED_P (XFRAME (w
->frame
))
990 /* Make sure recorded data applies to current buffer, etc */
991 && this_line_buffer
== current_buffer
992 && current_buffer
== XBUFFER (w
->buffer
)
993 && NILP (w
->force_start
)
994 /* Point must be on the line that we have info recorded about */
996 && PT
<= Z
- tlendpos
997 /* All text outside that line, including its final newline,
999 && ((XFASTINT (w
->last_modified
) >= MODIFF
1000 && (XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
))
1001 || (beg_unchanged
>= tlbufpos
- 1
1003 /* If selective display, can't optimize
1004 if the changes start at the beginning of the line. */
1005 && ((INTEGERP (current_buffer
->selective_display
)
1006 && XINT (current_buffer
->selective_display
) > 0
1007 ? (beg_unchanged
>= tlbufpos
1010 && end_unchanged
>= tlendpos
1011 && Z
- GPT
>= tlendpos
)))
1013 if (tlbufpos
> BEGV
&& FETCH_BYTE (tlbufpos
- 1) != '\n'
1015 || FETCH_BYTE (tlbufpos
) == '\n'))
1016 /* Former continuation line has disappeared by becoming empty */
1018 else if (XFASTINT (w
->last_modified
) < MODIFF
1019 || XFASTINT (w
->last_overlay_modified
) < OVERLAY_MODIFF
1020 || MINI_WINDOW_P (w
))
1022 /* We have to handle the case of continuation around a
1023 wide-column character (See the comment in indent.c around
1026 For instance, in the following case:
1028 -------- Insert --------
1029 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
1030 J_I_ ==> J_I_ `^^' are cursors.
1034 As we have to redraw the line above, we should goto cancel. */
1036 struct position val
;
1039 prevline
= find_next_newline (tlbufpos
, -1);
1040 val
= *compute_motion (prevline
, 0,
1041 XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0,
1044 1 << (BITS_PER_SHORT
- 1),
1045 1 << (BITS_PER_SHORT
- 1),
1046 window_internal_width (w
) - 1,
1047 XINT (w
->hscroll
), 0, w
);
1048 if (val
.hpos
!= this_line_start_hpos
)
1052 overlay_arrow_seen
= 0;
1053 zv_strings_seen
= 0;
1054 display_text_line (w
, tlbufpos
, this_line_vpos
, this_line_start_hpos
,
1055 pos_tab_offset (w
, tlbufpos
), 0);
1056 /* If line contains point, is not continued,
1057 and ends at same distance from eob as before, we win */
1058 if (cursor_vpos
>= 0 && this_line_bufpos
1059 && this_line_endpos
== tlendpos
)
1061 /* If this is not the window's last line,
1062 we must adjust the charstarts of the lines below. */
1063 if (this_line_vpos
+ 1
1064 < XFASTINT (w
->top
) + window_internal_height (w
))
1066 int left
= WINDOW_LEFT_MARGIN (w
);
1067 int *charstart_next_line
1068 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w
)))->charstarts
[this_line_vpos
+ 1];
1071 if (Z
- tlendpos
== ZV
)
1072 /* This line ends at end of (accessible part of) buffer.
1073 There is no newline to count. */
1074 adjust
= Z
- tlendpos
- charstart_next_line
[left
];
1076 /* This line ends in a newline.
1077 Must take account of the newline and the rest of the
1078 text that follows. */
1079 adjust
= Z
- tlendpos
+ 1 - charstart_next_line
[left
];
1081 adjust_window_charstarts (w
, this_line_vpos
, adjust
);
1084 if (!WINDOW_FULL_WIDTH_P (w
))
1085 preserve_other_columns (w
);
1091 else if (PT
== XFASTINT (w
->last_point
)
1092 /* Make sure the cursor was last displayed
1093 in this window. Otherwise we have to reposition it. */
1094 && XINT (w
->top
) <= FRAME_CURSOR_Y (selected_frame
)
1095 && (XINT (w
->top
) + XINT (w
->height
)
1096 > FRAME_CURSOR_Y (selected_frame
)))
1100 do_pending_window_change ();
1105 /* If highlighting the region, or if the cursor is in the echo area,
1106 then we can't just move the cursor. */
1107 else if (! (!NILP (Vtransient_mark_mode
)
1108 && !NILP (current_buffer
->mark_active
))
1109 && (w
== XWINDOW (current_buffer
->last_selected_window
)
1110 || highlight_nonselected_windows
)
1111 && NILP (w
->region_showing
)
1112 && !cursor_in_echo_area
)
1114 pos
= *compute_motion (tlbufpos
, 0,
1115 XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0,
1117 PT
, 2, - (1 << (BITS_PER_SHORT
- 1)),
1118 window_internal_width (w
) - 1,
1120 pos_tab_offset (w
, tlbufpos
), w
);
1123 int width
= window_internal_width (w
) - 1;
1124 FRAME_CURSOR_X (selected_frame
)
1125 = WINDOW_LEFT_MARGIN (w
) + minmax (0, pos
.hpos
, width
);
1126 FRAME_CURSOR_Y (selected_frame
) = this_line_vpos
;
1133 /* Text changed drastically or point moved off of line */
1134 cancel_line (this_line_vpos
, selected_frame
);
1137 this_line_bufpos
= 0;
1138 all_windows
|= buffer_shared
> 1;
1140 clear_face_cache_count
++;
1144 Lisp_Object tail
, frame
;
1147 /* Clear the face cache, only when we do a full redisplay
1148 and not too often either. */
1149 if (clear_face_cache_count
> 1000)
1151 clear_face_cache ();
1152 clear_face_cache_count
= 0;
1156 /* Recompute # windows showing selected buffer.
1157 This will be incremented each time such a window is displayed. */
1160 FOR_EACH_FRAME (tail
, frame
)
1162 FRAME_PTR f
= XFRAME (frame
);
1163 if (FRAME_WINDOW_P (f
) || f
== selected_frame
)
1166 /* Mark all the scroll bars to be removed; we'll redeem the ones
1167 we want when we redisplay their windows. */
1168 if (condemn_scroll_bars_hook
)
1169 (*condemn_scroll_bars_hook
) (f
);
1171 if (FRAME_VISIBLE_P (f
) && !FRAME_OBSCURED_P (f
))
1172 redisplay_windows (FRAME_ROOT_WINDOW (f
), preserve_echo_area
);
1174 /* Any scroll bars which redisplay_windows should have nuked
1175 should now go away. */
1176 if (judge_scroll_bars_hook
)
1177 (*judge_scroll_bars_hook
) (f
);
1181 else if (FRAME_VISIBLE_P (selected_frame
) && !FRAME_OBSCURED_P (selected_frame
))
1183 redisplay_window (selected_window
, 1, preserve_echo_area
);
1184 if (!WINDOW_FULL_WIDTH_P (w
))
1185 preserve_other_columns (w
);
1189 /* Prevent various kinds of signals during display update.
1190 stdio is not robust about handling signals,
1191 which can cause an apparent I/O error. */
1192 if (interrupt_input
)
1202 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
1206 if (!FRAMEP (XCONS (tail
)->car
))
1209 f
= XFRAME (XCONS (tail
)->car
);
1211 if ((FRAME_WINDOW_P (f
) || f
== selected_frame
)
1212 && FRAME_VISIBLE_P (f
) && !FRAME_OBSCURED_P (f
))
1214 pause
|= update_frame (f
, 0, 0);
1217 mark_window_display_accurate (f
->root_window
, 1);
1218 if (frame_up_to_date_hook
!= 0)
1219 (*frame_up_to_date_hook
) (f
);
1226 if (FRAME_VISIBLE_P (selected_frame
) && !FRAME_OBSCURED_P (selected_frame
))
1227 pause
= update_frame (selected_frame
, 0, 0);
1231 /* We may have called echo_area_display at the top of this
1232 function. If the echo area is on another frame, that may
1233 have put text on a frame other than the selected one, so the
1234 above call to update_frame would not have caught it. Catch
1237 Lisp_Object mini_window
;
1238 FRAME_PTR mini_frame
;
1240 mini_window
= FRAME_MINIBUF_WINDOW (selected_frame
);
1241 mini_frame
= XFRAME (WINDOW_FRAME (XWINDOW (mini_window
)));
1243 if (mini_frame
!= selected_frame
&& FRAME_WINDOW_P (mini_frame
))
1244 pause
|= update_frame (mini_frame
, 0, 0);
1248 /* If frame does not match, prevent doing single-line-update next time.
1249 Also, don't forget to check every line to update the arrow. */
1252 this_line_bufpos
= 0;
1253 if (!NILP (last_arrow_position
))
1255 last_arrow_position
= Qt
;
1256 last_arrow_string
= Qt
;
1258 /* If we pause after scrolling, some lines in current_frame
1259 may be null, so preserve_other_columns won't be able to
1260 preserve all the vertical-bar separators. So, avoid using it
1262 if (!WINDOW_FULL_WIDTH_P (w
))
1263 update_mode_lines
= 1;
1266 /* Now text on frame agrees with windows, so
1267 put info into the windows for partial redisplay to follow */
1271 register struct buffer
*b
= XBUFFER (w
->buffer
);
1273 blank_end_of_window
= 0;
1274 unchanged_modified
= BUF_MODIFF (b
);
1275 overlay_unchanged_modified
= BUF_OVERLAY_MODIFF (b
);
1276 beg_unchanged
= BUF_GPT (b
) - BUF_BEG (b
);
1277 end_unchanged
= BUF_Z (b
) - BUF_GPT (b
);
1279 XSETFASTINT (w
->last_point
, BUF_PT (b
));
1280 XSETFASTINT (w
->last_point_x
, FRAME_CURSOR_X (selected_frame
));
1281 XSETFASTINT (w
->last_point_y
, FRAME_CURSOR_Y (selected_frame
));
1284 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame
), 1);
1287 b
->clip_changed
= 0;
1288 w
->update_mode_line
= Qnil
;
1289 XSETFASTINT (w
->last_modified
, BUF_MODIFF (b
));
1290 XSETFASTINT (w
->last_overlay_modified
, BUF_OVERLAY_MODIFF (b
));
1292 = (BUF_MODIFF (XBUFFER (w
->buffer
)) > BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))
1295 /* Record if we are showing a region, so can make sure to
1296 update it fully at next redisplay. */
1297 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
1298 && (w
== XWINDOW (current_buffer
->last_selected_window
)
1299 || highlight_nonselected_windows
)
1300 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
1301 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
1304 w
->window_end_valid
= w
->buffer
;
1305 last_arrow_position
= COERCE_MARKER (Voverlay_arrow_position
);
1306 last_arrow_string
= Voverlay_arrow_string
;
1307 if (do_verify_charstarts
)
1308 verify_charstarts (w
);
1309 if (frame_up_to_date_hook
!= 0)
1310 (*frame_up_to_date_hook
) (selected_frame
);
1312 update_mode_lines
= 0;
1313 windows_or_buffers_changed
= 0;
1316 /* Start SIGIO interrupts coming again.
1317 Having them off during the code above
1318 makes it less likely one will discard output,
1319 but not impossible, since there might be stuff
1320 in the system buffer here.
1321 But it is much hairier to try to do anything about that. */
1323 if (interrupt_input
)
1327 /* If something has become visible now which was not before,
1328 redisplay again, so that we get them. */
1331 Lisp_Object tail
, frame
;
1334 FOR_EACH_FRAME (tail
, frame
)
1336 int this_is_visible
= 0;
1338 if (XFRAME (frame
)->visible
)
1339 this_is_visible
= 1;
1340 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
1341 if (XFRAME (frame
)->visible
)
1342 this_is_visible
= 1;
1344 if (this_is_visible
)
1348 if (new_count
!= number_of_visible_frames
)
1349 windows_or_buffers_changed
++;
1352 /* Change frame size now if a change is pending. */
1353 do_pending_window_change ();
1355 /* If we just did a pending size change, or have additional
1356 visible frames, redisplay again. */
1357 if (windows_or_buffers_changed
&& !pause
)
1361 /* Redisplay, but leave alone any recent echo area message
1362 unless another message has been requested in its place.
1364 This is useful in situations where you need to redisplay but no
1365 user action has occurred, making it inappropriate for the message
1366 area to be cleared. See tracking_off and
1367 wait_reading_process_input for examples of these situations. */
1369 redisplay_preserve_echo_area ()
1371 if (echo_area_glyphs
== 0 && previous_echo_glyphs
!= 0)
1373 echo_area_glyphs
= previous_echo_glyphs
;
1374 redisplay_internal (1);
1375 echo_area_glyphs
= 0;
1378 redisplay_internal (1);
1382 mark_window_display_accurate (window
, flag
)
1386 register struct window
*w
;
1388 for (;!NILP (window
); window
= w
->next
)
1390 if (!WINDOWP (window
)) abort ();
1391 w
= XWINDOW (window
);
1393 if (!NILP (w
->buffer
))
1395 XSETFASTINT (w
->last_modified
,
1396 !flag
? 0 : BUF_MODIFF (XBUFFER (w
->buffer
)));
1397 XSETFASTINT (w
->last_overlay_modified
,
1398 !flag
? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)));
1400 = (BUF_MODIFF (XBUFFER (w
->buffer
)) > BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))
1403 /* Record if we are showing a region, so can make sure to
1404 update it fully at next redisplay. */
1405 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
1406 && (w
== XWINDOW (current_buffer
->last_selected_window
)
1407 || highlight_nonselected_windows
)
1408 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
1409 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
1413 w
->window_end_valid
= w
->buffer
;
1414 w
->update_mode_line
= Qnil
;
1415 if (!NILP (w
->buffer
) && flag
)
1416 XBUFFER (w
->buffer
)->clip_changed
= 0;
1418 if (!NILP (w
->vchild
))
1419 mark_window_display_accurate (w
->vchild
, flag
);
1420 if (!NILP (w
->hchild
))
1421 mark_window_display_accurate (w
->hchild
, flag
);
1426 last_arrow_position
= COERCE_MARKER (Voverlay_arrow_position
);
1427 last_arrow_string
= Voverlay_arrow_string
;
1431 /* t is unequal to any useful value of Voverlay_arrow_... */
1432 last_arrow_position
= Qt
;
1433 last_arrow_string
= Qt
;
1437 /* Update the menu bar item list for frame F.
1438 This has to be done before we start to fill in any display lines,
1439 because it can call eval.
1441 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1444 update_menu_bar (f
, save_match_data
)
1446 int save_match_data
;
1448 struct buffer
*old
= current_buffer
;
1450 register struct window
*w
;
1452 window
= FRAME_SELECTED_WINDOW (f
);
1453 w
= XWINDOW (window
);
1455 if (update_mode_lines
)
1456 w
->update_mode_line
= Qt
;
1458 if (FRAME_WINDOW_P (f
)
1460 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1461 FRAME_EXTERNAL_MENU_BAR (f
)
1463 FRAME_MENU_BAR_LINES (f
) > 0
1465 : FRAME_MENU_BAR_LINES (f
) > 0)
1467 /* If the user has switched buffers or windows, we need to
1468 recompute to reflect the new bindings. But we'll
1469 recompute when update_mode_lines is set too; that means
1470 that people can use force-mode-line-update to request
1471 that the menu bar be recomputed. The adverse effect on
1472 the rest of the redisplay algorithm is about the same as
1473 windows_or_buffers_changed anyway. */
1474 if (windows_or_buffers_changed
1475 || !NILP (w
->update_mode_line
)
1476 || ((BUF_SAVE_MODIFF (XBUFFER (w
->buffer
))
1477 < BUF_MODIFF (XBUFFER (w
->buffer
)))
1478 != !NILP (w
->last_had_star
))
1479 || ((!NILP (Vtransient_mark_mode
)
1480 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
1481 != !NILP (w
->region_showing
)))
1483 struct buffer
*prev
= current_buffer
;
1484 int count
= specpdl_ptr
- specpdl
;
1486 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1487 if (save_match_data
)
1488 record_unwind_protect (Fstore_match_data
, Fmatch_data (Qnil
, Qnil
));
1489 if (NILP (Voverriding_local_map_menu_flag
))
1491 specbind (Qoverriding_terminal_local_map
, Qnil
);
1492 specbind (Qoverriding_local_map
, Qnil
);
1495 /* Run the Lucid hook. */
1496 call1 (Vrun_hooks
, Qactivate_menubar_hook
);
1497 /* If it has changed current-menubar from previous value,
1498 really recompute the menubar from the value. */
1499 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1500 call0 (Qrecompute_lucid_menubar
);
1501 safe_run_hooks (Qmenu_bar_update_hook
);
1502 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1503 /* Redisplay the menu bar in case we changed it. */
1504 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1505 if (FRAME_WINDOW_P (f
))
1506 set_frame_menubar (f
, 0, 0);
1508 /* On a terminal screen, the menu bar is an ordinary screen
1509 line, and this makes it get updated. */
1510 w
->update_mode_line
= Qt
;
1511 #else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
1512 /* In the non-toolkit version, the menu bar is an ordinary screen
1513 line, and this makes it get updated. */
1514 w
->update_mode_line
= Qt
;
1515 #endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
1517 unbind_to (count
, Qnil
);
1518 set_buffer_internal_1 (prev
);
1525 /* Redisplay WINDOW and its subwindows and siblings. */
1528 redisplay_windows (window
, preserve_echo_area
)
1530 int preserve_echo_area
;
1532 for (; !NILP (window
); window
= XWINDOW (window
)->next
)
1533 redisplay_window (window
, 0, preserve_echo_area
);
1536 /* Return value in display table DP (Lisp_Char_Table *) for character
1537 C. Since a display table doesn't have any parent, we don't have to
1538 follow parent. Do not call this function directly but use the
1539 macro DISP_CHAR_VECTOR. */
1541 disp_char_vector (dp
, c
)
1542 struct Lisp_Char_Table
*dp
;
1548 if (SINGLE_BYTE_CHAR_P (c
)) return (dp
->contents
[c
]);
1550 SPLIT_NON_ASCII_CHAR (c
, code
[0], code
[1], code
[2]);
1551 if (code
[0] != CHARSET_COMPOSITION
)
1553 if (code
[1] < 32) code
[1] = -1;
1554 else if (code
[2] < 32) code
[2] = -1;
1556 /* Here, the possible range of CODE[0] (== charset ID) is
1557 128..MAX_CHARSET. Since the top level char table contains data
1558 for multibyte characters after 256th element, we must increment
1559 CODE[0] by 128 to get a correct index. */
1561 code
[3] = -1; /* anchor */
1563 for (i
= 0; code
[i
] >= 0; i
++, dp
= XCHAR_TABLE (val
))
1565 val
= dp
->contents
[code
[i
]];
1566 if (!SUB_CHAR_TABLE_P (val
))
1567 return (NILP (val
) ? dp
->defalt
: val
);
1569 /* Here, VAL is a sub char table. We return the default value of it. */
1570 return (dp
->defalt
);
1573 /* Redisplay window WINDOW and its subwindows. */
1576 redisplay_window (window
, just_this_one
, preserve_echo_area
)
1578 int just_this_one
, preserve_echo_area
;
1580 register struct window
*w
= XWINDOW (window
);
1581 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1583 register int lpoint
= PT
;
1584 struct buffer
*old
= current_buffer
;
1585 register int width
= window_internal_width (w
) - 1;
1586 register int startp
;
1587 register int hscroll
= XINT (w
->hscroll
);
1588 struct position pos
;
1591 int update_mode_line
;
1592 struct Lisp_Char_Table
*dp
= window_display_table (w
);
1594 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1596 /* If this is a combination window, do its children; that's all. */
1598 if (!NILP (w
->vchild
))
1600 redisplay_windows (w
->vchild
, preserve_echo_area
);
1603 if (!NILP (w
->hchild
))
1605 redisplay_windows (w
->hchild
, preserve_echo_area
);
1608 if (NILP (w
->buffer
))
1611 height
= window_internal_height (w
);
1612 update_mode_line
= (!NILP (w
->update_mode_line
) || update_mode_lines
);
1613 if (XBUFFER (w
->buffer
)->clip_changed
)
1614 update_mode_line
= 1;
1616 if (MINI_WINDOW_P (w
))
1618 if (w
== XWINDOW (echo_area_window
) && echo_area_glyphs
)
1619 /* We've already displayed the echo area glyphs in this window. */
1620 goto finish_scroll_bars
;
1621 else if (w
!= XWINDOW (minibuf_window
))
1623 /* This is a minibuffer, but it's not the currently active one,
1625 int vpos
= XFASTINT (w
->top
);
1628 for (i
= 0; i
< height
; i
++)
1630 get_display_line (f
, vpos
+ i
, 0);
1631 display_string (w
, vpos
+ i
, "", 0,
1632 FRAME_LEFT_SCROLL_BAR_WIDTH (f
),
1636 goto finish_scroll_bars
;
1640 /* Otherwise set up data on this window; select its buffer and point value */
1642 if (update_mode_line
)
1643 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1645 set_buffer_temp (XBUFFER (w
->buffer
));
1649 /* If %c is in mode line, update it if needed. */
1650 if (!NILP (w
->column_number_displayed
)
1651 /* This alternative quickly identifies a common case
1652 where no change is needed. */
1653 && !(PT
== XFASTINT (w
->last_point
)
1654 && XFASTINT (w
->last_modified
) >= MODIFF
1655 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
)
1656 && XFASTINT (w
->column_number_displayed
) != current_column ())
1657 update_mode_line
= 1;
1659 /* Count number of windows showing the selected buffer.
1660 An indirect buffer counts as its base buffer. */
1664 struct buffer
*current_base
, *window_base
;
1665 current_base
= current_buffer
;
1666 window_base
= XBUFFER (XWINDOW (selected_window
)->buffer
);
1667 if (current_base
->base_buffer
)
1668 current_base
= current_base
->base_buffer
;
1669 if (window_base
->base_buffer
)
1670 window_base
= window_base
->base_buffer
;
1671 if (current_base
== window_base
)
1675 /* POINT refers normally to the selected window.
1676 For any other window, set up appropriate value. */
1678 if (!EQ (window
, selected_window
))
1680 int new_pt
= marker_position (w
->pointm
);
1684 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1686 else if (new_pt
> (ZV
- 1))
1689 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1691 /* We don't use SET_PT so that the point-motion hooks don't run. */
1692 BUF_PT (current_buffer
) = new_pt
;
1695 /* If any of the character widths specified in the display table
1696 have changed, invalidate the width run cache. It's true that this
1697 may be a bit late to catch such changes, but the rest of
1698 redisplay goes (non-fatally) haywire when the display table is
1699 changed, so why should we worry about doing any better? */
1700 if (current_buffer
->width_run_cache
)
1702 struct Lisp_Char_Table
*disptab
= buffer_display_table ();
1704 if (! disptab_matches_widthtab (disptab
,
1705 XVECTOR (current_buffer
->width_table
)))
1707 invalidate_region_cache (current_buffer
,
1708 current_buffer
->width_run_cache
,
1710 recompute_width_table (current_buffer
, disptab
);
1714 /* If window-start is screwed up, choose a new one. */
1715 if (XMARKER (w
->start
)->buffer
!= current_buffer
)
1718 startp
= marker_position (w
->start
);
1720 /* If someone specified a new starting point but did not insist,
1721 check whether it can be used. */
1722 if (!NILP (w
->optional_new_start
))
1724 w
->optional_new_start
= Qnil
;
1725 /* Check whether this start pos is usable given where point is. */
1727 pos
= *compute_motion (startp
, 0,
1728 (((EQ (window
, minibuf_window
)
1730 ? minibuf_prompt_width
: 0)
1731 + (hscroll
? 1 - hscroll
: 0)),
1734 /* BUG FIX: See the comment of
1735 Fpos_visible_in_window_p (window.c). */
1736 - (1 << (BITS_PER_SHORT
- 1)),
1737 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1738 /* If PT does fit on the screen, we will use this start pos,
1739 so do so by setting force_start. */
1740 if (pos
.bufpos
== PT
)
1741 w
->force_start
= Qt
;
1744 /* Handle case where place to start displaying has been specified,
1745 unless the specified location is outside the accessible range. */
1746 if (!NILP (w
->force_start
))
1748 w
->force_start
= Qnil
;
1749 /* Forget any recorded base line for line number display. */
1750 w
->base_line_number
= Qnil
;
1751 /* Redisplay the mode line. Select the buffer properly for that.
1752 Also, run the hook window-scroll-functions
1753 because we have scrolled. */
1754 /* Note, we do this after clearing force_start because
1755 if there's an error, it is better to forget about force_start
1756 than to get into an infinite loop calling the hook functions
1757 and having them get more errors. */
1758 if (!update_mode_line
1759 || ! NILP (Vwindow_scroll_functions
))
1761 Lisp_Object temp
[3];
1763 set_buffer_temp (old
);
1764 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1765 update_mode_line
= 1;
1766 w
->update_mode_line
= Qt
;
1767 if (! NILP (Vwindow_scroll_functions
))
1769 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1770 make_number (startp
));
1771 startp
= marker_position (w
->start
);
1774 XSETFASTINT (w
->last_modified
, 0);
1775 XSETFASTINT (w
->last_overlay_modified
, 0);
1776 if (startp
< BEGV
) startp
= BEGV
;
1777 if (startp
> ZV
) startp
= ZV
;
1778 try_window (window
, startp
);
1779 if (cursor_vpos
< 0)
1781 /* If point does not appear, move point so it does appear */
1782 pos
= *compute_motion (startp
, 0,
1783 (((EQ (window
, minibuf_window
)
1785 ? minibuf_prompt_width
: 0)
1786 + (hscroll
? 1 - hscroll
: 0)),
1789 - (1 << (BITS_PER_SHORT
- 1)),
1790 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1791 BUF_PT (current_buffer
) = pos
.bufpos
;
1792 if (w
!= XWINDOW (selected_window
))
1793 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
1796 if (current_buffer
== old
)
1798 FRAME_CURSOR_X (f
) = (WINDOW_LEFT_MARGIN (w
)
1799 + minmax (0, pos
.hpos
, width
));
1800 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1802 /* If we are highlighting the region,
1803 then we just changed the region, so redisplay to show it. */
1804 if (!NILP (Vtransient_mark_mode
)
1805 && !NILP (current_buffer
->mark_active
))
1807 cancel_my_columns (XWINDOW (window
));
1808 try_window (window
, startp
);
1814 /* Handle case where text has not changed, only point,
1815 and it has not moved off the frame. */
1817 /* This code is not used for minibuffer for the sake of
1818 the case of redisplaying to replace an echo area message;
1819 since in that case the minibuffer contents per se are usually unchanged.
1820 This code is of no real use in the minibuffer since
1821 the handling of this_line_bufpos, etc.,
1822 in redisplay handles the same cases. */
1824 if (XFASTINT (w
->last_modified
) >= MODIFF
1825 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
1826 && PT
>= startp
&& !current_buffer
->clip_changed
1827 && (just_this_one
|| WINDOW_FULL_WIDTH_P (w
))
1828 /* If force-mode-line-update was called, really redisplay;
1829 that's how redisplay is forced after e.g. changing
1830 buffer-invisibility-spec. */
1831 && NILP (w
->update_mode_line
)
1832 /* Can't use this case if highlighting a region. */
1833 && !(!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1834 && NILP (w
->region_showing
)
1835 /* If end pos is out of date, scroll bar and percentage will be wrong */
1836 && INTEGERP (w
->window_end_vpos
)
1837 && XFASTINT (w
->window_end_vpos
) < XFASTINT (w
->height
)
1838 && !EQ (window
, minibuf_window
)
1839 && (!MARKERP (Voverlay_arrow_position
)
1840 || current_buffer
!= XMARKER (Voverlay_arrow_position
)->buffer
))
1842 /* All positions in this clause are relative to the window edge. */
1844 int this_scroll_margin
= scroll_margin
;
1845 int last_point_y
= XFASTINT (w
->last_point_y
) - XINT (w
->top
);
1846 int last_point_x
= (XFASTINT (w
->last_point_x
) - WINDOW_LEFT_MARGIN (w
));
1848 /* Find where PT is located now on the frame. */
1849 /* Check just_this_one as a way of verifying that the
1850 window edges have not changed. */
1851 if (PT
== XFASTINT (w
->last_point
) && just_this_one
)
1853 pos
.hpos
= last_point_x
;
1854 pos
.vpos
= last_point_y
;
1857 else if (PT
> XFASTINT (w
->last_point
)
1858 && XFASTINT (w
->last_point
) > startp
&& just_this_one
1859 /* We can't use this if point is in the left margin of a
1860 hscrolled window, because w->last_point_x has been
1861 clipped to the window edges. */
1862 && !(last_point_x
<= 0 && hscroll
))
1864 pos
= *compute_motion (XFASTINT (w
->last_point
),
1865 last_point_y
, last_point_x
, 0,
1867 /* BUG FIX: See the comment of
1868 Fpos_visible_in_window_p (window.c). */
1869 - (1 << (BITS_PER_SHORT
- 1)),
1871 pos_tab_offset (w
, startp
), w
);
1875 pos
= *compute_motion (startp
, 0, (hscroll
? 1 - hscroll
: 0), 0,
1877 /* BUG FIX: See the comment of
1878 Fpos_visible_in_window_p (window.c). */
1879 - (1 << (BITS_PER_SHORT
- 1)),
1881 pos_tab_offset (w
, startp
), w
);
1884 /* Don't use a scroll margin that is negative or too large. */
1885 if (this_scroll_margin
< 0)
1886 this_scroll_margin
= 0;
1888 if (XINT (w
->height
) < 4 * scroll_margin
)
1889 this_scroll_margin
= XINT (w
->height
) / 4;
1891 /* If point fits on the screen, and not within the scroll margin,
1893 if (pos
.vpos
< height
- this_scroll_margin
1894 && (pos
.vpos
>= this_scroll_margin
|| startp
== BEGV
))
1896 /* Ok, point is still on frame */
1897 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
1899 /* These variables are supposed to be origin 1 */
1900 FRAME_CURSOR_X (f
) = (WINDOW_LEFT_MARGIN (w
)
1901 + minmax (0, pos
.hpos
, width
));
1902 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1904 /* This doesn't do the trick, because if a window to the right of
1905 this one must be redisplayed, this does nothing because there
1906 is nothing in DesiredFrame yet, and then the other window is
1907 redisplayed, making likes that are empty in this window's columns.
1908 if (WINDOW_FULL_WIDTH_P (w))
1909 preserve_my_columns (w);
1913 /* Don't bother trying redisplay with same start;
1914 we already know it will lose */
1916 /* If current starting point was originally the beginning of a line
1917 but no longer is, find a new starting point. */
1918 else if (!NILP (w
->start_at_line_beg
)
1920 || FETCH_BYTE (startp
- 1) == '\n'))
1924 else if (just_this_one
&& !MINI_WINDOW_P (w
)
1926 && XFASTINT (w
->last_modified
)
1927 /* or else vmotion on first line won't work. */
1928 && ! NILP (w
->start_at_line_beg
)
1929 && ! EQ (w
->window_end_valid
, Qnil
)
1930 && do_id
&& !current_buffer
->clip_changed
1931 && !blank_end_of_window
1932 && WINDOW_FULL_WIDTH_P (w
)
1933 /* Can't use this case if highlighting a region. */
1934 && !(!NILP (Vtransient_mark_mode
)
1935 && !NILP (current_buffer
->mark_active
))
1936 /* Don't use try_window_id if newline
1937 doesn't display as the end of a line. */
1938 && !(dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, '\n')))
1939 && NILP (w
->region_showing
)
1940 && EQ (last_arrow_position
, COERCE_MARKER (Voverlay_arrow_position
))
1941 && EQ (last_arrow_string
, Voverlay_arrow_string
)
1942 && (tem
= try_window_id (FRAME_SELECTED_WINDOW (f
)))
1945 /* tem > 0 means success. tem == -1 means choose new start.
1946 tem == -2 means try again with same start,
1947 and nothing but whitespace follows the changed stuff.
1948 tem == 0 means try again with same start. */
1952 else if (startp
>= BEGV
&& startp
<= ZV
1954 /* Avoid starting at end of buffer. */
1955 #if 0 /* This change causes trouble for M-! finger & RET.
1956 It will have to be considered later. */
1957 || ! EQ (window
, selected_window
)
1958 /* Don't do the recentering if redisplay
1959 is not for no user action. */
1960 || preserve_echo_area
1963 || (XFASTINT (w
->last_modified
) >= MODIFF
1964 && XFASTINT (w
->last_overlay_modified
) >= OVERLAY_MODIFF
)))
1966 /* Try to redisplay starting at same place as before */
1967 /* If point has not moved off frame, accept the results */
1968 try_window (window
, startp
);
1969 if (cursor_vpos
>= 0)
1971 if (!just_this_one
|| current_buffer
->clip_changed
1972 || beg_unchanged
< startp
)
1973 /* Forget any recorded base line for line number display. */
1974 w
->base_line_number
= Qnil
;
1978 cancel_my_columns (w
);
1981 XSETFASTINT (w
->last_modified
, 0);
1982 XSETFASTINT (w
->last_overlay_modified
, 0);
1983 /* Redisplay the mode line. Select the buffer properly for that. */
1984 if (!update_mode_line
)
1986 set_buffer_temp (old
);
1987 set_buffer_internal_1 (XBUFFER (w
->buffer
));
1988 update_mode_line
= 1;
1989 w
->update_mode_line
= Qt
;
1992 /* Try to scroll by specified few lines */
1994 if (scroll_conservatively
&& !current_buffer
->clip_changed
1995 && startp
>= BEGV
&& startp
<= ZV
)
1997 int this_scroll_margin
= scroll_margin
;
1998 int scroll_margin_pos
;
2000 /* Don't use a scroll margin that is negative or too large. */
2001 if (this_scroll_margin
< 0)
2002 this_scroll_margin
= 0;
2004 if (XINT (w
->height
) < 4 * this_scroll_margin
)
2005 this_scroll_margin
= XINT (w
->height
) / 4;
2007 scroll_margin_pos
= Z
- XFASTINT (w
->window_end_pos
);
2008 if (this_scroll_margin
)
2010 pos
= *vmotion (scroll_margin_pos
, -this_scroll_margin
, w
);
2011 scroll_margin_pos
= pos
.bufpos
;
2013 if (PT
>= scroll_margin_pos
)
2015 struct position pos
;
2016 pos
= *compute_motion (scroll_margin_pos
, 0, 0, 0,
2017 PT
, XFASTINT (w
->height
), 0,
2018 XFASTINT (w
->width
), XFASTINT (w
->hscroll
),
2019 pos_tab_offset (w
, startp
), w
);
2020 if (pos
.vpos
> scroll_conservatively
)
2023 pos
= *vmotion (startp
, pos
.vpos
+ 1, w
);
2025 if (! NILP (Vwindow_scroll_functions
))
2027 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
2028 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
2029 make_number (pos
.bufpos
));
2030 pos
.bufpos
= marker_position (w
->start
);
2032 try_window (window
, pos
.bufpos
);
2033 if (cursor_vpos
>= 0)
2035 if (!just_this_one
|| current_buffer
->clip_changed
2036 || beg_unchanged
< startp
)
2037 /* Forget any recorded base line for line number display. */
2038 w
->base_line_number
= Qnil
;
2042 cancel_my_columns (w
);
2045 scroll_margin_pos
= startp
;
2046 if (this_scroll_margin
)
2048 pos
= *vmotion (scroll_margin_pos
, this_scroll_margin
, w
);
2049 scroll_margin_pos
= pos
.bufpos
;
2051 if (PT
< scroll_margin_pos
)
2053 struct position pos
;
2054 pos
= *compute_motion (PT
, 0, 0, 0,
2055 scroll_margin_pos
, XFASTINT (w
->height
), 0,
2056 XFASTINT (w
->width
), XFASTINT (w
->hscroll
),
2057 pos_tab_offset (w
, startp
), w
);
2058 if (pos
.vpos
> scroll_conservatively
)
2061 pos
= *vmotion (startp
, -pos
.vpos
, w
);
2063 if (! NILP (Vwindow_scroll_functions
))
2065 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
2066 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
2067 make_number (pos
.bufpos
));
2068 pos
.bufpos
= marker_position (w
->start
);
2070 try_window (window
, pos
.bufpos
);
2071 if (cursor_vpos
>= 0)
2073 if (!just_this_one
|| current_buffer
->clip_changed
2074 || beg_unchanged
< startp
)
2075 /* Forget any recorded base line for line number display. */
2076 w
->base_line_number
= Qnil
;
2080 cancel_my_columns (w
);
2085 if (scroll_step
&& !current_buffer
->clip_changed
2086 && startp
>= BEGV
&& startp
<= ZV
)
2090 pos
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), scroll_step
, w
);
2091 if (pos
.vpos
>= height
)
2095 pos
= *vmotion (startp
, (PT
< startp
? - scroll_step
: scroll_step
), w
);
2097 if (PT
>= pos
.bufpos
)
2099 if (! NILP (Vwindow_scroll_functions
))
2101 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
2102 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
2103 make_number (pos
.bufpos
));
2104 pos
.bufpos
= marker_position (w
->start
);
2106 try_window (window
, pos
.bufpos
);
2107 if (cursor_vpos
>= 0)
2109 if (!just_this_one
|| current_buffer
->clip_changed
2110 || beg_unchanged
< startp
)
2111 /* Forget any recorded base line for line number display. */
2112 w
->base_line_number
= Qnil
;
2116 cancel_my_columns (w
);
2121 /* Finally, just choose place to start which centers point */
2124 /* Forget any previously recorded base line for line number display. */
2125 w
->base_line_number
= Qnil
;
2127 pos
= *vmotion (PT
, - (height
/ 2), w
);
2128 /* Set startp here explicitly in case that helps avoid an infinite loop
2129 in case the window-scroll-functions functions get errors. */
2130 Fset_marker (w
->start
, make_number (pos
.bufpos
), Qnil
);
2131 if (! NILP (Vwindow_scroll_functions
))
2133 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
2134 make_number (pos
.bufpos
));
2135 pos
.bufpos
= marker_position (w
->start
);
2137 try_window (window
, pos
.bufpos
);
2139 startp
= marker_position (w
->start
);
2140 w
->start_at_line_beg
2141 = (startp
== BEGV
|| FETCH_BYTE (startp
- 1) == '\n') ? Qt
: Qnil
;
2144 if ((update_mode_line
2145 /* If window not full width, must redo its mode line
2146 if the window to its side is being redone */
2147 || (!just_this_one
&& !WINDOW_FULL_WIDTH_P (w
))
2148 || INTEGERP (w
->base_line_pos
)
2149 || (!NILP (w
->column_number_displayed
)
2150 && XFASTINT (w
->column_number_displayed
) != current_column ()))
2151 && height
!= XFASTINT (w
->height
))
2152 display_mode_line (w
);
2153 if (! line_number_displayed
2154 && ! BUFFERP (w
->base_line_pos
))
2156 w
->base_line_pos
= Qnil
;
2157 w
->base_line_number
= Qnil
;
2160 /* When we reach a frame's selected window, redo the frame's menu bar. */
2161 if (update_mode_line
2162 && (FRAME_WINDOW_P (f
)
2164 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
2165 FRAME_EXTERNAL_MENU_BAR (f
)
2167 FRAME_MENU_BAR_LINES (f
) > 0
2169 : FRAME_MENU_BAR_LINES (f
) > 0)
2170 && EQ (FRAME_SELECTED_WINDOW (f
), window
))
2171 display_menu_bar (w
);
2174 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2176 int start
, end
, whole
;
2178 /* Calculate the start and end positions for the current window.
2179 At some point, it would be nice to choose between scrollbars
2180 which reflect the whole buffer size, with special markers
2181 indicating narrowing, and scrollbars which reflect only the
2184 Note that minibuffers sometimes aren't displaying any text. */
2185 if (! MINI_WINDOW_P (w
)
2186 || (w
== XWINDOW (minibuf_window
) && ! echo_area_glyphs
))
2189 start
= marker_position (w
->start
) - BEGV
;
2190 /* I don't think this is guaranteed to be right. For the
2191 moment, we'll pretend it is. */
2192 end
= (Z
- XINT (w
->window_end_pos
)) - BEGV
;
2194 if (end
< start
) end
= start
;
2195 if (whole
< (end
- start
)) whole
= end
- start
;
2198 start
= end
= whole
= 0;
2200 /* Indicate what this scroll bar ought to be displaying now. */
2201 (*set_vertical_scroll_bar_hook
) (w
, end
- start
, whole
, start
);
2203 /* Note that we actually used the scroll bar attached to this window,
2204 so it shouldn't be deleted at the end of redisplay. */
2205 (*redeem_scroll_bar_hook
) (w
);
2208 BUF_PT (current_buffer
) = opoint
;
2209 if (update_mode_line
)
2210 set_buffer_internal_1 (old
);
2212 set_buffer_temp (old
);
2213 BUF_PT (current_buffer
) = lpoint
;
2216 /* Do full redisplay on one window, starting at position `pos'. */
2219 try_window (window
, pos
)
2223 register struct window
*w
= XWINDOW (window
);
2224 register int height
= window_internal_height (w
);
2225 register int vpos
= XFASTINT (w
->top
);
2226 register int last_text_vpos
= vpos
;
2227 FRAME_PTR f
= XFRAME (w
->frame
);
2228 int width
= window_internal_width (w
) - 1;
2229 struct position val
;
2231 /* POS should never be out of range! */
2232 if (pos
< XBUFFER (w
->buffer
)->begv
2233 || pos
> XBUFFER (w
->buffer
)->zv
)
2236 Fset_marker (w
->start
, make_number (pos
), Qnil
);
2238 overlay_arrow_seen
= 0;
2239 zv_strings_seen
= 0;
2240 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
2241 val
.ovstring_chars_done
= 0;
2242 val
.tab_offset
= pos_tab_offset (w
, pos
);
2244 while (--height
>= 0)
2246 val
= *display_text_line (w
, pos
, vpos
, val
.hpos
, val
.tab_offset
,
2247 val
.ovstring_chars_done
);
2248 /* The following code is omitted because we maintain tab_offset
2251 tab_offset
+= width
;
2252 if (val
.vpos
) tab_offset
= 0;
2255 if (pos
!= val
.bufpos
)
2258 #ifdef USE_TEXT_PROPERTIES
2259 Lisp_Object invis_prop
;
2260 invis_prop
= Fget_char_property (val
.bufpos
-1, Qinvisible
, window
);
2261 invis
= TEXT_PROP_MEANS_INVISIBLE (invis_prop
);
2265 /* Next line, unless prev line ended in end of buffer with no cr */
2267 && (FETCH_BYTE (val
.bufpos
- 1) != '\n' || invis
));
2272 /* If last line is continued in middle of character,
2273 include the split character in the text considered on the frame */
2274 if (val
.hpos
< (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
2277 /* If bottom just moved off end of frame, change mode line percentage. */
2278 if (XFASTINT (w
->window_end_pos
) == 0
2280 w
->update_mode_line
= Qt
;
2282 /* Say where last char on frame will be, once redisplay is finished. */
2283 XSETFASTINT (w
->window_end_pos
, Z
- pos
);
2284 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
- XFASTINT (w
->top
));
2285 /* But that is not valid info until redisplay finishes. */
2286 w
->window_end_valid
= Qnil
;
2289 /* Try to redisplay when buffer is modified locally,
2290 computing insert/delete line to preserve text outside
2291 the bounds of the changes.
2292 Return 1 if successful, 0 if if cannot tell what to do,
2293 or -1 to tell caller to find a new window start,
2294 or -2 to tell caller to do normal redisplay with same window start. */
2297 try_window_id (window
)
2301 register struct window
*w
= XWINDOW (window
);
2302 register int height
= window_internal_height (w
);
2303 FRAME_PTR f
= XFRAME (w
->frame
);
2304 int top
= XFASTINT (w
->top
);
2305 int start
= marker_position (w
->start
);
2306 int width
= window_internal_width (w
) - 1;
2307 int hscroll
= XINT (w
->hscroll
);
2308 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
2311 register int i
, tem
;
2312 int last_text_vpos
= 0;
2314 int selective
= (INTEGERP (current_buffer
->selective_display
)
2315 ? XINT (current_buffer
->selective_display
)
2316 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2318 struct position val
, bp
, ep
, xp
, pp
;
2319 int scroll_amount
= 0;
2323 if (GPT
- BEG
< beg_unchanged
)
2324 beg_unchanged
= GPT
- BEG
;
2325 if (Z
- GPT
< end_unchanged
)
2326 end_unchanged
= Z
- GPT
;
2328 if (beg_unchanged
+ BEG
< start
)
2329 return 0; /* Give up if changes go above top of window */
2331 /* Find position before which nothing is changed. */
2332 bp
= *compute_motion (start
, 0, lmargin
, 0,
2333 min (ZV
, beg_unchanged
+ BEG
), height
,
2334 /* BUG FIX: See the comment of
2335 Fpos_visible_in_window_p() (window.c). */
2336 - (1 << (BITS_PER_SHORT
- 1)),
2337 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2338 if (bp
.vpos
>= height
)
2342 /* All changes are beyond the window end, and point is on the screen.
2343 We don't need to change the text at all.
2344 But we need to update window_end_pos to account for
2345 any change in buffer size. */
2346 bp
= *compute_motion (start
, 0, lmargin
, 0,
2348 /* BUG FIX: See the comment of
2349 Fpos_visible_in_window_p() (window.c). */
2350 - (1 << (BITS_PER_SHORT
- 1)),
2351 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2352 XSETFASTINT (w
->window_end_vpos
, height
);
2353 XSETFASTINT (w
->window_end_pos
, Z
- bp
.bufpos
);
2361 /* Find beginning of that frame line. Must display from there. */
2362 bp
= *vmotion (bp
.bufpos
, 0, w
);
2370 /* If about to start displaying at the beginning of a continuation line,
2371 really start with previous frame line, in case it was not
2372 continued when last redisplayed */
2373 if ((bp
.contin
&& bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0)
2375 /* Likewise if we have to worry about selective display. */
2376 (selective
> 0 && bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0))
2378 bp
= *vmotion (bp
.bufpos
, -1, w
);
2382 val
.tab_offset
= bp
.tab_offset
; /* Update tab offset. */
2384 if (bp
.contin
&& bp
.hpos
!= lmargin
)
2386 val
.hpos
= bp
.prevhpos
- width
+ lmargin
;
2387 val
.tab_offset
= bp
.tab_offset
+ bp
.prevhpos
- width
;
2394 /* Find first visible newline after which no more is changed. */
2395 tem
= find_next_newline (Z
- max (end_unchanged
, Z
- ZV
), 1);
2397 while (tem
< ZV
- 1 && (indented_beyond_p (tem
, selective
)))
2398 tem
= find_next_newline (tem
, 1);
2400 /* Compute the cursor position after that newline. */
2401 ep
= *compute_motion (pos
, vpos
, val
.hpos
, did_motion
, tem
,
2402 height
, - (1 << (BITS_PER_SHORT
- 1)),
2404 /* We have tab offset in VAL, use it. */
2407 /* If changes reach past the text available on the frame,
2408 just display rest of frame. */
2409 if (ep
.bufpos
> Z
- XFASTINT (w
->window_end_pos
))
2412 stop_vpos
= ep
.vpos
;
2414 /* If no newline before ep, the line ep is on includes some changes
2415 that must be displayed. Make sure we don't stop before it. */
2416 /* Also, if changes reach all the way until ep.bufpos,
2417 it is possible that something was deleted after the
2418 newline before it, so the following line must be redrawn. */
2419 if (stop_vpos
== ep
.vpos
2420 && (ep
.bufpos
== BEGV
2421 || FETCH_BYTE (ep
.bufpos
- 1) != '\n'
2422 || ep
.bufpos
== Z
- end_unchanged
))
2423 stop_vpos
= ep
.vpos
+ 1;
2426 overlay_arrow_seen
= 0;
2427 zv_strings_seen
= 0;
2429 /* If changes do not reach to bottom of window,
2430 figure out how much to scroll the rest of the window */
2431 if (stop_vpos
< height
)
2433 /* Now determine how far up or down the rest of the window has moved */
2434 xp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
2435 Z
- XFASTINT (w
->window_end_pos
),
2436 /* Don't care for VPOS... */
2437 1 << (BITS_PER_SHORT
- 1),
2439 1 << (BITS_PER_SHORT
- 1),
2440 width
, hscroll
, ep
.tab_offset
, w
);
2441 scroll_amount
= xp
.vpos
- XFASTINT (w
->window_end_vpos
);
2443 /* Is everything on frame below the changes whitespace?
2444 If so, no scrolling is really necessary. */
2445 for (i
= ep
.bufpos
; i
< xp
.bufpos
; i
++)
2447 tem
= FETCH_BYTE (i
);
2448 if (tem
!= ' ' && tem
!= '\n' && tem
!= '\t')
2454 XSETFASTINT (w
->window_end_vpos
,
2455 XFASTINT (w
->window_end_vpos
) + scroll_amount
);
2457 /* Before doing any scrolling, verify that point will be on frame. */
2458 if (PT
> ep
.bufpos
&& !(PT
<= xp
.bufpos
&& xp
.vpos
< height
))
2460 if (PT
<= xp
.bufpos
)
2462 pp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
, 1,
2463 PT
, height
, - (1 << (BITS_PER_SHORT
- 1)),
2465 /* We have tab offset in EP, use it. */
2470 pp
= *compute_motion (xp
.bufpos
, xp
.vpos
, xp
.hpos
, 1,
2471 PT
, height
, - (1 << (BITS_PER_SHORT
- 1)),
2473 /* We have tab offset in XP, use it. */
2476 if (pp
.bufpos
< PT
|| pp
.vpos
== height
)
2478 cursor_vpos
= pp
.vpos
+ top
;
2479 cursor_hpos
= WINDOW_LEFT_MARGIN (w
) + minmax (0, pp
.hpos
, width
);
2482 if (stop_vpos
- scroll_amount
>= height
2483 || ep
.bufpos
== xp
.bufpos
)
2485 if (scroll_amount
< 0)
2486 stop_vpos
-= scroll_amount
;
2488 /* In this path, we have altered window_end_vpos
2489 and not left it negative.
2490 We must make sure that, in case display is preempted
2491 before the frame changes to reflect what we do here,
2492 further updates will not come to try_window_id
2493 and assume the frame and window_end_vpos match. */
2494 blank_end_of_window
= 1;
2496 else if (!scroll_amount
)
2498 /* Even if we don't need to scroll, we must adjust the
2499 charstarts of subsequent lines (that we won't redisplay)
2500 according to the amount of text inserted or deleted. */
2501 int oldpos
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2502 int adjust
= ep
.bufpos
- oldpos
;
2503 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1, adjust
);
2505 else if (bp
.bufpos
== Z
- end_unchanged
)
2507 /* If reprinting everything is nearly as fast as scrolling,
2508 don't bother scrolling. Can happen if lines are short. */
2509 if (scroll_cost (f
, bp
.vpos
+ top
- scroll_amount
,
2510 top
+ height
- max (0, scroll_amount
),
2512 > xp
.bufpos
- bp
.bufpos
- 20)
2513 /* Return "try normal display with same window-start."
2514 Too bad we can't prevent further scroll-thinking. */
2516 /* If pure deletion, scroll up as many lines as possible.
2517 In common case of killing a line, this can save the
2518 following line from being overwritten by scrolling
2519 and therefore having to be redrawn. */
2520 tem
= scroll_frame_lines (f
, bp
.vpos
+ top
- scroll_amount
,
2521 top
+ height
- max (0, scroll_amount
),
2522 scroll_amount
, bp
.bufpos
);
2527 /* scroll_frame_lines did not properly adjust subsequent
2528 lines' charstarts in the case where the text of the
2529 screen line at bp.vpos has changed.
2530 (This can happen in a deletion that ends in mid-line.)
2531 To adjust properly, we need to make things consistent
2533 So do a second adjust to make that happen.
2534 Note that stop_vpos >= ep.vpos, so it is sufficient
2535 to update the charstarts for lines at ep.vpos and below. */
2537 = FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
2538 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1,
2539 ep
.bufpos
- oldstart
);
2542 else if (scroll_amount
)
2544 /* If reprinting everything is nearly as fast as scrolling,
2545 don't bother scrolling. Can happen if lines are short. */
2546 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2547 overestimate of cost of reprinting, since xp.bufpos
2548 would end up below the bottom of the window. */
2549 if (scroll_cost (f
, ep
.vpos
+ top
- scroll_amount
,
2550 top
+ height
- max (0, scroll_amount
),
2552 > xp
.bufpos
- ep
.bufpos
- 20)
2553 /* Return "try normal display with same window-start."
2554 Too bad we can't prevent further scroll-thinking. */
2556 tem
= scroll_frame_lines (f
, ep
.vpos
+ top
- scroll_amount
,
2557 top
+ height
- max (0, scroll_amount
),
2558 scroll_amount
, ep
.bufpos
);
2559 if (!tem
) stop_vpos
= height
;
2563 /* In any case, do not display past bottom of window */
2564 if (stop_vpos
>= height
)
2570 /* Handle case where pos is before w->start --
2571 can happen if part of line had been clipped and is not clipped now */
2572 if (vpos
== 0 && pos
< marker_position (w
->start
))
2573 Fset_marker (w
->start
, make_number (pos
), Qnil
);
2575 /* Redisplay the lines where the text was changed */
2576 last_text_vpos
= vpos
;
2577 /* The following code is omitted because we maintain tab offset in
2580 tab_offset
= pos_tab_offset (w
, pos
);
2581 /* If we are starting display in mid-character, correct tab_offset
2582 to account for passing the line that that character really starts in. */
2583 if (val
.hpos
< lmargin
)
2584 tab_offset
+= width
;
2587 while (vpos
< stop_vpos
)
2589 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, val
.tab_offset
,
2590 val
.ovstring_chars_done
);
2591 /* If display_text_line ran a hook and changed some text,
2592 redisplay all the way to bottom of buffer
2593 So that we show the changes. */
2594 if (old_tick
!= MODIFF
)
2596 /* The following code is omitted because we maintain tab offset
2597 in val.tab_offset. */
2599 tab_offset
+= width
;
2600 if (val
.vpos
) tab_offset
= 0;
2602 if (pos
!= val
.bufpos
)
2604 /* Next line, unless prev line ended in end of buffer with no cr */
2605 = vpos
- (val
.vpos
&& FETCH_BYTE (val
.bufpos
- 1) != '\n');
2609 /* There are two cases:
2610 1) we have displayed down to the bottom of the window
2611 2) we have scrolled lines below stop_vpos by scroll_amount */
2615 /* If last line is continued in middle of character,
2616 include the split character in the text considered on the frame */
2617 if (val
.hpos
< lmargin
)
2619 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
);
2620 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2623 /* If scrolling made blank lines at window bottom,
2624 redisplay to fill those lines */
2625 if (scroll_amount
< 0)
2627 /* Don't consider these lines for general-purpose scrolling.
2628 That will save time in the scrolling computation. */
2629 FRAME_SCROLL_BOTTOM_VPOS (f
) = xp
.vpos
;
2633 val
.tab_offset
= xp
.tab_offset
;
2635 { /* Display from next line */
2636 vpos
= height
+ scroll_amount
;
2640 else if (xp
.contin
&& xp
.hpos
!= lmargin
)
2642 val
.hpos
= xp
.prevhpos
- width
+ lmargin
;
2643 val
.tab_offset
= xp
.tab_offset
+ bp
.prevhpos
- width
;
2647 blank_end_of_window
= 1;
2648 /* The following code is omitted because we maintain tab offset
2649 in val.tab_offset. */
2651 tab_offset
= pos_tab_offset (w
, pos
);
2652 /* If we are starting display in mid-character, correct tab_offset
2653 to account for passing the line that that character starts in. */
2654 if (val
.hpos
< lmargin
)
2655 tab_offset
+= width
;
2657 while (vpos
< height
)
2659 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
,
2660 val
.tab_offset
, val
.ovstring_chars_done
);
2661 /* The following code is omitted because we maintain tab
2662 offset in val.tab_offset. */
2664 tab_offset
+= width
;
2665 if (val
.vpos
) tab_offset
= 0;
2670 /* Here is a case where display_text_line sets cursor_vpos wrong.
2671 Make it be fixed up, below. */
2677 /* If bottom just moved off end of frame, change mode line percentage. */
2678 if (XFASTINT (w
->window_end_pos
) == 0
2680 w
->update_mode_line
= Qt
;
2682 /* Attempt to adjust end-of-text positions to new bottom line */
2685 delta
= height
- xp
.vpos
;
2687 || (delta
> 0 && xp
.bufpos
<= ZV
)
2688 || (delta
== 0 && xp
.hpos
))
2690 val
= *vmotion (Z
- XFASTINT (w
->window_end_pos
), delta
, w
);
2691 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
2692 XSETFASTINT (w
->window_end_vpos
,
2693 XFASTINT (w
->window_end_vpos
) + val
.vpos
);
2697 w
->window_end_valid
= Qnil
;
2699 /* If point was not in a line that was displayed, find it */
2700 if (cursor_vpos
< 0)
2703 val
= *compute_motion (start
, 0, lmargin
, 0, PT
,
2704 /* Don't care for VPOS... */
2705 1 << (BITS_PER_SHORT
- 1),
2707 1 << (BITS_PER_SHORT
- 1),
2708 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2709 /* Admit failure if point is off frame now */
2710 if (val
.vpos
>= height
)
2712 for (vpos
= 0; vpos
< height
; vpos
++)
2713 cancel_line (vpos
+ top
, f
);
2716 cursor_vpos
= val
.vpos
+ top
;
2717 cursor_hpos
= WINDOW_LEFT_MARGIN (w
) + minmax (0, val
.hpos
, width
);
2720 FRAME_CURSOR_X (f
) = cursor_hpos
;
2721 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2725 val
= *compute_motion (start
, 0, lmargin
, 0, ZV
,
2726 height
, - (1 << (BITS_PER_SHORT
- 1)),
2727 width
, hscroll
, pos_tab_offset (w
, start
), w
);
2728 if (val
.vpos
!= XFASTINT (w
->window_end_vpos
))
2730 if (XFASTINT (w
->window_end_pos
)
2738 /* Copy LEN glyphs starting address FROM to the rope TO.
2739 But don't actually copy the parts that would come in before S.
2740 Value is TO, advanced past the copied data.
2741 F is the frame we are displaying in. */
2744 copy_part_of_rope (f
, to
, s
, from
, len
, face
)
2746 register GLYPH
*to
; /* Copy to here. */
2747 register GLYPH
*s
; /* Starting point. */
2748 Lisp_Object
*from
; /* Data to copy. */
2750 int face
; /* Face to apply to glyphs which don't specify one. */
2753 register Lisp_Object
*fp
= from
;
2754 /* These cache the results of the last call to compute_glyph_face. */
2756 int last_merged
= 0;
2759 if (! FRAME_TERMCAP_P (f
))
2762 GLYPH glyph
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2764 unsigned int c
= FAST_GLYPH_CHAR (glyph
);
2767 /* For an invalid character code, use space. */
2770 if (FAST_GLYPH_FACE (glyph
) == 0)
2771 /* If GLYPH has no face code, use FACE. */
2773 else if (FAST_GLYPH_FACE (glyph
) == last_code
)
2774 /* If it's same as previous glyph, use same result. */
2775 facecode
= last_merged
;
2778 /* Merge this glyph's face and remember the result. */
2779 last_code
= FAST_GLYPH_FACE (glyph
);
2780 last_merged
= facecode
= compute_glyph_face (f
, last_code
, face
);
2784 *to
= FAST_MAKE_GLYPH (c
, facecode
);
2792 if (to
>= s
) *to
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
2799 /* Correct a glyph by replacing its specified user-level face code
2800 with a displayable computed face code. */
2803 fix_glyph (f
, glyph
, cface
)
2809 if (! FRAME_TERMCAP_P (f
))
2811 if (FAST_GLYPH_FACE (glyph
) != 0)
2812 cface
= compute_glyph_face (f
, FAST_GLYPH_FACE (glyph
), cface
);
2813 glyph
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), cface
);
2819 /* Display one line of window W, starting at position START in W's buffer.
2821 Display starting at horizontal position HPOS, expressed relative to
2822 W's left edge. In situations where the text at START shouldn't
2823 start at the left margin (i.e. when the window is hscrolled, or
2824 we're continuing a line which left off in the midst of a
2825 multi-column character), HPOS should be negative; we throw away
2826 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2829 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2831 OVSTR_DONE is the number of chars of overlay before/after strings
2832 at this position which have already been processed.
2834 Display on position VPOS on the frame. It is origin 0, relative to
2835 the top of the frame, not W.
2837 Returns a STRUCT POSITION giving character to start next line with
2838 and where to display it, including a zero or negative hpos.
2839 The vpos field is not really a vpos; it is 1 unless the line is continued */
2841 struct position val_display_text_line
;
2843 static struct position
*
2844 display_text_line (w
, start
, vpos
, hpos
, taboffset
, ovstr_done
)
2852 register int pos
= start
;
2856 register unsigned char *p
;
2858 register GLYPH
*leftmargin
;
2859 register GLYPH
*p1prev
;
2860 register GLYPH
*p1start
;
2863 FRAME_PTR f
= XFRAME (w
->frame
);
2864 int tab_width
= XINT (current_buffer
->tab_width
);
2865 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
2866 int width
= window_internal_width (w
) - 1;
2867 struct position val
;
2870 int last_invis_skip
= 0;
2871 Lisp_Object last_invis_prop
;
2872 int hscroll
= XINT (w
->hscroll
);
2873 int truncate
= (hscroll
2874 || (truncate_partial_width_windows
2875 && !WINDOW_FULL_WIDTH_P (w
))
2876 || !NILP (current_buffer
->truncate_lines
));
2878 /* 1 if we should highlight the region. */
2879 int highlight_region
2880 = (!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
)
2881 && (XWINDOW (current_buffer
->last_selected_window
) == w
2882 || highlight_nonselected_windows
));
2883 int region_beg
, region_end
;
2885 int selective
= (INTEGERP (current_buffer
->selective_display
)
2886 ? XINT (current_buffer
->selective_display
)
2887 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2888 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
2889 register struct Lisp_Char_Table
*dp
= window_display_table (w
);
2891 Lisp_Object default_invis_vector
[3];
2892 /* Number of characters of ellipsis to display after an invisible line
2893 if it calls for an ellipsis.
2894 Note that this value can be nonzero regardless of whether
2895 selective display is enabled--you must check that separately. */
2897 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2898 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
2899 : !NILP (current_buffer
->selective_display_ellipses
) ? 3 : 0);
2900 /* This is the sequence of Lisp objects to display
2901 when there are invisible lines. */
2902 Lisp_Object
*invis_vector_contents
2903 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2904 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->contents
2905 : default_invis_vector
);
2907 GLYPH truncator
= (dp
== 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp
))
2908 || !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp
)))
2909 ? '$' : XINT (DISP_TRUNC_GLYPH (dp
)));
2910 GLYPH continuer
= (dp
== 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp
))
2911 || !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp
)))
2912 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp
)));
2914 /* If 1, we must handle multibyte characters. */
2915 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
2916 /* Length of multibyte form of each character. */
2918 /* Glyphs generated should be set this bit mask if text must be
2919 displayed from right to left. */
2920 GLYPH rev_dir_bit
= (NILP (current_buffer
->direction_reversed
)
2921 ? 0 : GLYPH_MASK_REV_DIR
);
2923 /* The next buffer location at which the face should change, due
2924 to overlays or text property changes. */
2925 int next_face_change
;
2927 /* The next location where the `invisible' property changes, or an
2928 overlay starts or ends. */
2931 /* The face we're currently using. */
2932 int current_face
= 0;
2935 XSETFASTINT (default_invis_vector
[2], '.');
2936 default_invis_vector
[0] = default_invis_vector
[1] = default_invis_vector
[2];
2938 get_display_line (f
, vpos
, WINDOW_LEFT_MARGIN (w
));
2939 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
2941 /* Show where to highlight the region. */
2942 if (highlight_region
&& XMARKER (current_buffer
->mark
)->buffer
!= 0
2943 /* Maybe highlight only in selected window. */
2944 && (highlight_nonselected_windows
2945 || w
== XWINDOW (selected_window
)))
2947 region_beg
= marker_position (current_buffer
->mark
);
2948 if (PT
< region_beg
)
2950 region_end
= region_beg
;
2955 w
->region_showing
= Qt
;
2959 region_beg
= region_end
= -1;
2960 w
->region_showing
= Qnil
;
2963 if (MINI_WINDOW_P (w
)
2965 && vpos
== XFASTINT (w
->top
))
2967 if (! NILP (minibuf_prompt
))
2969 int old_width
= minibuf_prompt_width
;
2971 minibuf_prompt_width
2972 = (display_string (w
, vpos
, XSTRING (minibuf_prompt
)->data
,
2973 XSTRING (minibuf_prompt
)->size
,
2974 hpos
+ WINDOW_LEFT_MARGIN (w
),
2975 /* Display a space if we truncate. */
2978 /* Truncate the prompt a little before the
2979 margin, so user input can at least start
2980 on the first line. */
2981 (XFASTINT (w
->width
) > 10
2982 ? XFASTINT (w
->width
) - 4 : -1))
2983 - hpos
- WINDOW_LEFT_MARGIN (w
));
2984 hpos
+= minibuf_prompt_width
;
2985 taboffset
-= minibuf_prompt_width
- old_width
;
2988 minibuf_prompt_width
= 0;
2991 /* If we're hscrolled at all, use compute_motion to skip over any
2992 text off the left edge of the window. compute_motion may know
2993 tricks to do this faster than we can. */
2996 struct position
*left_edge
2997 = compute_motion (pos
, vpos
, hpos
, 0,
2999 width
, hscroll
, taboffset
, w
);
3001 /* Retrieve the buffer position and column provided by
3002 compute_motion. We can't assume that the column will be
3003 zero, because you may have multi-column characters crossing
3006 compute_motion may have moved us past the screen position we
3007 requested, if we hit a multi-column character, or the end of
3008 the line. If so, back up. */
3009 if (left_edge
->vpos
> vpos
3010 || left_edge
->hpos
> 0)
3012 pos
= left_edge
->bufpos
;
3013 /* Since this should not be a valid multibyte character, we
3014 can decrease POS by 1. */
3016 hpos
= left_edge
->prevhpos
;
3020 pos
= left_edge
->bufpos
;
3021 hpos
= left_edge
->hpos
;
3025 hpos
+= WINDOW_LEFT_MARGIN (w
);
3027 desired_glyphs
->bufp
[vpos
] = start
;
3028 p1
= desired_glyphs
->glyphs
[vpos
] + hpos
;
3030 charstart
= desired_glyphs
->charstarts
[vpos
] + hpos
;
3031 /* In case we don't ever write anything into it... */
3032 desired_glyphs
->charstarts
[vpos
][WINDOW_LEFT_MARGIN (w
)] = -1;
3033 leftmargin
= desired_glyphs
->glyphs
[vpos
] + WINDOW_LEFT_MARGIN (w
);
3034 endp
= leftmargin
+ width
;
3036 /* Arrange the overlays nicely for our purposes. Usually, we call
3037 display_text_line on only one line at a time, in which case this
3038 can't really hurt too much, or we call it on lines which appear
3039 one after another in the buffer, in which case all calls to
3040 recenter_overlay_lists but the first will be pretty cheap. */
3041 recenter_overlay_lists (current_buffer
, pos
);
3043 /* Loop generating characters.
3044 Stop at end of buffer, before newline,
3045 if reach or pass continuation column,
3046 or at face change. */
3048 next_face_change
= pos
;
3049 next_boundary
= pos
;
3053 /* If the window is hscrolled and point is in the invisible part of the
3054 current line beyond the left margin we can record the cursor location
3056 if (hscroll
&& start
<= PT
&& PT
< pos
&& cursor_vpos
< 0)
3059 cursor_hpos
= p1
- leftmargin
;
3068 while (pos
== next_boundary
)
3070 Lisp_Object position
, limit
, prop
, ww
;
3072 /* Display the overlay strings here, unless we're at ZV
3073 and have already displayed the appropriate strings
3074 on an earlier line. */
3075 if (pos
< ZV
|| !zv_strings_seen
++)
3078 unsigned char *ovstr
;
3079 ovlen
= overlay_strings (pos
, w
, &ovstr
);
3083 /* Skip the ones we did in a previous line. */
3084 ovstr
+= ovstr_done
;
3085 ovlen
-= ovstr_done
;
3094 c
= STRING_CHAR_AND_LENGTH (ovstr
, ovlen
, len
);
3095 ovstr
+= len
, ovlen
-= len
, ovstr_done
+= len
;
3096 charset
= CHAR_CHARSET (c
);
3097 cols
= (charset
== CHARSET_COMPOSITION
3098 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
3099 : CHARSET_WIDTH (charset
));
3103 c
= *ovstr
++, ovlen
--, ovstr_done
++;
3106 g
= MAKE_GLYPH (f
, c
, current_face
) | rev_dir_bit
;
3109 if (p1
>= leftmargin
&& p1
< endp
)
3110 *p1
= g
, g
|= GLYPH_MASK_PADDING
;
3114 /* If we did all the overlay strings
3115 and we have room for text, clear ovstr_done
3116 just for neatness' sake. */
3117 if (ovlen
== 0 && p1
< endp
)
3122 /* Did we reach point? Record the cursor location. */
3123 if (pos
== PT
&& cursor_vpos
< 0)
3126 cursor_hpos
= p1
- leftmargin
;
3132 XSETFASTINT (position
, pos
);
3133 limit
= Fnext_overlay_change (position
);
3134 #ifdef USE_TEXT_PROPERTIES
3135 /* This is just an estimate to give reasonable
3136 performance; nothing should go wrong if it is too small. */
3137 if (XFASTINT (limit
) > pos
+ 50)
3139 int limitpos
= pos
+ 50;
3141 INC_POS (limitpos
); /* Adjust to character boundary. */
3142 XSETFASTINT (limit
, limitpos
);
3144 limit
= Fnext_single_property_change (position
, Qinvisible
,
3145 Fcurrent_buffer (), limit
);
3147 next_boundary
= XFASTINT (limit
);
3148 /* if the `invisible' property is set, we can skip to
3149 the next property change. */
3151 prop
= Fget_char_property (position
, Qinvisible
, ww
);
3152 if (TEXT_PROP_MEANS_INVISIBLE (prop
))
3154 if (pos
< PT
&& next_boundary
>= PT
)
3157 cursor_hpos
= p1
- leftmargin
;
3159 pos
= next_boundary
;
3160 last_invis_skip
= pos
;
3161 last_invis_prop
= prop
;
3165 /* Did we reach point? Record the cursor location. */
3166 if (pos
== PT
&& cursor_vpos
< 0)
3169 cursor_hpos
= p1
- leftmargin
;
3172 /* Did we hit the end of the visible region of the buffer?
3176 /* Update charstarts for the end of this line. */
3177 /* Do nothing if off the left edge or at the right edge. */
3178 if (p1
>= leftmargin
&& p1
+ 1 != endp
)
3180 int *p2x
= &charstart
[(p1
< leftmargin
3188 /* Figure out where (if at all) the
3189 redisplay_end_trigger-hook should run. */
3190 if (MARKERP (w
->redisplay_end_trigger
)
3191 && XMARKER (w
->redisplay_end_trigger
)->buffer
!= 0)
3192 e_t_h
= marker_position (w
->redisplay_end_trigger
);
3193 else if (INTEGERP (w
->redisplay_end_trigger
))
3194 e_t_h
= XINT (w
->redisplay_end_trigger
);
3198 /* If we've gone past the place to run a hook,
3200 if (pos
>= e_t_h
&& e_t_h
!= ZV
)
3202 Lisp_Object args
[3];
3204 args
[0] = Qredisplay_end_trigger_functions
;
3205 XSETWINDOW (args
[1], w
);
3206 XSETINT (args
[2], e_t_h
);
3208 /* Since we are *trying* to run these functions,
3209 don't try to run them again, even if they get an error. */
3210 w
->redisplay_end_trigger
= Qnil
;
3211 Frun_hook_with_args (3, args
);
3214 /* Notice if it changed the face of this character. */
3215 next_face_change
= pos
;
3219 /* Did we hit a face change? Figure out what face we should
3220 use now. We also hit this the first time through the
3221 loop, to see what face we should start with. */
3222 if (pos
>= next_face_change
3223 && (FRAME_WINDOW_P (f
) || FRAME_MSDOS_P (f
)))
3225 int limit
= pos
+ 50;
3227 if (limit
< Z
&& !CHAR_HEAD_P (POS_ADDR (limit
)))
3228 INC_POS (limit
); /* Adjust to character boundary. */
3229 current_face
= compute_char_face (f
, w
, pos
,
3230 region_beg
, region_end
,
3231 &next_face_change
, limit
, 0);
3235 /* Compute the next place we need to stop
3236 and do something special; set PAUSE. */
3240 if (pos
< next_boundary
&& next_boundary
< pause
)
3241 pause
= next_boundary
;
3242 if (pos
< next_face_change
&& next_face_change
< pause
)
3243 pause
= next_face_change
;
3248 /* Wouldn't you hate to read the next line to someone over
3250 if (pos
< PT
&& PT
< pause
)
3252 if (pos
< GPT
&& GPT
< pause
)
3264 /* PAUSE is surely at character boundary. */
3265 c
= STRING_CHAR_AND_LENGTH (p
, pause
- pos
, len
), p
+= len
;
3268 /* Let a display table override all standard display methods. */
3269 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
3271 p1
= copy_part_of_rope (f
, p1
, leftmargin
,
3272 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
3273 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
3274 current_face
, rev_dir_bit
);
3276 else if (c
>= 040 && c
< 0177)
3278 if (p1
>= leftmargin
)
3279 *p1
= MAKE_GLYPH (f
, c
, current_face
) | rev_dir_bit
;
3285 /* Same as p1prev, but after the invis_vector_contents text
3286 (if we have that on this line). */
3287 GLYPH
*p1prev_modified
;
3291 if (last_invis_skip
== pos
3292 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop
))
3296 && indented_beyond_p (pos
+ 1, selective
))
3299 pos
= find_next_newline (pos
+ 1, 1);
3300 if (FETCH_BYTE (pos
- 1) == '\n')
3303 if (invis
&& selective_rlen
> 0 && p1
>= leftmargin
)
3308 cs
= charstart
+ (p1
- p1start
);
3311 p1
+= selective_rlen
;
3312 if (p1
- leftmargin
> width
)
3315 #if 0 /* This needs more work; charstarts needs to record
3316 both whether a position ho;ds an ellipsis character
3317 and what buffer position it corresponds to. */
3318 csend
= charstart
+ (p1
- p1start
);
3321 /* The idea is to use p1prev_modified instead of p1prev
3322 in the loop below over p2x. */
3323 p1prev_modified
= p1
;
3326 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
3327 (p1
- p1prev
), current_face
, rev_dir_bit
);
3330 /* Update charstarts for the newline that ended this line. */
3331 /* Do nothing here for a char that's entirely off the left edge
3332 or if it starts at the right edge. */
3333 if (p1
>= leftmargin
&& p1prev
!= endp
)
3335 /* Store the newline's position into charstarts
3336 for the column where the newline starts.
3337 Store -1 for the rest of the glyphs it occupies. */
3338 int *p2x
= &charstart
[(p1prev
< leftmargin
3339 ? leftmargin
: p1prev
)
3341 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
3348 /* Draw the face of the newline character as extending all the
3349 way to the end of the frame line. */
3352 if (p1
< leftmargin
)
3355 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
) | rev_dir_bit
;
3365 if (p1
>= leftmargin
&& p1
< endp
)
3366 *p1
= MAKE_GLYPH (f
, ' ', current_face
) | rev_dir_bit
;
3369 while ((p1
- leftmargin
+ taboffset
+ hscroll
- (hscroll
> 0))
3372 else if (c
== Ctl ('M') && selective
== -1)
3374 pos
= find_next_newline (pos
, 1);
3375 if (FETCH_BYTE (pos
- 1) == '\n')
3377 if (selective_rlen
> 0)
3379 p1
+= selective_rlen
;
3380 if (p1
- leftmargin
> width
)
3382 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
3383 (p1
- p1prev
), current_face
, rev_dir_bit
);
3386 /* Draw the face of the newline character as extending all the
3387 way to the end of the frame line. */
3390 if (p1
< leftmargin
)
3393 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
) | rev_dir_bit
;
3397 /* Update charstarts for the ^M that ended this line. */
3398 /* Do nothing here for a char that's entirely off the left edge
3399 or if it starts at the right edge. */
3400 if (p1
>= leftmargin
&& p1prev
!= endp
)
3402 /* Store the newline's position into charstarts
3403 for the column where the newline starts.
3404 Store -1 for the rest of the glyphs it occupies. */
3405 int *p2x
= &charstart
[(p1prev
< leftmargin
3406 ? leftmargin
: p1prev
)
3408 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
3416 else if (c
< 0200 && ctl_arrow
)
3418 if (p1
>= leftmargin
)
3420 (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
3421 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp
)))
3422 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
3426 if (p1
>= leftmargin
&& p1
< endp
)
3427 *p1
= MAKE_GLYPH (f
, c
^ 0100, current_face
) | rev_dir_bit
;
3432 /* C is not a multibyte character. */
3433 if (p1
>= leftmargin
)
3435 (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
3436 && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp
)))
3437 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
3441 if (p1
>= leftmargin
&& p1
< endp
)
3442 *p1
= MAKE_GLYPH (f
, (c
>> 6) + '0', current_face
) | rev_dir_bit
;
3444 if (p1
>= leftmargin
&& p1
< endp
)
3445 *p1
= (MAKE_GLYPH (f
, (7 & (c
>> 3)) + '0', current_face
)
3448 if (p1
>= leftmargin
&& p1
< endp
)
3449 *p1
= MAKE_GLYPH (f
, (7 & c
) + '0', current_face
) | rev_dir_bit
;
3454 /* C is a multibyte character. */
3455 int charset
= CHAR_CHARSET (c
);
3456 int columns
= (charset
== CHARSET_COMPOSITION
3457 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
3458 : CHARSET_WIDTH (charset
));
3459 GLYPH g
= MAKE_GLYPH (f
, c
, current_face
) | rev_dir_bit
;
3463 if (p1
>= leftmargin
&& p1
< endp
)
3464 *p1
= g
, g
|= GLYPH_MASK_PADDING
;
3472 /* Update charstarts for the character just output. */
3474 /* Do nothing here for a char that's entirely off the left edge. */
3475 if (p1
>= leftmargin
)
3477 /* Store the char's position into charstarts
3478 for the first glyph occupied by this char.
3479 Store -1 for the rest of the glyphs it occupies. */
3482 int *p2x
= &charstart
[(p1prev
< leftmargin
3483 ? leftmargin
: p1prev
)
3485 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
3495 val
.hpos
= - XINT (w
->hscroll
);
3503 /* Store 0 in this charstart line for the positions where
3504 there is no character. But do leave what was recorded
3505 for the character that ended the line. */
3506 /* Add 1 in the endtest to compensate for the fact that ENDP was
3507 made from WIDTH, which is 1 less than the window's actual
3509 i
= p1
- p1start
+ 1;
3510 if (p1
< leftmargin
)
3511 i
+= leftmargin
- p1
;
3512 for (; i
< endp
- p1start
+ 1; i
++)
3515 /* Handle continuation in middle of a character */
3516 /* by backing up over it */
3519 /* Don't back up if we never actually displayed any text.
3520 This occurs when the minibuffer prompt takes up the whole line. */
3523 /* Start the next line with that same character whose
3524 character code is C and the length of multi-byte form is
3529 /* C is not a multi-byte character. We can break it and
3530 start from the middle column in the next line. So,
3531 adjust VAL.HPOS to skip the columns output on this
3533 val
.hpos
+= p1prev
- endp
;
3536 /* C is a multibyte character. Since we can't broke it
3537 in the middle, the whole character should be driven
3538 into the next line. */
3539 /* As the result, the actual columns occupied by the
3540 text on this line is less than WIDTH. VAL.TAB_OFFSET
3541 must be adjusted. */
3542 taboffset
= taboffset
+ (p1prev
- endp
);
3543 /* Let's fill unused columns with TRUNCATOR or CONTINUER. */
3545 GLYPH g
= fix_glyph (f
, truncate
? truncator
: continuer
, 0);
3546 while (p1prev
< endp
)
3549 /* If POINT is at POS, cursor should not on this line. */
3556 /* Keep in this line everything up to the continuation column. */
3560 /* Finish deciding which character to start the next line on,
3561 and what hpos to start it at.
3562 Also set `lastpos' to the last position which counts as "on this line"
3563 for cursor-positioning. */
3567 if (FETCH_BYTE (pos
) == '\n')
3569 /* If stopped due to a newline, start next line after it */
3572 /* Check again for hidden lines, in case the newline occurred exactly
3573 at the right margin. */
3574 while (pos
< ZV
&& selective
> 0
3575 && indented_beyond_p (pos
, selective
))
3576 pos
= find_next_newline (pos
, 1);
3579 /* Stopped due to right margin of window */
3583 *p1
++ = fix_glyph (f
, truncator
, 0);
3584 /* Truncating => start next line after next newline,
3585 and point is on this line if it is before the newline,
3586 and skip none of first char of next line */
3588 pos
= find_next_newline (pos
, 1);
3589 while (pos
< ZV
&& selective
> 0
3590 && indented_beyond_p (pos
, selective
));
3591 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
3593 lastpos
= pos
- (FETCH_BYTE (pos
- 1) == '\n');
3598 *p1
++ = fix_glyph (f
, continuer
, 0);
3601 val
.tab_offset
= taboffset
+ width
;
3608 /* If point is at eol or in invisible text at eol,
3609 record its frame location now. */
3611 if (start
<= PT
&& PT
<= lastpos
&& cursor_vpos
< 0)
3614 cursor_hpos
= p1
- leftmargin
;
3617 if (cursor_vpos
== vpos
)
3619 if (cursor_hpos
< 0) cursor_hpos
= 0;
3620 if (cursor_hpos
> width
) cursor_hpos
= width
;
3621 cursor_hpos
+= WINDOW_LEFT_MARGIN (w
);
3622 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
3624 if (!(cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f
)
3625 && EQ (FRAME_MINIBUF_WINDOW (f
), minibuf_window
)))
3627 FRAME_CURSOR_Y (f
) = cursor_vpos
;
3628 FRAME_CURSOR_X (f
) = cursor_hpos
;
3631 if (w
== XWINDOW (selected_window
))
3633 /* Line is not continued and did not start
3634 in middle of character */
3635 if ((hpos
- WINDOW_LEFT_MARGIN (w
)
3636 == (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
3639 this_line_bufpos
= start
;
3640 this_line_buffer
= current_buffer
;
3641 this_line_vpos
= cursor_vpos
;
3642 this_line_start_hpos
= hpos
- WINDOW_LEFT_MARGIN (w
);
3643 this_line_endpos
= Z
- lastpos
;
3646 this_line_bufpos
= 0;
3651 /* If hscroll and line not empty, insert truncation-at-left marker */
3652 if (hscroll
&& lastpos
!= start
)
3654 GLYPH g
= fix_glyph (f
, truncator
, 0);
3656 if (p1
<= leftmargin
)
3657 p1
= leftmargin
+ 1;
3658 else /* MULE: it may be a wide-column character */
3660 p1prev
= leftmargin
+ 1;
3661 while (p1prev
< p1
&& *p1prev
& GLYPH_MASK_PADDING
)
3666 if (!WINDOW_RIGHTMOST_P (w
))
3669 if (p1
< leftmargin
) p1
= leftmargin
;
3670 while (p1
< endp
) *p1
++ = SPACEGLYPH
;
3672 /* Don't draw vertical bars if we're using scroll bars. They're
3673 covered up by the scroll bars, and it's distracting to see
3674 them when the scroll bar windows are flickering around to be
3676 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
3679 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
3682 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3683 *p1
++ = (dp
&& INTEGERP (DISP_BORDER_GLYPH (dp
))
3684 ? XINT (DISP_BORDER_GLYPH (dp
))
3687 desired_glyphs
->used
[vpos
] = max (desired_glyphs
->used
[vpos
],
3688 p1
- desired_glyphs
->glyphs
[vpos
]);
3689 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
3691 /* If the start of this line is the overlay arrow-position,
3692 then put the arrow string into the display-line. */
3694 if (MARKERP (Voverlay_arrow_position
)
3695 && current_buffer
== XMARKER (Voverlay_arrow_position
)->buffer
3696 && start
== marker_position (Voverlay_arrow_position
)
3697 && STRINGP (Voverlay_arrow_string
)
3698 && ! overlay_arrow_seen
)
3700 unsigned char *p
= XSTRING (Voverlay_arrow_string
)->data
;
3702 int len
= XSTRING (Voverlay_arrow_string
)->size
;
3708 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string
)->intervals
))
3710 /* If the arrow string has text props, obey them when displaying. */
3711 for (i
= 0; i
< len
; i
++)
3714 Lisp_Object face
, ilisp
;
3717 XSETFASTINT (ilisp
, i
);
3718 face
= Fget_text_property (ilisp
, Qface
, Voverlay_arrow_string
);
3719 newface
= compute_glyph_face_1 (f
, face
, 0);
3720 leftmargin
[i
] = FAST_MAKE_GLYPH (c
, newface
);
3724 #endif /* HAVE_FACES */
3726 for (i
= 0; i
< len
; i
++)
3727 leftmargin
[i
] = p
[i
];
3730 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
3731 arrow_end
= (leftmargin
- desired_glyphs
->glyphs
[vpos
]) + len
;
3732 if (desired_glyphs
->used
[vpos
] < arrow_end
)
3733 desired_glyphs
->used
[vpos
] = arrow_end
;
3735 overlay_arrow_seen
= 1;
3739 val
.ovstring_chars_done
= ovstr_done
;
3740 val_display_text_line
= val
;
3741 return &val_display_text_line
;
3744 /* Redisplay the menu bar in the frame for window W. */
3747 display_menu_bar (w
)
3750 Lisp_Object items
, tail
;
3751 register int vpos
= 0;
3752 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3753 int maxendcol
= FRAME_WIDTH (f
);
3758 if (!NILP (Vwindow_system
))
3762 #ifdef USE_X_TOOLKIT
3765 #endif /* USE_X_TOOLKIT */
3767 get_display_line (f
, vpos
, 0);
3769 items
= FRAME_MENU_BAR_ITEMS (f
);
3770 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
3772 Lisp_Object pos
, string
;
3773 string
= XVECTOR (items
)->contents
[i
+ 1];
3777 XSETFASTINT (XVECTOR (items
)->contents
[i
+ 3], hpos
);
3779 if (hpos
< maxendcol
)
3780 hpos
= display_string (w
, vpos
,
3781 XSTRING (string
)->data
,
3782 XSTRING (string
)->size
,
3783 hpos
, 0, 0, hpos
, maxendcol
);
3784 /* Put a space between items. */
3785 if (hpos
< maxendcol
)
3787 int hpos1
= hpos
+ 1;
3788 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0,
3789 min (hpos1
, maxendcol
), maxendcol
);
3793 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3794 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3796 /* Fill out the line with spaces. */
3797 if (maxendcol
> hpos
)
3798 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0, maxendcol
, maxendcol
);
3800 /* Clear the rest of the lines allocated to the menu bar. */
3802 while (vpos
< FRAME_MENU_BAR_LINES (f
))
3803 get_display_line (f
, vpos
++, 0);
3806 /* Display the mode line for window w */
3809 display_mode_line (w
)
3812 register int vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
3813 register int left
= WINDOW_LEFT_MARGIN (w
);
3814 register int right
= WINDOW_RIGHT_MARGIN (w
);
3815 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3817 line_number_displayed
= 0;
3818 w
->column_number_displayed
= Qnil
;
3820 get_display_line (f
, vpos
, left
);
3822 /* Temporarily make frame F's kboard the current kboard
3823 so that kboard-local variables in the mode_line_format
3824 will get the right values. */
3825 push_frame_kboard (f
);
3827 display_mode_element (w
, vpos
, left
, 0, right
, right
,
3828 current_buffer
->mode_line_format
);
3830 pop_frame_kboard ();
3832 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
3834 /* Put the mode line in inverse video.
3835 Use faces if possible, since that lets us handle
3836 partial-width windows and avoid inverting the scroll bar columns. */
3838 if (! FRAME_TERMCAP_P (f
) && mode_line_inverse_video
)
3840 /* For a partial width window, explicitly set face of each glyph. */
3842 unsigned int padding
;
3843 GLYPH
*ptr
= FRAME_DESIRED_GLYPHS (f
)->glyphs
[vpos
];
3844 for (i
= left
; i
< right
; ++i
)
3846 padding
= ptr
[i
] & GLYPH_MASK_PADDING
;
3847 ptr
[i
] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr
[i
]), 1) | padding
;
3853 /* Make the mode line inverse video if the entire line
3854 is made of mode lines.
3855 I.e. if this window is full width,
3856 or if it is the child of a full width window
3857 (which implies that that window is split side-by-side
3858 and the rest of this line is mode lines of the sibling windows). */
3859 if (WINDOW_FULL_WIDTH_P (w
)
3860 || WINDOW_FULL_WIDTH_P (XWINDOW (w
->parent
)))
3861 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
3864 /* Contribute ELT to the mode line for window W.
3865 How it translates into text depends on its data type.
3867 VPOS is the position of the mode line being displayed.
3869 HPOS is the position (absolute on frame) where this element's text
3870 should start. The output is truncated automatically at the right
3873 DEPTH is the depth in recursion. It is used to prevent
3874 infinite recursion here.
3876 MINENDCOL is the hpos before which the element may not end.
3877 The element is padded at the right with spaces if nec
3878 to reach this column.
3880 MAXENDCOL is the hpos past which this element may not extend.
3881 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
3882 (This is necessary to make nested padding and truncation work.)
3884 Returns the hpos of the end of the text generated by ELT.
3885 The next element will receive that value as its HPOS arg,
3886 so as to concatenate the elements. */
3889 display_mode_element (w
, vpos
, hpos
, depth
, minendcol
, maxendcol
, elt
)
3891 register int vpos
, hpos
;
3894 register int maxendcol
;
3895 register Lisp_Object elt
;
3903 switch (SWITCH_ENUM_CAST (XTYPE (elt
)))
3907 /* A string: output it and check for %-constructs within it. */
3908 register unsigned char c
;
3909 register unsigned char *this = XSTRING (elt
)->data
;
3911 while (hpos
< maxendcol
&& *this)
3913 unsigned char *last
= this;
3914 while ((c
= *this++) != '\0' && c
!= '%')
3916 if (this - 1 != last
)
3918 register int lim
= --this - last
+ hpos
;
3919 if (frame_title_ptr
)
3920 hpos
= store_frame_title (last
, hpos
, min (lim
, maxendcol
));
3922 hpos
= display_string (w
, vpos
, last
, -1, hpos
, 0, 1,
3923 hpos
, min (lim
, maxendcol
));
3927 register int minendcol
;
3928 register int spec_width
= 0;
3930 /* We can't allow -ve args due to the "%-" construct */
3931 /* Argument specifies minwidth but not maxwidth
3932 (maxwidth can be specified by
3933 (<negative-number> . <stuff>) mode-line elements) */
3935 while ((c
= *this++) >= '0' && c
<= '9')
3937 spec_width
= spec_width
* 10 + (c
- '0');
3940 minendcol
= hpos
+ spec_width
;
3941 if (minendcol
> maxendcol
)
3943 spec_width
= maxendcol
- hpos
;
3944 minendcol
= maxendcol
;
3948 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
3949 spec_width
, maxendcol
,
3950 Vglobal_mode_string
);
3953 char *spec
= decode_mode_spec (w
, c
, spec_width
,
3955 if (frame_title_ptr
)
3956 hpos
= store_frame_title (spec
, minendcol
, maxendcol
);
3958 hpos
= display_string (w
, vpos
, spec
, -1,
3960 minendcol
, maxendcol
);
3968 /* A symbol: process the value of the symbol recursively
3969 as if it appeared here directly. Avoid error if symbol void.
3970 Special case: if value of symbol is a string, output the string
3973 register Lisp_Object tem
;
3974 tem
= Fboundp (elt
);
3977 tem
= Fsymbol_value (elt
);
3978 /* If value is a string, output that string literally:
3979 don't check for % within it. */
3982 if (frame_title_ptr
)
3983 hpos
= store_frame_title (XSTRING (tem
)->data
,
3984 minendcol
, maxendcol
);
3986 hpos
= display_string (w
, vpos
, XSTRING (tem
)->data
,
3987 XSTRING (tem
)->size
,
3988 hpos
, 0, 1, minendcol
, maxendcol
);
3990 /* Give up right away for nil or t. */
3991 else if (!EQ (tem
, elt
))
3992 { elt
= tem
; goto tail_recurse
; }
3999 register Lisp_Object car
, tem
;
4001 /* A cons cell: three distinct cases.
4002 If first element is a string or a cons, process all the elements
4003 and effectively concatenate them.
4004 If first element is a negative number, truncate displaying cdr to
4005 at most that many characters. If positive, pad (with spaces)
4006 to at least that many characters.
4007 If first element is a symbol, process the cadr or caddr recursively
4008 according to whether the symbol's value is non-nil or nil. */
4009 car
= XCONS (elt
)->car
;
4012 tem
= Fboundp (car
);
4013 elt
= XCONS (elt
)->cdr
;
4016 /* elt is now the cdr, and we know it is a cons cell.
4017 Use its car if CAR has a non-nil value. */
4020 tem
= Fsymbol_value (car
);
4022 { elt
= XCONS (elt
)->car
; goto tail_recurse
; }
4024 /* Symbol's value is nil (or symbol is unbound)
4025 Get the cddr of the original list
4026 and if possible find the caddr and use that. */
4027 elt
= XCONS (elt
)->cdr
;
4030 else if (!CONSP (elt
))
4032 elt
= XCONS (elt
)->car
;
4035 else if (INTEGERP (car
))
4037 register int lim
= XINT (car
);
4038 elt
= XCONS (elt
)->cdr
;
4040 /* Negative int means reduce maximum width.
4041 DO NOT change MINENDCOL here!
4042 (20 -10 . foo) should truncate foo to 10 col
4043 and then pad to 20. */
4044 maxendcol
= min (maxendcol
, hpos
- lim
);
4047 /* Padding specified. Don't let it be more than
4050 if (lim
> maxendcol
)
4052 /* If that's more padding than already wanted, queue it.
4053 But don't reduce padding already specified even if
4054 that is beyond the current truncation point. */
4055 if (lim
> minendcol
)
4060 else if (STRINGP (car
) || CONSP (car
))
4062 register int limit
= 50;
4063 /* LIMIT is to protect against circular lists. */
4064 while (CONSP (elt
) && --limit
> 0
4065 && hpos
< maxendcol
)
4067 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
4070 elt
= XCONS (elt
)->cdr
;
4078 if (frame_title_ptr
)
4079 hpos
= store_frame_title ("*invalid*", minendcol
, maxendcol
);
4081 hpos
= display_string (w
, vpos
, "*invalid*", -1, hpos
, 0, 1,
4082 minendcol
, maxendcol
);
4086 if (minendcol
> hpos
)
4087 if (frame_title_ptr
)
4088 hpos
= store_frame_title ("", minendcol
, maxendcol
);
4090 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 1, minendcol
, maxendcol
);
4094 /* Write a null-terminated, right justified decimal representation of
4095 the positive integer D to BUF using a minimal field width WIDTH. */
4098 pint2str (buf
, width
, d
)
4103 register char *p
= buf
;
4110 *p
++ = d
% 10 + '0';
4113 for (width
-= (int) (p
- buf
); width
> 0; --width
) *p
++ = ' ';
4123 /* Set a mnemonic character for CODING_SYSTEM (Lisp symbol) in BUF.
4124 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
4125 type of CODING_SYSTEM. Return updated pointer into BUF. */
4128 decode_mode_spec_coding (coding_system
, buf
, eol_flag
)
4129 Lisp_Object coding_system
;
4134 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
4136 val
= coding_system
;
4138 if (NILP (val
)) /* Not yet decided. */
4143 *buf
++ = eol_mnemonic_undecided
;
4144 /* Don't mention EOL conversion if it isn't decided. */
4148 Lisp_Object eolvalue
;
4150 eolvalue
= Fget (coding_system
, Qeol_type
);
4152 while (!NILP (val
) && SYMBOLP (val
))
4154 val
= Fget (val
, Qcoding_system
);
4155 if (NILP (eolvalue
))
4156 eolvalue
= Fget (val
, Qeol_type
);
4160 *buf
++ = XFASTINT (XVECTOR (val
)->contents
[1]);
4164 /* The EOL conversion we are using. */
4166 /* The EOL conversion that is normal on this system. */
4168 if (NILP (eolvalue
)) /* Not yet decided. */
4169 eoltype
= eol_mnemonic_undecided
;
4170 else if (VECTORP (eolvalue
)) /* Not yet decided. */
4171 eoltype
= eol_mnemonic_undecided
;
4172 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
4173 eoltype
= (XFASTINT (eolvalue
) == 0
4175 : (XFASTINT (eolvalue
) == 1
4176 ? eol_mnemonic_dos
: eol_mnemonic_mac
));
4178 /* Mention the EOL conversion if it is not the usual one. */
4185 /* Return a string for the output of a mode line %-spec for window W,
4186 generated by character C. SPEC_WIDTH is the field width when
4187 padding to the left (%c, %l). The value returned from this
4188 function will later be truncated to width MAXWIDTH. */
4190 static char lots_of_dashes
[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
4193 decode_mode_spec (w
, c
, spec_width
, maxwidth
)
4196 register int spec_width
;
4197 register int maxwidth
;
4200 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
4201 char *decode_mode_spec_buf
= (char *) FRAME_TEMP_GLYPHS (f
)->total_contents
;
4202 struct buffer
*b
= XBUFFER (w
->buffer
);
4205 if (maxwidth
> FRAME_WIDTH (f
))
4206 maxwidth
= FRAME_WIDTH (f
);
4211 if (!NILP (b
->read_only
))
4213 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
4218 /* This differs from %* only for a modified read-only buffer. */
4219 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
4221 if (!NILP (b
->read_only
))
4226 /* This differs from %* in ignoring read-only-ness. */
4227 if (BUF_MODIFF (b
) > BUF_SAVE_MODIFF (b
))
4239 if (command_loop_level
> 5)
4241 p
= decode_mode_spec_buf
;
4242 for (i
= 0; i
< command_loop_level
; i
++)
4245 return decode_mode_spec_buf
;
4253 if (command_loop_level
> 5)
4255 p
= decode_mode_spec_buf
;
4256 for (i
= 0; i
< command_loop_level
; i
++)
4259 return decode_mode_spec_buf
;
4267 if (maxwidth
< sizeof (lots_of_dashes
))
4268 return lots_of_dashes
;
4271 for (p
= decode_mode_spec_buf
, i
= maxwidth
; i
> 0; i
--)
4275 return decode_mode_spec_buf
;
4281 if (maxwidth
>= 3 && XSTRING (obj
)->size
> maxwidth
)
4283 bcopy (XSTRING (obj
)->data
, decode_mode_spec_buf
, maxwidth
- 1);
4284 decode_mode_spec_buf
[maxwidth
- 1] = '\\';
4285 decode_mode_spec_buf
[maxwidth
] = '\0';
4286 return decode_mode_spec_buf
;
4293 int col
= current_column ();
4294 XSETFASTINT (w
->column_number_displayed
, col
);
4295 pint2str (decode_mode_spec_buf
, spec_width
, col
);
4296 return decode_mode_spec_buf
;
4300 /* %F displays the frame name. */
4301 if (!NILP (f
->title
))
4302 return (char *) XSTRING (f
->title
)->data
;
4303 if (f
->explicit_name
|| ! FRAME_WINDOW_P (f
))
4304 return (char *) XSTRING (f
->name
)->data
;
4312 else if (STRINGP (obj
) && XSTRING (obj
)->size
> maxwidth
)
4314 bcopy ("...", decode_mode_spec_buf
, 3);
4315 bcopy (XSTRING (obj
)->data
+ XSTRING (obj
)->size
- maxwidth
+ 3,
4316 decode_mode_spec_buf
+ 3, maxwidth
- 3);
4317 return decode_mode_spec_buf
;
4324 int startpos
= marker_position (w
->start
);
4325 int line
, linepos
, topline
;
4328 int height
= XFASTINT (w
->height
);
4330 /* If we decided that this buffer isn't suitable for line numbers,
4331 don't forget that too fast. */
4332 if (EQ (w
->base_line_pos
, w
->buffer
))
4334 /* But do forget it, if the window shows a different buffer now. */
4335 else if (BUFFERP (w
->base_line_pos
))
4336 w
->base_line_pos
= Qnil
;
4338 /* If the buffer is very big, don't waste time. */
4339 if (BUF_ZV (b
) - BUF_BEGV (b
) > line_number_display_limit
)
4341 w
->base_line_pos
= Qnil
;
4342 w
->base_line_number
= Qnil
;
4346 if (!NILP (w
->base_line_number
)
4347 && !NILP (w
->base_line_pos
)
4348 && XFASTINT (w
->base_line_pos
) <= marker_position (w
->start
))
4350 line
= XFASTINT (w
->base_line_number
);
4351 linepos
= XFASTINT (w
->base_line_pos
);
4356 linepos
= BUF_BEGV (b
);
4359 /* Count lines from base line to window start position. */
4360 nlines
= display_count_lines (linepos
, startpos
, startpos
, &junk
);
4362 topline
= nlines
+ line
;
4364 /* Determine a new base line, if the old one is too close
4365 or too far away, or if we did not have one.
4366 "Too close" means it's plausible a scroll-down would
4368 if (startpos
== BUF_BEGV (b
))
4370 XSETFASTINT (w
->base_line_number
, topline
);
4371 XSETFASTINT (w
->base_line_pos
, BUF_BEGV (b
));
4373 else if (nlines
< height
+ 25 || nlines
> height
* 3 + 50
4374 || linepos
== BUF_BEGV (b
))
4376 int limit
= BUF_BEGV (b
);
4378 int distance
= (height
* 2 + 30) * 200;
4380 if (startpos
- distance
> limit
)
4381 limit
= startpos
- distance
;
4383 nlines
= display_count_lines (startpos
, limit
,
4386 /* If we couldn't find the lines we wanted within
4388 give up on line numbers for this window. */
4389 if (position
== startpos
- distance
)
4391 w
->base_line_pos
= w
->buffer
;
4392 w
->base_line_number
= Qnil
;
4396 XSETFASTINT (w
->base_line_number
, topline
- nlines
);
4397 XSETFASTINT (w
->base_line_pos
, position
);
4400 /* Now count lines from the start pos to point. */
4401 nlines
= display_count_lines (startpos
, PT
, PT
, &junk
);
4403 /* Record that we did display the line number. */
4404 line_number_displayed
= 1;
4406 /* Make the string to show. */
4407 pint2str (decode_mode_spec_buf
, spec_width
, topline
+ nlines
);
4408 return decode_mode_spec_buf
;
4411 char* p
= decode_mode_spec_buf
;
4412 for (spec_width
-= 2; spec_width
> 0; --spec_width
) *p
++ = ' ';
4414 return decode_mode_spec_buf
;
4424 if (BUF_BEGV (b
) > BUF_BEG (b
) || BUF_ZV (b
) < BUF_Z (b
))
4430 int pos
= marker_position (w
->start
);
4431 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
4433 if (XFASTINT (w
->window_end_pos
) <= BUF_Z (b
) - BUF_ZV (b
))
4435 if (pos
<= BUF_BEGV (b
))
4440 else if (pos
<= BUF_BEGV (b
))
4444 if (total
> 1000000)
4445 /* Do it differently for a large value, to avoid overflow. */
4446 total
= ((pos
- BUF_BEGV (b
)) + (total
/ 100) - 1) / (total
/ 100);
4448 total
= ((pos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
4449 /* We can't normally display a 3-digit number,
4450 so get us a 2-digit number that is close. */
4453 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
4454 return decode_mode_spec_buf
;
4458 /* Display percentage of size above the bottom of the screen. */
4461 int toppos
= marker_position (w
->start
);
4462 int botpos
= BUF_Z (b
) - XFASTINT (w
->window_end_pos
);
4463 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
4465 if (botpos
>= BUF_ZV (b
))
4467 if (toppos
<= BUF_BEGV (b
))
4474 if (total
> 1000000)
4475 /* Do it differently for a large value, to avoid overflow. */
4476 total
= ((botpos
- BUF_BEGV (b
)) + (total
/ 100) - 1) / (total
/ 100);
4478 total
= ((botpos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
4479 /* We can't normally display a 3-digit number,
4480 so get us a 2-digit number that is close. */
4483 if (toppos
<= BUF_BEGV (b
))
4484 sprintf (decode_mode_spec_buf
, "Top%2d%%", total
);
4486 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
4487 return decode_mode_spec_buf
;
4492 /* status of process */
4493 obj
= Fget_buffer_process (w
->buffer
);
4495 return "no process";
4497 obj
= Fsymbol_name (Fprocess_status (obj
));
4501 case 't': /* indicate TEXT or BINARY */
4502 #ifdef MODE_LINE_BINARY_TEXT
4503 return MODE_LINE_BINARY_TEXT (b
);
4509 /* coding-system (not including end-of-line format) */
4511 /* coding-system (including end-of-line type) */
4513 int eol_flag
= (c
== 'Z');
4514 char *p
= decode_mode_spec_buf
;
4516 if (! FRAME_WINDOW_P (f
))
4518 /* No need to mention EOL here--the terminal never needs
4519 to do EOL conversion. */
4520 p
= decode_mode_spec_coding (keyboard_coding
.symbol
, p
, 0);
4521 p
= decode_mode_spec_coding (terminal_coding
.symbol
, p
, 0);
4523 p
= decode_mode_spec_coding (b
->buffer_file_coding_system
,
4526 #if 0 /* This proves to be annoying; I think we can do without. -- rms. */
4528 obj
= Fget_buffer_process (Fcurrent_buffer ());
4531 p
= decode_mode_spec_coding (XPROCESS (obj
)->decode_coding_system
,
4533 p
= decode_mode_spec_coding (XPROCESS (obj
)->encode_coding_system
,
4536 #endif /* subprocesses */
4539 return decode_mode_spec_buf
;
4544 return (char *) XSTRING (obj
)->data
;
4549 /* Search for COUNT instances of a line boundary, which means either a
4550 newline or (if selective display enabled) a carriage return.
4551 Start at START. If COUNT is negative, search backwards.
4553 If we find COUNT instances, set *SHORTAGE to zero, and return the
4554 position after the COUNTth match. Note that for reverse motion
4555 this is not the same as the usual convention for Emacs motion commands.
4557 If we don't find COUNT instances before reaching the end of the
4558 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
4559 the number of line boundaries left unfound, and return the end of the
4560 buffer we bumped up against. */
4563 display_scan_buffer (start
, count
, shortage
)
4564 int *shortage
, start
;
4567 int limit
= ((count
> 0) ? ZV
- 1 : BEGV
);
4568 int direction
= ((count
> 0) ? 1 : -1);
4570 register unsigned char *cursor
;
4571 unsigned char *base
;
4573 register int ceiling
;
4574 register unsigned char *ceiling_addr
;
4576 /* If we are not in selective display mode,
4577 check only for newlines. */
4578 if (! (!NILP (current_buffer
->selective_display
)
4579 && !INTEGERP (current_buffer
->selective_display
)))
4580 return scan_buffer ('\n', start
, 0, count
, shortage
, 0);
4582 /* The code that follows is like scan_buffer
4583 but checks for either newline or carriage return. */
4589 while (start
!= limit
+ 1)
4591 ceiling
= BUFFER_CEILING_OF (start
);
4592 ceiling
= min (limit
, ceiling
);
4593 ceiling_addr
= POS_ADDR (ceiling
) + 1;
4594 base
= (cursor
= POS_ADDR (start
));
4597 while (*cursor
!= '\n' && *cursor
!= 015 && ++cursor
!= ceiling_addr
)
4599 if (cursor
!= ceiling_addr
)
4604 return (start
+ cursor
- base
+ 1);
4607 if (++cursor
== ceiling_addr
)
4613 start
+= cursor
- base
;
4617 start
--; /* first character we scan */
4618 while (start
> limit
- 1)
4619 { /* we WILL scan under start */
4620 ceiling
= BUFFER_FLOOR_OF (start
);
4621 ceiling
= max (limit
, ceiling
);
4622 ceiling_addr
= POS_ADDR (ceiling
) - 1;
4623 base
= (cursor
= POS_ADDR (start
));
4627 while (--cursor
!= ceiling_addr
4628 && *cursor
!= '\n' && *cursor
!= 015)
4630 if (cursor
!= ceiling_addr
)
4635 return (start
+ cursor
- base
+ 1);
4641 start
+= cursor
- base
;
4646 *shortage
= count
* direction
;
4647 return (start
+ ((direction
== 1 ? 0 : 1)));
4650 /* Count up to N lines starting from FROM.
4651 But don't go beyond LIMIT.
4652 Return the number of lines thus found (always positive).
4653 Store the position after what was found into *POS_PTR. */
4656 display_count_lines (from
, limit
, n
, pos_ptr
)
4669 *pos_ptr
= display_scan_buffer (from
, n
, &shortage
);
4675 /* When scanning backwards, scan_buffer stops *after* the last newline
4676 it finds, but does count it. Compensate for that. */
4677 return - n
- shortage
- (*pos_ptr
!= limit
);
4678 return n
- shortage
;
4681 /* Display STRING on one line of window W, starting at HPOS.
4682 Display at position VPOS. Caller should have done get_display_line.
4683 If VPOS == -1, display it as the current frame's title.
4684 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
4686 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
4688 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
4689 MAXCOL is the last column ok to end at. Truncate here.
4690 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
4691 Both count from the left edge of the frame, as does HPOS.
4692 The right edge of W is an implicit maximum.
4693 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
4695 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
4696 at the place where the current window ends in this line
4697 and not display anything beyond there. Otherwise, only MAXCOL
4698 controls where to stop output.
4700 Returns ending hpos. */
4703 display_string (w
, vpos
, string
, length
, hpos
, truncate
,
4704 obey_window_width
, mincol
, maxcol
)
4706 unsigned char *string
;
4710 int obey_window_width
;
4716 int hscroll
= XINT (w
->hscroll
);
4717 int tab_width
= XINT (XBUFFER (w
->buffer
)->tab_width
);
4718 register GLYPH
*start
;
4719 register GLYPH
*end
;
4720 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
4721 struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
4722 GLYPH
*p1start
= desired_glyphs
->glyphs
[vpos
] + hpos
;
4723 int window_width
= XFASTINT (w
->width
);
4724 /* If 1, we must display multibyte characters. */
4725 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
4727 /* Use the standard display table, not the window's display table.
4728 We don't want the mode line in rot13. */
4729 register struct Lisp_Char_Table
*dp
= 0;
4732 if (DISP_TABLE_P (Vstandard_display_table
))
4733 dp
= XCHAR_TABLE (Vstandard_display_table
);
4735 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
4738 start
= desired_glyphs
->glyphs
[vpos
];
4740 if (obey_window_width
)
4742 start
+= XFASTINT (w
->left
);
4743 end
= start
+ window_width
- (truncate
!= 0);
4745 if (!WINDOW_RIGHTMOST_P (w
))
4747 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f
))
4751 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
4754 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
4759 if (! obey_window_width
4760 || (maxcol
>= 0 && end
- desired_glyphs
->glyphs
[vpos
] > maxcol
))
4761 end
= desired_glyphs
->glyphs
[vpos
] + maxcol
;
4763 /* Store 0 in charstart for these columns. */
4764 for (i
= (hpos
>= 0 ? hpos
: 0); i
< end
- p1start
+ hpos
; i
++)
4765 desired_glyphs
->charstarts
[vpos
][i
] = 0;
4767 if (maxcol
>= 0 && mincol
> maxcol
)
4771 /* We need this value for multibyte characters. */
4772 length
= strlen (string
);
4774 /* We set truncated to 1 if we get stopped by trying to pass END
4775 (that is, trying to pass MAXCOL.) */
4784 c
= STRING_CHAR_AND_LENGTH (string
, length
, len
);
4786 c
= *string
, len
= 1;
4788 string
+= len
, length
-= len
;
4796 if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
4798 p1
= copy_part_of_rope (f
, p1
, start
,
4799 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
4800 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
4803 else if (c
>= 040 && c
< 0177)
4813 if (p1
>= start
&& p1
< end
)
4817 while ((p1
- start
+ hscroll
- (hscroll
> 0)) % tab_width
);
4819 else if (c
< 0200 && ! NILP (buffer_defaults
.ctl_arrow
))
4823 (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
4824 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp
)))
4825 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
4828 if (p1
>= start
&& p1
< end
)
4834 /* C is a control character or a binary byte data. */
4837 (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
4838 && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp
)))
4839 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
4842 if (p1
>= start
&& p1
< end
)
4843 *p1
= (c
>> 6) + '0';
4845 if (p1
>= start
&& p1
< end
)
4846 *p1
= (7 & (c
>> 3)) + '0';
4848 if (p1
>= start
&& p1
< end
)
4849 *p1
= (7 & c
) + '0';
4854 /* C is a multibyte character. */
4855 int charset
= CHAR_CHARSET (c
);
4856 int columns
= (charset
== CHARSET_COMPOSITION
4857 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
4858 : CHARSET_WIDTH (charset
));
4862 /* Since we can't show the left part of C, fill all
4863 columns with spaces. */
4864 columns
-= start
- p1
;
4873 else if (p1
+ columns
> end
)
4875 /* Since we can't show the right part of C, fill all
4876 columns with TRUNCATE if TRUNCATE is specified. */
4880 *p1
++ = fix_glyph (f
, truncate
, 0);
4881 /* And tell the line is truncated. */
4888 /* We can show the whole glyph of C. */
4891 *p1
++ = c
| GLYPH_MASK_PADDING
;
4899 if (truncate
) *p1
++ = fix_glyph (f
, truncate
, 0);
4901 else if (mincol
>= 0)
4903 end
= desired_glyphs
->glyphs
[vpos
] + mincol
;
4909 register int len
= p1
- desired_glyphs
->glyphs
[vpos
];
4911 if (len
> desired_glyphs
->used
[vpos
])
4912 desired_glyphs
->used
[vpos
] = len
;
4913 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
4919 /* This is like a combination of memq and assq.
4920 Return 1 if PROPVAL appears as an element of LIST
4921 or as the car of an element of LIST.
4922 If PROPVAL is a list, compare each element against LIST
4923 in that way, and return 1 if any element of PROPVAL is found in LIST.
4925 This function cannot quit. */
4928 invisible_p (propval
, list
)
4929 register Lisp_Object propval
;
4932 register Lisp_Object tail
, proptail
;
4933 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4935 register Lisp_Object tem
;
4936 tem
= XCONS (tail
)->car
;
4937 if (EQ (propval
, tem
))
4939 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4942 if (CONSP (propval
))
4943 for (proptail
= propval
; CONSP (proptail
);
4944 proptail
= XCONS (proptail
)->cdr
)
4946 Lisp_Object propelt
;
4947 propelt
= XCONS (proptail
)->car
;
4948 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4950 register Lisp_Object tem
;
4951 tem
= XCONS (tail
)->car
;
4952 if (EQ (propelt
, tem
))
4954 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4961 /* Return 1 if PROPVAL appears as the car of an element of LIST
4962 and the cdr of that element is non-nil.
4963 If PROPVAL is a list, check each element of PROPVAL in that way,
4964 and the first time some element is found,
4965 return 1 if the cdr of that element is non-nil.
4967 This function cannot quit. */
4970 invisible_ellipsis_p (propval
, list
)
4971 register Lisp_Object propval
;
4974 register Lisp_Object tail
, proptail
;
4975 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4977 register Lisp_Object tem
;
4978 tem
= XCONS (tail
)->car
;
4979 if (CONSP (tem
) && EQ (propval
, XCONS (tem
)->car
))
4980 return ! NILP (XCONS (tem
)->cdr
);
4982 if (CONSP (propval
))
4983 for (proptail
= propval
; CONSP (proptail
);
4984 proptail
= XCONS (proptail
)->cdr
)
4986 Lisp_Object propelt
;
4987 propelt
= XCONS (proptail
)->car
;
4988 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
4990 register Lisp_Object tem
;
4991 tem
= XCONS (tail
)->car
;
4992 if (CONSP (tem
) && EQ (propelt
, XCONS (tem
)->car
))
4993 return ! NILP (XCONS (tem
)->cdr
);
5002 staticpro (&Qmenu_bar_update_hook
);
5003 Qmenu_bar_update_hook
= intern ("menu-bar-update-hook");
5005 staticpro (&Qoverriding_terminal_local_map
);
5006 Qoverriding_terminal_local_map
= intern ("overriding-terminal-local-map");
5008 staticpro (&Qoverriding_local_map
);
5009 Qoverriding_local_map
= intern ("overriding-local-map");
5011 staticpro (&Qwindow_scroll_functions
);
5012 Qwindow_scroll_functions
= intern ("window-scroll-functions");
5014 staticpro (&Qredisplay_end_trigger_functions
);
5015 Qredisplay_end_trigger_functions
= intern ("redisplay-end-trigger-functions");
5017 staticpro (&last_arrow_position
);
5018 staticpro (&last_arrow_string
);
5019 last_arrow_position
= Qnil
;
5020 last_arrow_string
= Qnil
;
5022 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
,
5023 "String (or mode line construct) included (normally) in `mode-line-format'.");
5024 Vglobal_mode_string
= Qnil
;
5026 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
,
5027 "Marker for where to display an arrow on top of the buffer text.\n\
5028 This must be the beginning of a line in order to work.\n\
5029 See also `overlay-arrow-string'.");
5030 Voverlay_arrow_position
= Qnil
;
5032 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
,
5033 "String to display as an arrow. See also `overlay-arrow-position'.");
5034 Voverlay_arrow_string
= Qnil
;
5036 DEFVAR_INT ("scroll-step", &scroll_step
,
5037 "*The number of lines to try scrolling a window by when point moves out.\n\
5038 If that fails to bring point back on frame, point is centered instead.\n\
5039 If this is zero, point is always centered after it moves off frame.");
5041 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively
,
5042 "*Scroll up to this many lines, to bring point back on screen.");
5043 scroll_conservatively
= 0;
5045 DEFVAR_INT ("scroll-margin", &scroll_margin
,
5046 "*Number of lines of margin at the top and bottom of a window.\n\
5047 Recenter the window whenever point gets within this many lines\n\
5048 of the top or bottom of the window.");
5051 DEFVAR_INT ("debug-end-pos", &debug_end_pos
, "Don't ask");
5053 DEFVAR_BOOL ("truncate-partial-width-windows",
5054 &truncate_partial_width_windows
,
5055 "*Non-nil means truncate lines in all windows less than full frame wide.");
5056 truncate_partial_width_windows
= 1;
5058 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
,
5059 "*Non-nil means use inverse video for the mode line.");
5060 mode_line_inverse_video
= 1;
5062 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit
,
5063 "*Maximum buffer size for which line number should be displayed.");
5064 line_number_display_limit
= 1000000;
5066 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
,
5067 "*Non-nil means highlight region even in nonselected windows.");
5068 highlight_nonselected_windows
= 0;
5070 DEFVAR_BOOL ("multiple-frames", &multiple_frames
,
5071 "Non-nil if more than one frame is visible on this display.\n\
5072 Minibuffer-only frames don't count, but iconified frames do.\n\
5073 This variable is not guaranteed to be accurate except while processing\n\
5074 `frame-title-format' and `icon-title-format'.");
5076 DEFVAR_LISP ("frame-title-format", &Vframe_title_format
,
5077 "Template for displaying the titlebar of visible frames.\n\
5078 \(Assuming the window manager supports this feature.)\n\
5079 This variable has the same structure as `mode-line-format' (which see),\n\
5080 and is used only on frames for which no explicit name has been set\n\
5081 \(see `modify-frame-parameters').");
5082 DEFVAR_LISP ("icon-title-format", &Vicon_title_format
,
5083 "Template for displaying the titlebar of an iconified frame.\n\
5084 \(Assuming the window manager supports this feature.)\n\
5085 This variable has the same structure as `mode-line-format' (which see),\n\
5086 and is used only on frames for which no explicit name has been set\n\
5087 \(see `modify-frame-parameters').");
5089 = Vframe_title_format
5090 = Fcons (intern ("multiple-frames"),
5091 Fcons (build_string ("%b"),
5092 Fcons (Fcons (build_string (""),
5093 Fcons (intern ("invocation-name"),
5094 Fcons (build_string ("@"),
5095 Fcons (intern ("system-name"),
5099 DEFVAR_LISP ("message-log-max", &Vmessage_log_max
,
5100 "Maximum number of lines to keep in the message log buffer.\n\
5101 If nil, disable message logging. If t, log messages but don't truncate\n\
5102 the buffer when it becomes large.");
5103 XSETFASTINT (Vmessage_log_max
, 50);
5105 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions
,
5106 "Functions called before redisplay, if window sizes have changed.\n\
5107 The value should be a list of functions that take one argument.\n\
5108 Just before redisplay, for each frame, if any of its windows have changed\n\
5109 size since the last redisplay, or have been split or deleted,\n\
5110 all the functions in the list are called, with the frame as argument.");
5111 Vwindow_size_change_functions
= Qnil
;
5113 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions
,
5114 "List of Functions to call before redisplaying a window with scrolling.\n\
5115 Each function is called with two arguments, the window\n\
5116 and its new display-start position. Note that the value of `window-end'\n\
5117 is not valid when these functions are called.");
5118 Vwindow_scroll_functions
= Qnil
;
5121 /* initialize the window system */
5124 Lisp_Object root_window
;
5125 #ifndef COMPILER_REGISTER_BUG
5127 #endif /* COMPILER_REGISTER_BUG */
5128 struct window
*mini_w
;
5130 this_line_bufpos
= 0;
5132 mini_w
= XWINDOW (minibuf_window
);
5133 root_window
= FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w
)));
5135 echo_area_glyphs
= 0;
5136 previous_echo_glyphs
= 0;
5138 if (!noninteractive
)
5140 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (root_window
)));
5141 XSETFASTINT (XWINDOW (root_window
)->top
, FRAME_MENU_BAR_LINES (f
));
5142 set_window_height (root_window
,
5143 FRAME_HEIGHT (f
) - 1 - FRAME_MENU_BAR_LINES (f
),
5145 XSETFASTINT (mini_w
->top
, FRAME_HEIGHT (f
) - 1);
5146 set_window_height (minibuf_window
, 1, 0);
5148 XSETFASTINT (XWINDOW (root_window
)->width
, FRAME_WIDTH (f
));
5149 XSETFASTINT (mini_w
->width
, FRAME_WIDTH (f
));