1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 /*#include <ctype.h>*/
29 #include "dispextern.h"
35 #include "termhooks.h"
36 #include "intervals.h"
39 extern void set_frame_menubar ();
42 extern int interrupt_input
;
43 extern int command_loop_level
;
45 extern Lisp_Object Qface
;
47 /* Nonzero means print newline before next minibuffer message. */
49 int noninteractive_need_newline
;
51 #define min(a, b) ((a) < (b) ? (a) : (b))
52 #define max(a, b) ((a) > (b) ? (a) : (b))
54 /* The buffer position of the first character appearing
55 entirely or partially on the current frame line.
56 Or zero, which disables the optimization for the current frame line. */
57 static int this_line_bufpos
;
59 /* Number of characters past the end of this line,
60 including the terminating newline */
61 static int this_line_endpos
;
63 /* The vertical position of this frame line. */
64 static int this_line_vpos
;
66 /* Hpos value for start of display on this frame line.
67 Usually zero, but negative if first character really began
69 static int this_line_start_hpos
;
71 /* Buffer that this_line variables are describing. */
72 static struct buffer
*this_line_buffer
;
74 /* Set by try_window_id to the vpos of first of any lines
75 scrolled on to the bottom of the frame. These lines should
76 not be included in any general scroll computation. */
77 static int scroll_bottom_vpos
;
79 /* Value of echo_area_glyphs when it was last acted on.
80 If this is nonzero, there is a message on the frame
81 in the minibuffer and it should be erased as soon
82 as it is no longer requested to appear. */
83 char *previous_echo_glyphs
;
85 /* Nonzero means truncate lines in all windows less wide than the frame */
86 int truncate_partial_width_windows
;
88 /* Nonzero means we have more than one non-minibuffer-only frame.
89 Not guaranteed to be accurate except while parsing frame-title-format. */
92 Lisp_Object Vglobal_mode_string
;
94 /* Marker for where to display an arrow on top of the buffer text. */
95 Lisp_Object Voverlay_arrow_position
;
97 /* String to display for the arrow. */
98 Lisp_Object Voverlay_arrow_string
;
100 /* Like mode-line-format, but for the titlebar on a visible frame. */
101 Lisp_Object Vframe_title_format
;
103 /* Like mode-line-format, but for the titlebar on an iconified frame. */
104 Lisp_Object Vicon_title_format
;
106 /* Values of those variables at last redisplay. */
107 static Lisp_Object last_arrow_position
, last_arrow_string
;
109 Lisp_Object Qmenu_bar_update_hook
;
111 /* Nonzero if overlay arrow has been displayed once in this window. */
112 static int overlay_arrow_seen
;
114 /* Nonzero means highlight the region even in nonselected windows. */
115 static int highlight_nonselected_windows
;
117 /* If cursor motion alone moves point off frame,
118 Try scrolling this many lines up or down if that will bring it back. */
121 /* Nonzero if try_window_id has made blank lines at window bottom
122 since the last redisplay that paused */
123 static int blank_end_of_window
;
125 /* Number of windows showing the buffer of the selected window.
126 keyboard.c refers to this. */
129 /* display_text_line sets these to the frame position (origin 0) of point,
130 whether the window is selected or not.
131 Set one to -1 first to determine whether point was found afterwards. */
133 static int cursor_vpos
;
134 static int cursor_hpos
;
138 /* Nonzero means display mode line highlighted */
139 int mode_line_inverse_video
;
141 static void echo_area_display ();
142 void mark_window_display_accurate ();
143 static void redisplay_windows ();
144 static void redisplay_window ();
145 static void update_menu_bars ();
146 static void update_menu_bar ();
147 static void try_window ();
148 static int try_window_id ();
149 static struct position
*display_text_line ();
150 static void display_mode_line ();
151 static int display_mode_element ();
152 static char *fmodetrunc ();
153 static char *decode_mode_spec ();
154 static int display_string ();
155 static void display_menu_bar ();
156 static int display_count_lines ();
158 /* Prompt to display in front of the minibuffer contents */
159 Lisp_Object minibuf_prompt
;
161 /* Width in columns of current minibuffer prompt. */
162 int minibuf_prompt_width
;
164 /* Message to display instead of minibuffer contents
165 This is what the functions error and message make,
166 and command echoing uses it as well.
167 It overrides the minibuf_prompt as well as the buffer. */
168 char *echo_area_glyphs
;
170 /* This is the length of the message in echo_area_glyphs. */
171 int echo_area_glyphs_length
;
173 /* true iff we should redraw the mode lines on the next redisplay */
174 int update_mode_lines
;
176 /* Smallest number of characters before the gap
177 at any time since last redisplay that finished.
178 Valid for current buffer when try_window_id can be called. */
181 /* Smallest number of characters after the gap
182 at any time since last redisplay that finished.
183 Valid for current buffer when try_window_id can be called. */
186 /* MODIFF as of last redisplay that finished;
187 if it matches MODIFF, beg_unchanged and end_unchanged
188 contain no useful information */
189 int unchanged_modified
;
191 /* Nonzero if head_clip or tail_clip of current buffer has changed
192 since last redisplay that finished */
195 /* Nonzero if window sizes or contents have changed
196 since last redisplay that finished */
197 int windows_or_buffers_changed
;
199 /* Nonzero after display_mode_line if %l was used
200 and it displayed a line number. */
201 int line_number_displayed
;
203 /* Maximum buffer size for which to display line numbers. */
204 int line_number_display_limit
;
206 /* Display an echo area message M with a specified length of LEN chars.
207 The string may include null characters. If m is 0, clear out any
208 existing message, and let the minibuffer text show through.
209 Do not pass text that is stored in a Lisp string. */
218 if (noninteractive_need_newline
)
220 noninteractive_need_newline
= 0;
221 fwrite (m
, len
, 1, stderr
);
222 if (cursor_in_echo_area
== 0)
223 fprintf (stderr
, "\n");
226 /* A null message buffer means that the frame hasn't really been
227 initialized yet. Error messages get reported properly by
228 cmd_error, so this must be just an informative message; toss it. */
229 else if (INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
232 Lisp_Object minibuf_frame
;
234 choose_minibuf_frame ();
235 minibuf_frame
= WINDOW_FRAME (XWINDOW (minibuf_window
));
236 FRAME_SAMPLE_VISIBILITY (XFRAME (minibuf_frame
));
237 if (FRAME_VISIBLE_P (selected_frame
)
238 && ! FRAME_VISIBLE_P (XFRAME (minibuf_frame
)))
239 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (minibuf_window
)));
244 echo_area_glyphs
= m
;
245 echo_area_glyphs_length
= len
;
248 echo_area_glyphs
= previous_echo_glyphs
= 0;
250 do_pending_window_change ();
251 echo_area_display ();
252 update_frame (XFRAME (XWINDOW (minibuf_window
)->frame
), 1, 1);
253 do_pending_window_change ();
254 if (frame_up_to_date_hook
!= 0 && ! gc_in_progress
)
255 (*frame_up_to_date_hook
) (XFRAME (XWINDOW (minibuf_window
)->frame
));
263 message2 (m
, (m
? strlen (m
) : 0));
266 /* Truncate what will be displayed in the echo area
267 the next time we display it--but don't redisplay it now. */
270 truncate_echo_area (len
)
273 /* A null message buffer means that the frame hasn't really been
274 initialized yet. Error messages get reported properly by
275 cmd_error, so this must be just an informative message; toss it. */
276 if (!noninteractive
&& INTERACTIVE
&& FRAME_MESSAGE_BUF (selected_frame
))
277 echo_area_glyphs_length
= len
;
280 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
281 zero if being used by message. */
282 int message_buf_print
;
284 /* Dump an informative message to the minibuf. If m is 0, clear out
285 any existing message, and let the minibuffer text show through. */
288 message (m
, a1
, a2
, a3
)
290 EMACS_INT a1
, a2
, a3
;
296 if (noninteractive_need_newline
)
298 noninteractive_need_newline
= 0;
299 fprintf (stderr
, m
, a1
, a2
, a3
);
300 if (cursor_in_echo_area
== 0)
301 fprintf (stderr
, "\n");
305 else if (INTERACTIVE
)
307 /* The frame whose minibuffer we're going to display the message on.
308 It may be larger than the selected frame, so we need
309 to use its buffer, not the selected frame's buffer. */
310 FRAME_PTR echo_frame
;
312 choose_minibuf_frame ();
313 echo_frame
= XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window
)));
315 echo_frame
= selected_frame
;
318 /* A null message buffer means that the frame hasn't really been
319 initialized yet. Error messages get reported properly by
320 cmd_error, so this must be just an informative message; toss it. */
321 if (FRAME_MESSAGE_BUF (echo_frame
))
332 len
= doprnt (FRAME_MESSAGE_BUF (echo_frame
),
333 FRAME_WIDTH (echo_frame
), m
, 0, 3, a
);
335 len
= doprnt (FRAME_MESSAGE_BUF (echo_frame
),
336 FRAME_WIDTH (echo_frame
), m
, 0, 3, &a1
);
337 #endif /* NO_ARG_ARRAY */
339 message2 (FRAME_MESSAGE_BUF (echo_frame
), len
);
344 /* Print should start at the beginning of the message
346 message_buf_print
= 0;
354 message2 (echo_area_glyphs
, echo_area_glyphs_length
);
364 choose_minibuf_frame ();
367 f
= XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window
)));
369 if (! FRAME_VISIBLE_P (f
))
374 redraw_garbaged_frames ();
378 if (echo_area_glyphs
|| minibuf_level
== 0)
380 vpos
= XFASTINT (XWINDOW (minibuf_window
)->top
);
381 get_display_line (f
, vpos
, 0);
382 display_string (XWINDOW (minibuf_window
), vpos
,
383 echo_area_glyphs
? echo_area_glyphs
: "",
384 echo_area_glyphs
? echo_area_glyphs_length
: -1,
385 0, 0, 0, 0, FRAME_WIDTH (f
));
387 /* If desired cursor location is on this line, put it at end of text */
388 if (FRAME_CURSOR_Y (f
) == vpos
)
389 FRAME_CURSOR_X (f
) = FRAME_DESIRED_GLYPHS (f
)->used
[vpos
];
391 /* Fill the rest of the minibuffer window with blank lines. */
396 i
< vpos
+ XFASTINT (XWINDOW (minibuf_window
)->height
); i
++)
398 get_display_line (f
, i
, 0);
399 display_string (XWINDOW (minibuf_window
), vpos
,
400 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f
));
404 else if (!EQ (minibuf_window
, selected_window
))
405 windows_or_buffers_changed
++;
407 if (EQ (minibuf_window
, selected_window
))
408 this_line_bufpos
= 0;
410 previous_echo_glyphs
= echo_area_glyphs
;
413 #ifdef HAVE_X_WINDOWS
414 static char frame_title_buf
[512];
415 static char *frame_title_ptr
;
418 store_frame_title (str
, mincol
, maxcol
)
423 if (maxcol
< 0 || maxcol
>= sizeof(frame_title_buf
))
424 maxcol
= sizeof (frame_title_buf
);
425 limit
= &frame_title_buf
[maxcol
];
426 while (*str
!= '\0' && frame_title_ptr
< limit
)
427 *frame_title_ptr
++ = *str
++;
428 while (frame_title_ptr
< &frame_title_buf
[mincol
])
429 *frame_title_ptr
++ = ' ';
430 return frame_title_ptr
- frame_title_buf
;
434 x_consider_frame_title (frame
)
440 FRAME_PTR f
= XFRAME (frame
);
442 if (!FRAME_X_P (f
) || FRAME_MINIBUF_ONLY_P (f
) || f
->explicit_name
)
444 multiple_frames
= !EQ (Fnext_frame (frame
, Qnil
), frame
);
445 obuf
= current_buffer
;
446 Fset_buffer (XWINDOW (f
->selected_window
)->buffer
);
447 fmt
= (FRAME_ICONIFIED_P (f
) ? Vicon_title_format
: Vframe_title_format
);
448 frame_title_ptr
= frame_title_buf
;
449 len
= display_mode_element (XWINDOW (f
->selected_window
), 0, 0, 0,
450 0, sizeof (frame_title_buf
), fmt
);
452 set_buffer_internal (obuf
);
453 /* Set the name only if it's changed. This avoids consing
454 in the common case where it hasn't. (If it turns out that we've
455 already wasted too much time by walking through the list with
456 display_mode_element, then we might need to optimize at a higher
458 if (! STRINGP (f
->name
) || XSTRING (f
->name
)->size
!= len
459 || bcmp (frame_title_buf
, XSTRING (f
->name
)->data
, len
) != 0)
460 x_implicitly_set_name (f
, make_string (frame_title_buf
, len
), Qnil
);
463 #define frame_title_ptr ((char *)0)
464 #define store_frame_title(str, mincol, maxcol) 0
467 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
468 This can't be done in `redisplay' itself because it can call eval. */
473 register struct window
*w
= XWINDOW (selected_window
);
479 /* Set the visible flags for all frames.
480 Do this before checking for resized or garbaged frames; they want
481 to know if their frames are visible.
482 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
484 Lisp_Object tail
, frame
;
486 FOR_EACH_FRAME (tail
, frame
)
487 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
490 /* Notice any pending interrupt request to change frame size. */
491 do_pending_window_change ();
495 redraw_garbaged_frames ();
499 all_windows
= (update_mode_lines
|| buffer_shared
> 1
500 || clip_changed
|| windows_or_buffers_changed
);
502 #ifdef HAVE_X_WINDOWS
503 if (windows_or_buffers_changed
)
505 Lisp_Object tail
, frame
;
507 FOR_EACH_FRAME (tail
, frame
)
508 if (FRAME_VISIBLE_P (XFRAME (frame
))
509 || FRAME_ICONIFIED_P (XFRAME (frame
)))
510 x_consider_frame_title (frame
);
514 /* Update the menu bar item lists, if appropriate.
515 This has to be done before any actual redisplay
516 or generation of display lines. */
519 Lisp_Object tail
, frame
;
521 FOR_EACH_FRAME (tail
, frame
)
522 update_menu_bar (XFRAME (frame
));
525 update_menu_bar (selected_frame
);
528 /* Do a frame update, taking possible shortcuts into account.
529 This is the main external entry point for redisplay.
531 If the last redisplay displayed an echo area message and that
532 message is no longer requested, we clear the echo area
533 or bring back the minibuffer if that is in use.
535 Do not call eval from within this function.
536 Calls to eval after the call to echo_area_display would confuse
537 the display_line mechanism and would cause a crash.
538 Calls to eval before that point will work most of the time,
539 but can still lose, because this function
540 can be called from signal handlers; with alarms set up;
541 or with synchronous processes running.
543 See Fcall_process; if you called it from here, it could be
544 entered recursively. */
546 static int do_verify_charstarts
;
548 /* Counter is used to clear the face cache
549 no more than once ever 1000 redisplays. */
550 static int clear_face_cache_count
;
555 register struct window
*w
= XWINDOW (selected_window
);
559 register int tlbufpos
, tlendpos
;
561 extern int input_pending
;
566 /* Set the visible flags for all frames.
567 Do this before checking for resized or garbaged frames; they want
568 to know if their frames are visible.
569 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
571 Lisp_Object tail
, frame
;
573 FOR_EACH_FRAME (tail
, frame
)
574 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
577 /* Notice any pending interrupt request to change frame size. */
578 do_pending_window_change ();
582 redraw_garbaged_frames ();
586 if (clip_changed
|| windows_or_buffers_changed
)
589 /* Detect case that we need to write a star in the mode line. */
590 if (XFASTINT (w
->last_modified
) < MODIFF
591 && XFASTINT (w
->last_modified
) <= current_buffer
->save_modified
)
593 w
->update_mode_line
= Qt
;
594 if (buffer_shared
> 1)
598 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w
->frame
)) = -1;
600 all_windows
= update_mode_lines
|| buffer_shared
> 1;
602 /* If specs for an arrow have changed, do thorough redisplay
603 to ensure we remove any arrow that should no longer exist. */
604 if (! EQ (Voverlay_arrow_position
, last_arrow_position
)
605 || ! EQ (Voverlay_arrow_string
, last_arrow_string
))
606 all_windows
= 1, clip_changed
= 1;
608 /* Normally the message* functions will have already displayed and
609 updated the echo area, but the frame may have been trashed, or
610 the update may have been preempted, so display the echo area
612 if (echo_area_glyphs
|| previous_echo_glyphs
)
614 echo_area_display ();
618 /* If showing region, and mark has changed, must redisplay whole window. */
619 if (((!NILP (Vtransient_mark_mode
)
620 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
621 != !NILP (w
->region_showing
))
622 || (!NILP (w
->region_showing
)
623 && !EQ (w
->region_showing
,
624 Fmarker_position (XBUFFER (w
->buffer
)->mark
))))
625 this_line_bufpos
= -1;
627 tlbufpos
= this_line_bufpos
;
628 tlendpos
= this_line_endpos
;
629 if (!all_windows
&& tlbufpos
> 0 && NILP (w
->update_mode_line
)
630 && FRAME_VISIBLE_P (XFRAME (w
->frame
))
631 /* Make sure recorded data applies to current buffer, etc */
632 && this_line_buffer
== current_buffer
633 && current_buffer
== XBUFFER (w
->buffer
)
634 && NILP (w
->force_start
)
635 /* Point must be on the line that we have info recorded about */
637 && PT
<= Z
- tlendpos
638 /* All text outside that line, including its final newline,
640 && (XFASTINT (w
->last_modified
) >= MODIFF
641 || (beg_unchanged
>= tlbufpos
- 1
643 /* If selective display, can't optimize
644 if the changes start at the beginning of the line. */
645 && ((INTEGERP (current_buffer
->selective_display
)
646 && XINT (current_buffer
->selective_display
) > 0
647 ? (beg_unchanged
>= tlbufpos
650 && end_unchanged
>= tlendpos
651 && Z
- GPT
>= tlendpos
)))
653 if (tlbufpos
> BEGV
&& FETCH_CHAR (tlbufpos
- 1) != '\n'
655 || FETCH_CHAR (tlbufpos
) == '\n'))
656 /* Former continuation line has disappeared by becoming empty */
658 else if (XFASTINT (w
->last_modified
) < MODIFF
659 || MINI_WINDOW_P (w
))
662 overlay_arrow_seen
= 0;
663 display_text_line (w
, tlbufpos
, this_line_vpos
, this_line_start_hpos
,
664 pos_tab_offset (w
, tlbufpos
));
665 /* If line contains point, is not continued,
666 and ends at same distance from eob as before, we win */
667 if (cursor_vpos
>= 0 && this_line_bufpos
668 && this_line_endpos
== tlendpos
)
670 /* If this is not the window's last line,
671 we must adjust the charstarts of the lines below. */
672 if (this_line_vpos
+ 1
673 < XFASTINT (w
->top
) + window_internal_height (w
))
675 int left
= XFASTINT (w
->left
);
676 int *charstart_next_line
677 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w
)))->charstarts
[this_line_vpos
+ 1];
681 if (Z
- tlendpos
== ZV
)
682 /* This line ends at end of (accessible part of) buffer.
683 There is no newline to count. */
684 adjust
= Z
- tlendpos
- charstart_next_line
[left
];
686 /* This line ends in a newline.
687 Must take account of the newline and the rest of the
688 text that follows. */
689 adjust
= Z
- tlendpos
+ 1 - charstart_next_line
[left
];
691 adjust_window_charstarts (w
, this_line_vpos
, adjust
);
694 if (XFASTINT (w
->width
) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w
))))
695 preserve_other_columns (w
);
701 else if (PT
== XFASTINT (w
->last_point
))
705 do_pending_window_change ();
710 /* If highlighting the region, we can't just move the cursor. */
711 else if (! (!NILP (Vtransient_mark_mode
)
712 && !NILP (current_buffer
->mark_active
))
713 && NILP (w
->region_showing
))
715 pos
= *compute_motion (tlbufpos
, 0,
716 XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0,
717 PT
, 2, - (1 << (SHORTBITS
- 1)),
718 window_internal_width (w
) - 1,
720 pos_tab_offset (w
, tlbufpos
), w
);
723 FRAME_CURSOR_X (selected_frame
)
724 = XFASTINT (w
->left
) + max (pos
.hpos
, 0);
725 FRAME_CURSOR_Y (selected_frame
) = this_line_vpos
;
732 /* Text changed drastically or point moved off of line */
733 cancel_line (this_line_vpos
, selected_frame
);
736 this_line_bufpos
= 0;
737 all_windows
|= buffer_shared
> 1;
739 clear_face_cache_count
++;
743 Lisp_Object tail
, frame
;
746 /* Clear the face cache, only when we do a full redisplay
747 and not too often either. */
748 if (clear_face_cache_count
> 1000)
751 clear_face_cache_count
= 0;
755 /* Recompute # windows showing selected buffer.
756 This will be incremented each time such a window is displayed. */
759 FOR_EACH_FRAME (tail
, frame
)
761 FRAME_PTR f
= XFRAME (frame
);
763 /* Mark all the scroll bars to be removed; we'll redeem the ones
764 we want when we redisplay their windows. */
765 if (condemn_scroll_bars_hook
)
766 (*condemn_scroll_bars_hook
) (f
);
768 if (FRAME_VISIBLE_P (f
))
769 redisplay_windows (FRAME_ROOT_WINDOW (f
));
771 /* Any scroll bars which redisplay_windows should have nuked
772 should now go away. */
773 if (judge_scroll_bars_hook
)
774 (*judge_scroll_bars_hook
) (f
);
777 else if (FRAME_VISIBLE_P (selected_frame
))
779 redisplay_window (selected_window
, 1);
780 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
781 preserve_other_columns (w
);
785 /* Prevent various kinds of signals during display update.
786 stdio is not robust about handling signals,
787 which can cause an apparent I/O error. */
799 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
803 if (!FRAMEP (XCONS (tail
)->car
))
806 f
= XFRAME (XCONS (tail
)->car
);
807 if (FRAME_VISIBLE_P (f
))
809 pause
|= update_frame (f
, 0, 0);
812 mark_window_display_accurate (f
->root_window
, 1);
813 if (frame_up_to_date_hook
!= 0)
814 (*frame_up_to_date_hook
) (f
);
820 #endif /* MULTI_FRAME */
822 if (FRAME_VISIBLE_P (selected_frame
))
823 pause
= update_frame (selected_frame
, 0, 0);
825 /* We may have called echo_area_display at the top of this
826 function. If the echo area is on another frame, that may
827 have put text on a frame other than the selected one, so the
828 above call to update_frame would not have caught it. Catch
832 = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window
)));
834 if (mini_frame
!= selected_frame
)
835 pause
|= update_frame (mini_frame
, 0, 0);
839 /* If frame does not match, prevent doing single-line-update next time.
840 Also, don't forget to check every line to update the arrow. */
843 this_line_bufpos
= 0;
844 if (!NILP (last_arrow_position
))
846 last_arrow_position
= Qt
;
847 last_arrow_string
= Qt
;
849 /* If we pause after scrolling, some lines in current_frame
850 may be null, so preserve_other_columns won't be able to
851 preserve all the vertical-bar separators. So, avoid using it
853 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
854 update_mode_lines
= 1;
857 /* Now text on frame agrees with windows, so
858 put info into the windows for partial redisplay to follow */
862 register struct buffer
*b
= XBUFFER (w
->buffer
);
864 blank_end_of_window
= 0;
866 unchanged_modified
= BUF_MODIFF (b
);
867 beg_unchanged
= BUF_GPT (b
) - BUF_BEG (b
);
868 end_unchanged
= BUF_Z (b
) - BUF_GPT (b
);
870 XSETFASTINT (w
->last_point
, BUF_PT (b
));
871 XSETFASTINT (w
->last_point_x
, FRAME_CURSOR_X (selected_frame
));
872 XSETFASTINT (w
->last_point_y
, FRAME_CURSOR_Y (selected_frame
));
875 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame
), 1);
878 w
->update_mode_line
= Qnil
;
879 XSETFASTINT (w
->last_modified
, BUF_MODIFF (b
));
880 w
->window_end_valid
= w
->buffer
;
881 last_arrow_position
= Voverlay_arrow_position
;
882 last_arrow_string
= Voverlay_arrow_string
;
883 if (do_verify_charstarts
)
884 verify_charstarts (w
);
885 if (frame_up_to_date_hook
!= 0)
886 (*frame_up_to_date_hook
) (selected_frame
);
888 update_mode_lines
= 0;
889 windows_or_buffers_changed
= 0;
892 /* Start SIGIO interrupts coming again.
893 Having them off during the code above
894 makes it less likely one will discard output,
895 but not impossible, since there might be stuff
896 in the system buffer here.
897 But it is much hairier to try to do anything about that. */
903 /* Change frame size now if a change is pending. */
904 do_pending_window_change ();
906 /* If we just did a pending size change, redisplay again
908 if (windows_or_buffers_changed
&& !pause
)
912 /* Redisplay, but leave alone any recent echo area message
913 unless another message has been requested in its place.
915 This is useful in situations where you need to redisplay but no
916 user action has occurred, making it inappropriate for the message
917 area to be cleared. See tracking_off and
918 wait_reading_process_input for examples of these situations. */
920 redisplay_preserve_echo_area ()
922 if (echo_area_glyphs
== 0 && previous_echo_glyphs
!= 0)
924 echo_area_glyphs
= previous_echo_glyphs
;
926 echo_area_glyphs
= 0;
933 mark_window_display_accurate (window
, flag
)
937 register struct window
*w
;
939 for (;!NILP (window
); window
= w
->next
)
941 if (!WINDOWP (window
)) abort ();
942 w
= XWINDOW (window
);
944 if (!NILP (w
->buffer
))
946 XSETFASTINT (w
->last_modified
,
947 !flag
? 0 : BUF_MODIFF (XBUFFER (w
->buffer
)));
949 /* Record if we are showing a region, so can make sure to
950 update it fully at next redisplay. */
951 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
952 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
953 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
957 w
->window_end_valid
= w
->buffer
;
958 w
->update_mode_line
= Qnil
;
960 if (!NILP (w
->vchild
))
961 mark_window_display_accurate (w
->vchild
, flag
);
962 if (!NILP (w
->hchild
))
963 mark_window_display_accurate (w
->hchild
, flag
);
968 last_arrow_position
= Voverlay_arrow_position
;
969 last_arrow_string
= Voverlay_arrow_string
;
973 /* t is unequal to any useful value of Voverlay_arrow_... */
974 last_arrow_position
= Qt
;
975 last_arrow_string
= Qt
;
979 /* Update the menu bar item list for frame F.
980 This has to be done before we start to fill in any display lines,
981 because it can call eval. */
987 struct buffer
*old
= current_buffer
;
989 register struct window
*w
;
990 window
= FRAME_SELECTED_WINDOW (f
);
991 w
= XWINDOW (window
);
993 if (update_mode_lines
)
994 w
->update_mode_line
= Qt
;
998 FRAME_EXTERNAL_MENU_BAR (f
)
1000 FRAME_MENU_BAR_LINES (f
) > 0
1004 /* If the user has switched buffers or windows, we need to
1005 recompute to reflect the new bindings. But we'll
1006 recompute when update_mode_lines is set too; that means
1007 that people can use force-mode-line-update to request
1008 that the menu bar be recomputed. The adverse effect on
1009 the rest of the redisplay algorithm is about the same as
1010 windows_or_buffers_changed anyway. */
1011 if (windows_or_buffers_changed
1012 || !NILP (w
->update_mode_line
)
1013 || (XFASTINT (w
->last_modified
) < MODIFF
1014 && (XFASTINT (w
->last_modified
)
1015 <= XBUFFER (w
->buffer
)->save_modified
)))
1017 struct buffer
*prev
= current_buffer
;
1018 call1 (Vrun_hooks
, Qmenu_bar_update_hook
);
1019 current_buffer
= XBUFFER (w
->buffer
);
1020 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1021 current_buffer
= prev
;
1022 #ifdef USE_X_TOOLKIT
1023 set_frame_menubar (f
, 0);
1024 #endif /* USE_X_TOOLKIT */
1031 /* Redisplay WINDOW and its subwindows and siblings. */
1034 redisplay_windows (window
)
1037 for (; !NILP (window
); window
= XWINDOW (window
)->next
)
1038 redisplay_window (window
, 0);
1041 /* Redisplay window WINDOW and its subwindows. */
1044 redisplay_window (window
, just_this_one
)
1048 register struct window
*w
= XWINDOW (window
);
1049 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1051 register int lpoint
= PT
;
1052 struct buffer
*old
= current_buffer
;
1053 register int width
= window_internal_width (w
) - 1;
1054 register int startp
;
1055 register int hscroll
= XINT (w
->hscroll
);
1056 struct position pos
;
1059 int window_needs_modeline
;
1061 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1063 /* If this is a combination window, do its children; that's all. */
1065 if (!NILP (w
->vchild
))
1067 redisplay_windows (w
->vchild
);
1070 if (!NILP (w
->hchild
))
1072 redisplay_windows (w
->hchild
);
1075 if (NILP (w
->buffer
))
1078 height
= window_internal_height (w
);
1080 if (MINI_WINDOW_P (w
))
1082 if (w
== XWINDOW (minibuf_window
))
1084 if (echo_area_glyphs
)
1085 /* We've already displayed the echo area glyphs, if any. */
1086 goto finish_scroll_bars
;
1090 /* This is a minibuffer, but it's not the currently active one, so
1092 int vpos
= XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f
))->top
);
1095 for (i
= 0; i
< height
; i
++)
1097 get_display_line (f
, vpos
+ i
, 0);
1098 display_string (w
, vpos
+ i
, "", 0, 0, 0, 1, 0, width
);
1101 goto finish_scroll_bars
;
1105 if (update_mode_lines
)
1106 w
->update_mode_line
= Qt
;
1108 /* Otherwise set up data on this window; select its buffer and point value */
1110 current_buffer
= XBUFFER (w
->buffer
);
1113 /* Count number of windows showing the selected buffer. */
1116 && current_buffer
== XBUFFER (XWINDOW (selected_window
)->buffer
))
1119 /* POINT refers normally to the selected window.
1120 For any other window, set up appropriate value. */
1122 if (!EQ (window
, selected_window
))
1124 int new_pt
= marker_position (w
->pointm
);
1128 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1130 else if (new_pt
> (ZV
- 1))
1133 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1135 /* We don't use SET_PT so that the point-motion hooks don't run. */
1136 BUF_PT (current_buffer
) = new_pt
;
1139 /* If any of the character widths specified in the display table
1140 have changed, invalidate the width run cache. It's true that this
1141 may be a bit late to catch such changes, but the rest of
1142 redisplay goes (non-fatally) haywire when the display table is
1143 changed, so why should we worry about doing any better? */
1144 if (current_buffer
->width_run_cache
)
1146 struct Lisp_Vector
*disptab
= buffer_display_table ();
1148 if (! disptab_matches_widthtab (disptab
,
1149 XVECTOR (current_buffer
->width_table
)))
1151 invalidate_region_cache (current_buffer
,
1152 current_buffer
->width_run_cache
,
1154 recompute_width_table (current_buffer
, disptab
);
1158 /* If window-start is screwed up, choose a new one. */
1159 if (XMARKER (w
->start
)->buffer
!= current_buffer
)
1162 startp
= marker_position (w
->start
);
1164 /* Handle case where place to start displaying has been specified,
1165 unless the specified location is outside the accessible range. */
1166 if (!NILP (w
->force_start
))
1168 /* Forget any recorded base line for line number display. */
1169 w
->base_line_number
= Qnil
;
1170 w
->update_mode_line
= Qt
;
1171 w
->force_start
= Qnil
;
1172 XSETFASTINT (w
->last_modified
, 0);
1173 if (startp
< BEGV
) startp
= BEGV
;
1174 if (startp
> ZV
) startp
= ZV
;
1175 try_window (window
, startp
);
1176 if (cursor_vpos
< 0)
1178 /* If point does not appear, move point so it does appear */
1179 pos
= *compute_motion (startp
, 0,
1180 ((EQ (window
, minibuf_window
) && startp
== 1)
1181 ? minibuf_prompt_width
: 0)
1183 (hscroll
? 1 - hscroll
: 0),
1185 - (1 << (SHORTBITS
- 1)),
1186 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1187 BUF_PT (current_buffer
) = pos
.bufpos
;
1188 if (w
!= XWINDOW (selected_window
))
1189 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
1192 if (current_buffer
== old
)
1194 FRAME_CURSOR_X (f
) = max (0, pos
.hpos
) + XFASTINT (w
->left
);
1195 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1197 /* If we are highlighting the region,
1198 then we just changed the region, so redisplay to show it. */
1199 if (!NILP (Vtransient_mark_mode
)
1200 && !NILP (current_buffer
->mark_active
))
1202 cancel_my_columns (XWINDOW (window
));
1203 try_window (window
, startp
);
1209 /* Handle case where text has not changed, only point,
1210 and it has not moved off the frame */
1212 /* This code is not used for minibuffer for the sake of
1213 the case of redisplaying to replace an echo area message;
1214 since in that case the minibuffer contents per se are usually unchanged.
1215 This code is of no real use in the minibuffer since
1216 the handling of this_line_bufpos, etc.,
1217 in redisplay handles the same cases. */
1219 if (XFASTINT (w
->last_modified
) >= MODIFF
1220 && PT
>= startp
&& !clip_changed
1221 && (just_this_one
|| XFASTINT (w
->width
) == FRAME_WIDTH (f
))
1222 /* Can't use this case if highlighting a region. */
1223 && !(!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1224 && NILP (w
->region_showing
)
1225 /* If end pos is out of date, scroll bar and percentage will be wrong */
1226 && INTEGERP (w
->window_end_vpos
)
1227 && XFASTINT (w
->window_end_vpos
) < XFASTINT (w
->height
)
1228 && !EQ (window
, minibuf_window
))
1230 pos
= *compute_motion (startp
, 0, (hscroll
? 1 - hscroll
: 0),
1231 PT
, height
+ 1, 10000, width
, hscroll
,
1232 pos_tab_offset (w
, startp
), w
);
1234 if (pos
.vpos
< height
)
1236 /* Ok, point is still on frame */
1237 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
1239 /* These variables are supposed to be origin 1 */
1240 FRAME_CURSOR_X (f
) = max (0, pos
.hpos
) + XFASTINT (w
->left
);
1241 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1243 /* This doesn't do the trick, because if a window to the right of
1244 this one must be redisplayed, this does nothing because there
1245 is nothing in DesiredFrame yet, and then the other window is
1246 redisplayed, making likes that are empty in this window's columns.
1247 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1248 preserve_my_columns (w);
1252 /* Don't bother trying redisplay with same start;
1253 we already know it will lose */
1255 /* If current starting point was originally the beginning of a line
1256 but no longer is, find a new starting point. */
1257 else if (!NILP (w
->start_at_line_beg
)
1259 || FETCH_CHAR (startp
- 1) == '\n'))
1263 else if (just_this_one
&& !MINI_WINDOW_P (w
)
1265 && XFASTINT (w
->last_modified
)
1266 /* or else vmotion on first line won't work. */
1267 && ! NILP (w
->start_at_line_beg
)
1268 && ! EQ (w
->window_end_valid
, Qnil
)
1269 && do_id
&& !clip_changed
1270 && !blank_end_of_window
1271 && XFASTINT (w
->width
) == FRAME_WIDTH (f
)
1272 /* Can't use this case if highlighting a region. */
1273 && !(!NILP (Vtransient_mark_mode
)
1274 && !NILP (current_buffer
->mark_active
))
1275 && NILP (w
->region_showing
)
1276 && EQ (last_arrow_position
, Voverlay_arrow_position
)
1277 && EQ (last_arrow_string
, Voverlay_arrow_string
)
1278 && (tem
= try_window_id (FRAME_SELECTED_WINDOW (f
)))
1281 /* tem > 0 means success. tem == -1 means choose new start.
1282 tem == -2 means try again with same start,
1283 and nothing but whitespace follows the changed stuff.
1284 tem == 0 means try again with same start. */
1288 else if (startp
>= BEGV
&& startp
<= ZV
1289 /* Avoid starting display at end of buffer! */
1290 && (startp
< ZV
|| startp
== BEGV
1291 || (XFASTINT (w
->last_modified
) >= MODIFF
)))
1293 /* Try to redisplay starting at same place as before */
1294 /* If point has not moved off frame, accept the results */
1295 try_window (window
, startp
);
1296 if (cursor_vpos
>= 0)
1298 if (!just_this_one
|| clip_changed
|| beg_unchanged
< startp
)
1299 /* Forget any recorded base line for line number display. */
1300 w
->base_line_number
= Qnil
;
1304 cancel_my_columns (w
);
1307 XSETFASTINT (w
->last_modified
, 0);
1308 w
->update_mode_line
= Qt
;
1310 /* Try to scroll by specified few lines */
1312 if (scroll_step
&& !clip_changed
)
1316 pos
= *vmotion (Z
- XFASTINT (w
->window_end_pos
),
1317 scroll_step
, width
, hscroll
, window
);
1318 if (pos
.vpos
>= height
)
1322 pos
= *vmotion (startp
, PT
< startp
? - scroll_step
: scroll_step
,
1323 width
, hscroll
, window
);
1325 if (PT
>= pos
.bufpos
)
1327 try_window (window
, pos
.bufpos
);
1328 if (cursor_vpos
>= 0)
1330 if (!just_this_one
|| clip_changed
|| beg_unchanged
< startp
)
1331 /* Forget any recorded base line for line number display. */
1332 w
->base_line_number
= Qnil
;
1336 cancel_my_columns (w
);
1341 /* Finally, just choose place to start which centers point */
1344 /* Forget any previously recorded base line for line number display. */
1345 w
->base_line_number
= Qnil
;
1347 pos
= *vmotion (PT
, - (height
/ 2), width
, hscroll
, window
);
1348 try_window (window
, pos
.bufpos
);
1350 startp
= marker_position (w
->start
);
1351 w
->start_at_line_beg
1352 = (startp
== BEGV
|| FETCH_CHAR (startp
- 1) == '\n') ? Qt
: Qnil
;
1355 if ((!NILP (w
->update_mode_line
)
1356 /* If window not full width, must redo its mode line
1357 if the window to its side is being redone */
1358 || (!just_this_one
&& width
< FRAME_WIDTH (f
) - 1)
1359 || INTEGERP (w
->base_line_pos
))
1360 && height
!= XFASTINT (w
->height
))
1361 display_mode_line (w
);
1362 if (! line_number_displayed
1363 && ! BUFFERP (w
->base_line_pos
))
1365 w
->base_line_pos
= Qnil
;
1366 w
->base_line_number
= Qnil
;
1369 /* When we reach a frame's selected window, redo the frame's menu bar. */
1370 if (!NILP (w
->update_mode_line
)
1371 #ifdef USE_X_TOOLKIT
1372 && FRAME_EXTERNAL_MENU_BAR (f
)
1374 && FRAME_MENU_BAR_LINES (f
) > 0
1376 && EQ (FRAME_SELECTED_WINDOW (f
), window
))
1377 display_menu_bar (w
);
1380 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1382 int start
, end
, whole
;
1384 /* Calculate the start and end positions for the current window.
1385 At some point, it would be nice to choose between scrollbars
1386 which reflect the whole buffer size, with special markers
1387 indicating narrowing, and scrollbars which reflect only the
1390 Note that minibuffers sometimes aren't displaying any text. */
1391 if (! MINI_WINDOW_P (w
)
1392 || (w
== XWINDOW (minibuf_window
) && ! echo_area_glyphs
))
1395 start
= startp
- BEGV
;
1396 /* I don't think this is guaranteed to be right. For the
1397 moment, we'll pretend it is. */
1398 end
= (Z
- XINT (w
->window_end_pos
)) - BEGV
;
1400 if (end
< start
) end
= start
;
1401 if (whole
< (end
- start
)) whole
= end
- start
;
1404 start
= end
= whole
= 0;
1406 /* Indicate what this scroll bar ought to be displaying now. */
1407 (*set_vertical_scroll_bar_hook
) (w
, end
- start
, whole
, start
);
1409 /* Note that we actually used the scroll bar attached to this window,
1410 so it shouldn't be deleted at the end of redisplay. */
1411 (*redeem_scroll_bar_hook
) (w
);
1414 BUF_PT (current_buffer
) = opoint
;
1415 current_buffer
= old
;
1416 BUF_PT (current_buffer
) = lpoint
;
1419 /* Do full redisplay on one window, starting at position `pos'. */
1422 try_window (window
, pos
)
1426 register struct window
*w
= XWINDOW (window
);
1427 register int height
= window_internal_height (w
);
1428 register int vpos
= XFASTINT (w
->top
);
1429 register int last_text_vpos
= vpos
;
1430 int tab_offset
= pos_tab_offset (w
, pos
);
1431 FRAME_PTR f
= XFRAME (w
->frame
);
1432 int width
= window_internal_width (w
) - 1;
1433 struct position val
;
1435 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1437 overlay_arrow_seen
= 0;
1438 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
1440 while (--height
>= 0)
1442 val
= *display_text_line (w
, pos
, vpos
, val
.hpos
, tab_offset
);
1443 tab_offset
+= width
;
1444 if (val
.vpos
) tab_offset
= 0;
1446 if (pos
!= val
.bufpos
)
1448 /* Next line, unless prev line ended in end of buffer with no cr */
1449 = vpos
- (val
.vpos
&& (FETCH_CHAR (val
.bufpos
- 1) != '\n'
1450 #ifdef USE_TEXT_PROPERTIES
1451 || ! NILP (Fget_char_property (val
.bufpos
-1,
1459 /* If last line is continued in middle of character,
1460 include the split character in the text considered on the frame */
1461 if (val
.hpos
< (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
1464 /* If bottom just moved off end of frame, change mode line percentage. */
1465 if (XFASTINT (w
->window_end_pos
) == 0
1467 w
->update_mode_line
= Qt
;
1469 /* Say where last char on frame will be, once redisplay is finished. */
1470 XSETFASTINT (w
->window_end_pos
, Z
- pos
);
1471 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
- XFASTINT (w
->top
));
1472 /* But that is not valid info until redisplay finishes. */
1473 w
->window_end_valid
= Qnil
;
1476 /* Try to redisplay when buffer is modified locally,
1477 computing insert/delete line to preserve text outside
1478 the bounds of the changes.
1479 Return 1 if successful, 0 if if cannot tell what to do,
1480 or -1 to tell caller to find a new window start,
1481 or -2 to tell caller to do normal redisplay with same window start. */
1484 try_window_id (window
)
1488 register struct window
*w
= XWINDOW (window
);
1489 register int height
= window_internal_height (w
);
1490 FRAME_PTR f
= XFRAME (w
->frame
);
1491 int top
= XFASTINT (w
->top
);
1492 int start
= marker_position (w
->start
);
1493 int width
= window_internal_width (w
) - 1;
1494 int hscroll
= XINT (w
->hscroll
);
1495 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1497 register int i
, tem
;
1498 int last_text_vpos
= 0;
1500 int selective
= (INTEGERP (current_buffer
->selective_display
)
1501 ? XINT (current_buffer
->selective_display
)
1502 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1504 struct position val
, bp
, ep
, xp
, pp
;
1505 int scroll_amount
= 0;
1507 int tab_offset
, epto
;
1509 if (GPT
- BEG
< beg_unchanged
)
1510 beg_unchanged
= GPT
- BEG
;
1511 if (Z
- GPT
< end_unchanged
)
1512 end_unchanged
= Z
- GPT
;
1514 if (beg_unchanged
+ BEG
< start
)
1515 return 0; /* Give up if changes go above top of window */
1517 /* Find position before which nothing is changed. */
1518 bp
= *compute_motion (start
, 0, lmargin
,
1519 min (ZV
, beg_unchanged
+ BEG
), height
+ 1, 0,
1520 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1521 if (bp
.vpos
>= height
)
1523 if (PT
< bp
.bufpos
&& !bp
.contin
)
1525 /* All changes are below the frame, and point is on the frame.
1526 We don't need to change the frame at all.
1527 But we need to update window_end_pos to account for
1528 any change in buffer size. */
1529 bp
= *compute_motion (start
, 0, lmargin
,
1531 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1532 XSETFASTINT (w
->window_end_vpos
, height
);
1533 XSETFASTINT (w
->window_end_pos
, Z
- bp
.bufpos
);
1541 /* Find beginning of that frame line. Must display from there. */
1542 bp
= *vmotion (bp
.bufpos
, 0, width
, hscroll
, window
);
1549 /* If about to start displaying at the beginning of a continuation line,
1550 really start with previous frame line, in case it was not
1551 continued when last redisplayed */
1552 if ((bp
.contin
&& bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0)
1554 /* Likewise if we have to worry about selective display. */
1555 (selective
> 0 && bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0))
1557 bp
= *vmotion (bp
.bufpos
, -1, width
, hscroll
, window
);
1562 if (bp
.contin
&& bp
.hpos
!= lmargin
)
1564 val
.hpos
= bp
.prevhpos
- width
+ lmargin
;
1570 /* Find first visible newline after which no more is changed. */
1571 tem
= find_next_newline (Z
- max (end_unchanged
, Z
- ZV
), 1);
1573 while (tem
< ZV
- 1 && (indented_beyond_p (tem
, selective
)))
1574 tem
= find_next_newline (tem
, 1);
1576 /* Compute the cursor position after that newline. */
1577 ep
= *compute_motion (pos
, vpos
, val
.hpos
, tem
,
1578 height
, - (1 << (SHORTBITS
- 1)),
1579 width
, hscroll
, pos_tab_offset (w
, bp
.bufpos
), w
);
1581 /* If changes reach past the text available on the frame,
1582 just display rest of frame. */
1583 if (ep
.bufpos
> Z
- XFASTINT (w
->window_end_pos
))
1586 stop_vpos
= ep
.vpos
;
1588 /* If no newline before ep, the line ep is on includes some changes
1589 that must be displayed. Make sure we don't stop before it. */
1590 /* Also, if changes reach all the way until ep.bufpos,
1591 it is possible that something was deleted after the
1592 newline before it, so the following line must be redrawn. */
1593 if (stop_vpos
== ep
.vpos
1594 && (ep
.bufpos
== BEGV
1595 || FETCH_CHAR (ep
.bufpos
- 1) != '\n'
1596 || ep
.bufpos
== Z
- end_unchanged
))
1597 stop_vpos
= ep
.vpos
+ 1;
1600 overlay_arrow_seen
= 0;
1602 /* If changes do not reach to bottom of window,
1603 figure out how much to scroll the rest of the window */
1604 if (stop_vpos
< height
)
1606 /* Now determine how far up or down the rest of the window has moved */
1607 epto
= pos_tab_offset (w
, ep
.bufpos
);
1608 xp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
,
1609 Z
- XFASTINT (w
->window_end_pos
),
1610 10000, 0, width
, hscroll
, epto
, w
);
1611 scroll_amount
= xp
.vpos
- XFASTINT (w
->window_end_vpos
);
1613 /* Is everything on frame below the changes whitespace?
1614 If so, no scrolling is really necessary. */
1615 for (i
= ep
.bufpos
; i
< xp
.bufpos
; i
++)
1617 tem
= FETCH_CHAR (i
);
1618 if (tem
!= ' ' && tem
!= '\n' && tem
!= '\t')
1624 XSETFASTINT (w
->window_end_vpos
,
1625 XFASTINT (w
->window_end_vpos
) + scroll_amount
);
1627 /* Before doing any scrolling, verify that point will be on frame. */
1628 if (PT
> ep
.bufpos
&& !(PT
<= xp
.bufpos
&& xp
.bufpos
< height
))
1630 if (PT
<= xp
.bufpos
)
1632 pp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
,
1633 PT
, height
, - (1 << (SHORTBITS
- 1)),
1634 width
, hscroll
, epto
, w
);
1638 pp
= *compute_motion (xp
.bufpos
, xp
.vpos
, xp
.hpos
,
1639 PT
, height
, - (1 << (SHORTBITS
- 1)),
1641 pos_tab_offset (w
, xp
.bufpos
), w
);
1643 if (pp
.bufpos
< PT
|| pp
.vpos
== height
)
1645 cursor_vpos
= pp
.vpos
+ top
;
1646 cursor_hpos
= pp
.hpos
+ XFASTINT (w
->left
);
1649 if (stop_vpos
- scroll_amount
>= height
1650 || ep
.bufpos
== xp
.bufpos
)
1652 if (scroll_amount
< 0)
1653 stop_vpos
-= scroll_amount
;
1655 /* In this path, we have altered window_end_vpos
1656 and not left it negative.
1657 We must make sure that, in case display is preempted
1658 before the frame changes to reflect what we do here,
1659 further updates will not come to try_window_id
1660 and assume the frame and window_end_vpos match. */
1661 blank_end_of_window
= 1;
1663 else if (!scroll_amount
)
1665 /* Even if we don't need to scroll, we must adjust the
1666 charstarts of subsequent lines (that we won't redisplay)
1667 according to the amount of text inserted or deleted. */
1668 int oldpos
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
1669 int adjust
= ep
.bufpos
- oldpos
;
1670 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1, adjust
);
1672 else if (bp
.bufpos
== Z
- end_unchanged
)
1674 /* If reprinting everything is nearly as fast as scrolling,
1675 don't bother scrolling. Can happen if lines are short. */
1676 if (scroll_cost (f
, bp
.vpos
+ top
- scroll_amount
,
1677 top
+ height
- max (0, scroll_amount
),
1679 > xp
.bufpos
- bp
.bufpos
- 20)
1680 /* Return "try normal display with same window-start."
1681 Too bad we can't prevent further scroll-thinking. */
1683 /* If pure deletion, scroll up as many lines as possible.
1684 In common case of killing a line, this can save the
1685 following line from being overwritten by scrolling
1686 and therefore having to be redrawn. */
1687 tem
= scroll_frame_lines (f
, bp
.vpos
+ top
- scroll_amount
,
1688 top
+ height
- max (0, scroll_amount
),
1689 scroll_amount
, bp
.bufpos
);
1694 /* scroll_frame_lines did not properly adjust subsequent
1695 lines' charstarts in the case where the text of the
1696 screen line at bp.vpos has changed.
1697 (This can happen in a deletion that ends in mid-line.)
1698 To adjust properly, we need to make things constent at
1700 So do a second adjust to make that happen.
1701 Note that stop_vpos >= ep.vpos, so it is sufficient
1702 to update the charstarts for lines at ep.vpos and below. */
1704 = FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
1705 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1,
1706 ep
.bufpos
- oldstart
);
1709 else if (scroll_amount
)
1711 /* If reprinting everything is nearly as fast as scrolling,
1712 don't bother scrolling. Can happen if lines are short. */
1713 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
1714 overestimate of cost of reprinting, since xp.bufpos
1715 would end up below the bottom of the window. */
1716 if (scroll_cost (f
, ep
.vpos
+ top
- scroll_amount
,
1717 top
+ height
- max (0, scroll_amount
),
1719 > xp
.bufpos
- ep
.bufpos
- 20)
1720 /* Return "try normal display with same window-start."
1721 Too bad we can't prevent further scroll-thinking. */
1723 tem
= scroll_frame_lines (f
, ep
.vpos
+ top
- scroll_amount
,
1724 top
+ height
- max (0, scroll_amount
),
1725 scroll_amount
, ep
.bufpos
);
1726 if (!tem
) stop_vpos
= height
;
1730 /* In any case, do not display past bottom of window */
1731 if (stop_vpos
>= height
)
1737 /* Handle case where pos is before w->start --
1738 can happen if part of line had been clipped and is not clipped now */
1739 if (vpos
== 0 && pos
< marker_position (w
->start
))
1740 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1742 /* Redisplay the lines where the text was changed */
1743 last_text_vpos
= vpos
;
1744 tab_offset
= pos_tab_offset (w
, pos
);
1745 /* If we are starting display in mid-character, correct tab_offset
1746 to account for passing the line that that character really starts in. */
1747 if (val
.hpos
< lmargin
)
1748 tab_offset
+= width
;
1749 while (vpos
< stop_vpos
)
1751 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
1752 tab_offset
+= width
;
1753 if (val
.vpos
) tab_offset
= 0;
1754 if (pos
!= val
.bufpos
)
1756 /* Next line, unless prev line ended in end of buffer with no cr */
1757 = vpos
- (val
.vpos
&& FETCH_CHAR (val
.bufpos
- 1) != '\n');
1761 /* There are two cases:
1762 1) we have displayed down to the bottom of the window
1763 2) we have scrolled lines below stop_vpos by scroll_amount */
1767 /* If last line is continued in middle of character,
1768 include the split character in the text considered on the frame */
1769 if (val
.hpos
< lmargin
)
1771 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
);
1772 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
1775 /* If scrolling made blank lines at window bottom,
1776 redisplay to fill those lines */
1777 if (scroll_amount
< 0)
1779 /* Don't consider these lines for general-purpose scrolling.
1780 That will save time in the scrolling computation. */
1781 FRAME_SCROLL_BOTTOM_VPOS (f
) = xp
.vpos
;
1786 vpos
= height
+ scroll_amount
;
1787 else if (xp
.contin
&& xp
.hpos
!= lmargin
)
1789 val
.hpos
= xp
.prevhpos
- width
+ lmargin
;
1793 blank_end_of_window
= 1;
1794 tab_offset
= pos_tab_offset (w
, pos
);
1795 /* If we are starting display in mid-character, correct tab_offset
1796 to account for passing the line that that character starts in. */
1797 if (val
.hpos
< lmargin
)
1798 tab_offset
+= width
;
1800 while (vpos
< height
)
1802 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
1803 tab_offset
+= width
;
1804 if (val
.vpos
) tab_offset
= 0;
1808 /* Here is a case where display_text_line sets cursor_vpos wrong.
1809 Make it be fixed up, below. */
1815 /* If bottom just moved off end of frame, change mode line percentage. */
1816 if (XFASTINT (w
->window_end_pos
) == 0
1818 w
->update_mode_line
= Qt
;
1820 /* Attempt to adjust end-of-text positions to new bottom line */
1823 delta
= height
- xp
.vpos
;
1825 || (delta
> 0 && xp
.bufpos
<= ZV
)
1826 || (delta
== 0 && xp
.hpos
))
1828 val
= *vmotion (Z
- XFASTINT (w
->window_end_pos
),
1829 delta
, width
, hscroll
, window
);
1830 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
1831 XSETFASTINT (w
->window_end_vpos
,
1832 XFASTINT (w
->window_end_vpos
) + val
.vpos
);
1836 w
->window_end_valid
= Qnil
;
1838 /* If point was not in a line that was displayed, find it */
1839 if (cursor_vpos
< 0)
1841 val
= *compute_motion (start
, 0, lmargin
, PT
, 10000, 10000,
1842 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1843 /* Admit failure if point is off frame now */
1844 if (val
.vpos
>= height
)
1846 for (vpos
= 0; vpos
< height
; vpos
++)
1847 cancel_line (vpos
+ top
, f
);
1850 cursor_vpos
= val
.vpos
+ top
;
1851 cursor_hpos
= val
.hpos
+ XFASTINT (w
->left
);
1854 FRAME_CURSOR_X (f
) = max (0, cursor_hpos
);
1855 FRAME_CURSOR_Y (f
) = cursor_vpos
;
1859 val
= *compute_motion (start
, 0, lmargin
, ZV
,
1860 height
, - (1 << (SHORTBITS
- 1)),
1861 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1862 if (val
.vpos
!= XFASTINT (w
->window_end_vpos
))
1864 if (XFASTINT (w
->window_end_pos
)
1872 /* Mark a section of BUF as modified, but only for the sake of redisplay.
1873 This is useful for recording changes to overlays.
1875 We increment the buffer's modification timestamp and set the
1876 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
1877 as if the region of text between START and END had been modified;
1878 the redisplay code will check this against the windows' timestamps,
1879 and redraw the appropriate area of the buffer.
1881 However, if the buffer is unmodified, we bump the last-save
1882 timestamp as well, so that incrementing the timestamp doesn't fool
1883 Emacs into thinking that the buffer's text has been modified.
1885 Tweaking the timestamps shouldn't hurt the first-modification
1886 timestamps recorded in the undo records; those values aren't
1887 written until just before a real text modification is made, so they
1888 will never catch the timestamp value just before this function gets
1892 redisplay_region (buf
, start
, end
)
1902 start
= end
; end
= temp
;
1905 /* If this is a buffer not in the selected window,
1906 we must do other windows. */
1907 if (buf
!= XBUFFER (XWINDOW (selected_window
)->buffer
))
1908 windows_or_buffers_changed
= 1;
1909 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
1910 else if (buf
!= current_buffer
)
1911 windows_or_buffers_changed
= 1;
1912 /* If multiple windows show this buffer, we must do other windows. */
1913 else if (buffer_shared
> 1)
1914 windows_or_buffers_changed
= 1;
1917 if (unchanged_modified
== MODIFF
)
1919 beg_unchanged
= start
- BEG
;
1920 end_unchanged
= Z
- end
;
1924 if (Z
- end
< end_unchanged
)
1925 end_unchanged
= Z
- end
;
1926 if (start
- BEG
< beg_unchanged
)
1927 beg_unchanged
= start
- BEG
;
1931 /* Increment the buffer's time stamp, but also increment the save
1932 and autosave timestamps, so as not to screw up that timekeeping. */
1933 if (BUF_MODIFF (buf
) == buf
->save_modified
)
1934 buf
->save_modified
++;
1935 if (BUF_MODIFF (buf
) == buf
->auto_save_modified
)
1936 buf
->auto_save_modified
++;
1938 BUF_MODIFF (buf
) ++;
1942 /* Copy LEN glyphs starting address FROM to the rope TO.
1943 But don't actually copy the parts that would come in before S.
1944 Value is TO, advanced past the copied data.
1945 F is the frame we are displaying in. */
1948 copy_part_of_rope (f
, to
, s
, from
, len
, face
)
1950 register GLYPH
*to
; /* Copy to here. */
1951 register GLYPH
*s
; /* Starting point. */
1952 Lisp_Object
*from
; /* Data to copy. */
1954 int face
; /* Face to apply to glyphs which don't specify one. */
1957 register Lisp_Object
*fp
= from
;
1958 /* These cache the results of the last call to compute_glyph_face. */
1960 int last_merged
= 0;
1963 if (! FRAME_TERMCAP_P (f
))
1966 int glyph
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
1969 if (FAST_GLYPH_FACE (glyph
) == 0)
1970 /* If GLYPH has no face code, use FACE. */
1972 else if (FAST_GLYPH_FACE (glyph
) == last_code
)
1973 /* If it's same as previous glyph, use same result. */
1974 facecode
= last_merged
;
1977 /* Merge this glyph's face and remember the result. */
1978 last_code
= FAST_GLYPH_FACE (glyph
);
1979 last_merged
= facecode
= compute_glyph_face (f
, last_code
, face
);
1983 *to
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), facecode
);
1991 if (to
>= s
) *to
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
1998 /* Correct a glyph by replacing its specified user-level face code
1999 with a displayable computed face code. */
2002 fix_glyph (f
, glyph
, cface
)
2008 if (! FRAME_TERMCAP_P (f
))
2010 if (FAST_GLYPH_FACE (glyph
) != 0)
2011 cface
= compute_glyph_face (f
, FAST_GLYPH_FACE (glyph
), cface
);
2012 glyph
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), cface
);
2018 /* Display one line of window W, starting at position START in W's buffer.
2020 Display starting at horizontal position HPOS, expressed relative to
2021 W's left edge. In situations where the text at START shouldn't
2022 start at the left margin (i.e. when the window is hscrolled, or
2023 we're continuing a line which left off in the midst of a
2024 multi-column character), HPOS should be negative; we throw away
2025 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2028 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2030 Display on position VPOS on the frame. It is origin 0, relative to
2031 the top of the frame, not W.
2033 Returns a STRUCT POSITION giving character to start next line with
2034 and where to display it, including a zero or negative hpos.
2035 The vpos field is not really a vpos; it is 1 unless the line is continued */
2037 struct position val_display_text_line
;
2039 static struct position
*
2040 display_text_line (w
, start
, vpos
, hpos
, taboffset
)
2047 register int pos
= start
;
2052 register unsigned char *p
;
2054 register GLYPH
*leftmargin
;
2055 register GLYPH
*p1prev
= 0;
2056 register GLYPH
*p1start
;
2058 FRAME_PTR f
= XFRAME (w
->frame
);
2059 int tab_width
= XINT (current_buffer
->tab_width
);
2060 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
2061 int width
= window_internal_width (w
) - 1;
2062 struct position val
;
2065 int hscroll
= XINT (w
->hscroll
);
2066 int truncate
= (hscroll
2067 || (truncate_partial_width_windows
2068 && XFASTINT (w
->width
) < FRAME_WIDTH (f
))
2069 || !NILP (current_buffer
->truncate_lines
));
2071 /* 1 if we should highlight the region. */
2072 int highlight_region
2073 = !NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
);
2074 int region_beg
, region_end
;
2076 int selective
= (INTEGERP (current_buffer
->selective_display
)
2077 ? XINT (current_buffer
->selective_display
)
2078 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2079 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
2080 register struct Lisp_Vector
*dp
= window_display_table (w
);
2082 Lisp_Object default_invis_vector
[3];
2083 /* Nonzero means display something where there are invisible lines.
2084 The precise value is the number of glyphs to display. */
2086 = (selective
&& dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2087 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
2088 : selective
&& !NILP (current_buffer
->selective_display_ellipses
)
2090 /* This is the sequence of Lisp objects to display
2091 when there are invisible lines. */
2092 Lisp_Object
*invis_vector_contents
2093 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2094 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->contents
2095 : default_invis_vector
);
2097 GLYPH truncator
= (dp
== 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp
))
2098 ? '$' : XINT (DISP_TRUNC_GLYPH (dp
)));
2099 GLYPH continuer
= (dp
== 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp
))
2100 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp
)));
2102 /* The next buffer location at which the face should change, due
2103 to overlays or text property changes. */
2104 int next_face_change
;
2106 #ifdef USE_TEXT_PROPERTIES
2107 /* The next location where the `invisible' property changes */
2111 /* The face we're currently using. */
2112 int current_face
= 0;
2115 XSETFASTINT (default_invis_vector
[2], '.');
2116 default_invis_vector
[0] = default_invis_vector
[1] = default_invis_vector
[2];
2118 hpos
+= XFASTINT (w
->left
);
2119 get_display_line (f
, vpos
, XFASTINT (w
->left
));
2120 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
2122 /* Show where to highlight the region. */
2123 if (highlight_region
&& XMARKER (current_buffer
->mark
)->buffer
!= 0
2124 /* Maybe highlight only in selected window. */
2125 && (highlight_nonselected_windows
2126 || w
== XWINDOW (selected_window
)))
2128 region_beg
= marker_position (current_buffer
->mark
);
2129 if (PT
< region_beg
)
2131 region_end
= region_beg
;
2136 w
->region_showing
= Qt
;
2139 region_beg
= region_end
= -1;
2141 if (MINI_WINDOW_P (w
)
2143 && vpos
== XFASTINT (w
->top
))
2145 if (! NILP (minibuf_prompt
))
2147 minibuf_prompt_width
2148 = (display_string (w
, vpos
, XSTRING (minibuf_prompt
)->data
,
2149 XSTRING (minibuf_prompt
)->size
, hpos
,
2150 (!truncate
? continuer
: truncator
),
2153 hpos
+= minibuf_prompt_width
;
2156 minibuf_prompt_width
= 0;
2161 /* If we're hscrolled at all, use compute_motion to skip over any
2162 text off the left edge of the window. compute_motion may know
2163 tricks to do this faster than we can. */
2166 struct position
*left_edge
2167 = compute_motion (pos
, vpos
, hpos
,
2169 width
, hscroll
, taboffset
, w
);
2171 /* Retrieve the buffer position and column provided by
2172 compute_motion. We can't assume that the column will be
2173 zero, because you may have multi-column characters crossing
2176 compute_motion may have moved us past the screen position we
2177 requested, if we hit a multi-column character, or the end of
2178 the line. If so, back up. */
2179 if (left_edge
->vpos
> vpos
2180 || left_edge
->hpos
> 0)
2182 pos
= left_edge
->bufpos
- 1;
2183 hpos
= left_edge
->prevhpos
;
2187 pos
= left_edge
->bufpos
;
2188 hpos
= left_edge
->hpos
;
2192 desired_glyphs
->bufp
[vpos
] = start
;
2193 p1
= desired_glyphs
->glyphs
[vpos
] + hpos
;
2195 charstart
= desired_glyphs
->charstarts
[vpos
] + hpos
;
2196 /* In case we don't ever write anything into it... */
2197 desired_glyphs
->charstarts
[vpos
][XFASTINT (w
->left
)] = -1;
2198 leftmargin
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
2199 endp
= leftmargin
+ width
;
2201 /* Arrange the overlays nicely for our purposes. Usually, we call
2202 display_text_line on only one line at a time, in which case this
2203 can't really hurt too much, or we call it on lines which appear
2204 one after another in the buffer, in which case all calls to
2205 recenter_overlay_lists but the first will be pretty cheap. */
2206 recenter_overlay_lists (current_buffer
, pos
);
2208 /* Loop generating characters.
2209 Stop at end of buffer, before newline,
2210 if reach or pass continuation column,
2211 or at face change. */
2213 next_face_change
= pos
;
2214 #ifdef USE_TEXT_PROPERTIES
2215 next_invisible
= pos
;
2219 /* Record which glyph starts a character,
2220 and the character position of that character. */
2221 if (p1
>= leftmargin
)
2222 charstart
[p1
- p1start
] = pos
;
2230 /* Did we hit the end of the visible region of the buffer?
2235 /* Did we reach point? Record the cursor location. */
2236 if (pos
== PT
&& cursor_vpos
< 0)
2239 cursor_hpos
= p1
- leftmargin
;
2242 #ifdef USE_TEXT_PROPERTIES
2243 /* if the `invisible' property is set to t, we can skip to
2244 the next property change */
2245 while (pos
== next_invisible
&& pos
< end
)
2247 Lisp_Object position
, limit
, endpos
, prop
, ww
;
2248 XSETFASTINT (position
, pos
);
2250 prop
= Fget_char_property (position
, Qinvisible
, ww
);
2251 /* This is just an estimate to give reasonable
2252 performance; nothing should go wrong if it is too small. */
2253 limit
= Fnext_overlay_change (position
);
2254 if (XFASTINT (limit
) > pos
+ 50)
2255 XSETFASTINT (limit
, pos
+ 50);
2256 endpos
= Fnext_single_property_change (position
, Qinvisible
,
2257 Fcurrent_buffer (), limit
);
2258 if (INTEGERP (endpos
))
2259 next_invisible
= XINT (endpos
);
2261 next_invisible
= end
;
2264 if (pos
< PT
&& next_invisible
>= PT
)
2267 cursor_hpos
= p1
- leftmargin
;
2269 pos
= next_invisible
;
2277 /* Did we hit a face change? Figure out what face we should
2278 use now. We also hit this the first time through the
2279 loop, to see what face we should start with. */
2280 if (pos
>= next_face_change
&& FRAME_X_P (f
))
2281 current_face
= compute_char_face (f
, w
, pos
,
2282 region_beg
, region_end
,
2283 &next_face_change
, pos
+ 50, 0);
2288 #ifdef USE_TEXT_PROPERTIES
2289 if (pos
< next_invisible
&& next_invisible
< pause
)
2290 pause
= next_invisible
;
2292 if (pos
< next_face_change
&& next_face_change
< pause
)
2293 pause
= next_face_change
;
2295 /* Wouldn't you hate to read the next line to someone over
2297 if (pos
< PT
&& PT
< pause
)
2299 if (pos
< GPT
&& GPT
< pause
)
2302 p
= &FETCH_CHAR (pos
);
2305 if (c
>= 040 && c
< 0177
2306 && (dp
== 0 || !VECTORP (DISP_CHAR_VECTOR (dp
, c
))))
2308 if (p1
>= leftmargin
)
2309 *p1
= MAKE_GLYPH (f
, c
, current_face
);
2315 while (pos
+ 1 < end
2317 && indented_beyond_p (pos
+ 1, selective
))
2320 pos
= find_next_newline (pos
+ 1, 1);
2321 if (FETCH_CHAR (pos
- 1) == '\n')
2324 if (invis
&& selective_rlen
> 0 && p1
>= leftmargin
)
2326 p1
+= selective_rlen
;
2327 if (p1
- leftmargin
> width
)
2329 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2330 (p1
- p1prev
), current_face
);
2333 /* Draw the face of the newline character as extending all the
2334 way to the end of the frame line. */
2337 if (p1
< leftmargin
)
2340 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2349 if (p1
>= leftmargin
&& p1
< endp
)
2350 *p1
= MAKE_GLYPH (f
, ' ', current_face
);
2353 while ((p1
- leftmargin
+ taboffset
+ hscroll
- (hscroll
> 0))
2356 else if (c
== Ctl ('M') && selective
== -1)
2358 pos
= find_next_newline (pos
, 1);
2359 if (FETCH_CHAR (pos
- 1) == '\n')
2361 if (selective_rlen
> 0)
2363 p1
+= selective_rlen
;
2364 if (p1
- leftmargin
> width
)
2366 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2367 (p1
- p1prev
), current_face
);
2370 /* Draw the face of the newline character as extending all the
2371 way to the end of the frame line. */
2374 if (p1
< leftmargin
)
2377 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2382 else if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
2384 p1
= copy_part_of_rope (f
, p1
, leftmargin
,
2385 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
2386 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
2389 else if (c
< 0200 && ctl_arrow
)
2391 if (p1
>= leftmargin
)
2392 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
2393 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
2396 if (p1
>= leftmargin
&& p1
< endp
)
2397 *p1
= MAKE_GLYPH (f
, c
^ 0100, current_face
);
2402 if (p1
>= leftmargin
)
2403 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
2404 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
2407 if (p1
>= leftmargin
&& p1
< endp
)
2408 *p1
= MAKE_GLYPH (f
, (c
>> 6) + '0', current_face
);
2410 if (p1
>= leftmargin
&& p1
< endp
)
2411 *p1
= MAKE_GLYPH (f
, (7 & (c
>> 3)) + '0', current_face
);
2413 if (p1
>= leftmargin
&& p1
< endp
)
2414 *p1
= MAKE_GLYPH (f
, (7 & c
) + '0', current_face
);
2418 /* Do nothing here for a char that's entirely off the left edge. */
2419 if (p1
>= leftmargin
)
2421 /* For all the glyphs occupied by this character, except for the
2422 first, store -1 in charstarts. */
2425 int *p2x
= &charstart
[p1prev
- p1start
];
2426 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2428 /* The window's left column should always
2429 contain a character position.
2430 And don't clobber anything to the left of that. */
2431 if (p1prev
< leftmargin
)
2433 p2x
= charstart
+ (leftmargin
- p1start
);
2437 /* This loop skips over the char p2x initially points to. */
2446 val
.hpos
= - XINT (w
->hscroll
);
2454 /* Store 0 in this charstart line for the positions where
2455 there is no character. But do leave what was recorded
2456 for the character that ended the line. */
2457 /* Add 1 in the endtest to compensate for the fact that ENDP was
2458 made from WIDTH, which is 1 less than the window's actual
2460 i
= p1
- p1start
+ 1;
2461 if (p1
< leftmargin
)
2462 i
+= leftmargin
- p1
;
2463 for (; i
< endp
- p1start
+ 1; i
++)
2466 /* Handle continuation in middle of a character */
2467 /* by backing up over it */
2470 /* Don't back up if we never actually displayed any text.
2471 This occurs when the minibuffer prompt takes up the whole line. */
2474 /* Start the next line with that same character */
2476 /* but at negative hpos, to skip the columns output on this line. */
2477 val
.hpos
+= p1prev
- endp
;
2480 /* Keep in this line everything up to the continuation column. */
2484 /* Finish deciding which character to start the next line on,
2485 and what hpos to start it at.
2486 Also set `lastpos' to the last position which counts as "on this line"
2487 for cursor-positioning. */
2491 if (FETCH_CHAR (pos
) == '\n')
2493 /* If stopped due to a newline, start next line after it */
2495 /* Check again for hidden lines, in case the newline occurred exactly
2496 at the right margin. */
2497 while (pos
< ZV
&& selective
> 0
2498 && indented_beyond_p (pos
, selective
))
2499 pos
= find_next_newline (pos
, 1);
2502 /* Stopped due to right margin of window */
2506 *p1
++ = fix_glyph (f
, truncator
, 0);
2507 /* Truncating => start next line after next newline,
2508 and point is on this line if it is before the newline,
2509 and skip none of first char of next line */
2511 pos
= find_next_newline (pos
, 1);
2512 while (pos
< ZV
&& selective
> 0
2513 && indented_beyond_p (pos
, selective
));
2514 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
2516 lastpos
= pos
- (FETCH_CHAR (pos
- 1) == '\n');
2520 *p1
++ = fix_glyph (f
, continuer
, 0);
2527 /* If point is at eol or in invisible text at eol,
2528 record its frame location now. */
2530 if (start
<= PT
&& PT
<= lastpos
&& cursor_vpos
< 0)
2533 cursor_hpos
= p1
- leftmargin
;
2536 if (cursor_vpos
== vpos
)
2538 if (cursor_hpos
< 0) cursor_hpos
= 0;
2539 if (cursor_hpos
> width
) cursor_hpos
= width
;
2540 cursor_hpos
+= XFASTINT (w
->left
);
2541 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
2543 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2544 FRAME_CURSOR_X (f
) = cursor_hpos
;
2546 if (w
== XWINDOW (selected_window
))
2548 /* Line is not continued and did not start
2549 in middle of character */
2550 if ((hpos
- XFASTINT (w
->left
)
2551 == (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
2554 this_line_bufpos
= start
;
2555 this_line_buffer
= current_buffer
;
2556 this_line_vpos
= cursor_vpos
;
2557 this_line_start_hpos
= hpos
;
2558 this_line_endpos
= Z
- lastpos
;
2561 this_line_bufpos
= 0;
2566 /* If hscroll and line not empty, insert truncation-at-left marker */
2567 if (hscroll
&& lastpos
!= start
)
2569 *leftmargin
= fix_glyph (f
, truncator
, 0);
2570 if (p1
<= leftmargin
)
2571 p1
= leftmargin
+ 1;
2574 if (XFASTINT (w
->width
) + XFASTINT (w
->left
) != FRAME_WIDTH (f
))
2577 if (p1
< leftmargin
) p1
= leftmargin
;
2578 while (p1
< endp
) *p1
++ = SPACEGLYPH
;
2580 /* Don't draw vertical bars if we're using scroll bars. They're
2581 covered up by the scroll bars, and it's distracting to see
2582 them when the scroll bar windows are flickering around to be
2584 *p1
++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2586 : (dp
&& INTEGERP (DISP_BORDER_GLYPH (dp
))
2587 ? DISP_BORDER_GLYPH (dp
)
2590 desired_glyphs
->used
[vpos
] = max (desired_glyphs
->used
[vpos
],
2591 p1
- desired_glyphs
->glyphs
[vpos
]);
2592 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
2594 /* If the start of this line is the overlay arrow-position,
2595 then put the arrow string into the display-line. */
2597 if (MARKERP (Voverlay_arrow_position
)
2598 && current_buffer
== XMARKER (Voverlay_arrow_position
)->buffer
2599 && start
== marker_position (Voverlay_arrow_position
)
2600 && STRINGP (Voverlay_arrow_string
)
2601 && ! overlay_arrow_seen
)
2603 unsigned char *p
= XSTRING (Voverlay_arrow_string
)->data
;
2605 int len
= XSTRING (Voverlay_arrow_string
)->size
;
2611 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string
)->intervals
))
2613 /* If the arrow string has text props, obey them when displaying. */
2614 for (i
= 0; i
< len
; i
++)
2617 Lisp_Object face
, ilisp
;
2620 XSETFASTINT (ilisp
, i
);
2621 face
= Fget_text_property (ilisp
, Qface
, Voverlay_arrow_string
);
2622 newface
= compute_glyph_face_1 (f
, face
, 0);
2623 leftmargin
[i
] = FAST_MAKE_GLYPH (c
, newface
);
2627 #endif /* HAVE_FACES */
2629 for (i
= 0; i
< len
; i
++)
2630 leftmargin
[i
] = p
[i
];
2633 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
2634 arrow_end
= (leftmargin
- desired_glyphs
->glyphs
[vpos
]) + len
;
2635 if (desired_glyphs
->used
[vpos
] < arrow_end
)
2636 desired_glyphs
->used
[vpos
] = arrow_end
;
2638 overlay_arrow_seen
= 1;
2642 val_display_text_line
= val
;
2643 return &val_display_text_line
;
2646 /* Redisplay the menu bar in the frame for window W. */
2649 display_menu_bar (w
)
2652 Lisp_Object items
, tail
;
2653 register int vpos
= 0;
2654 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2655 int maxendcol
= FRAME_WIDTH (f
);
2659 #ifndef USE_X_TOOLKIT
2660 if (FRAME_MENU_BAR_LINES (f
) <= 0)
2663 get_display_line (f
, vpos
, 0);
2665 items
= FRAME_MENU_BAR_ITEMS (f
);
2666 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 3)
2668 Lisp_Object pos
, string
;
2669 string
= XVECTOR (items
)->contents
[i
+ 1];
2673 XSETFASTINT (XVECTOR (items
)->contents
[i
+ 2], hpos
);
2675 if (hpos
< maxendcol
)
2676 hpos
= display_string (XWINDOW (FRAME_ROOT_WINDOW (f
)), vpos
,
2677 XSTRING (string
)->data
,
2678 XSTRING (string
)->size
,
2679 hpos
, 0, 0, hpos
, maxendcol
);
2680 /* Put a gap of 3 spaces between items. */
2681 if (hpos
< maxendcol
)
2683 int hpos1
= hpos
+ 3;
2684 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0,
2685 min (hpos1
, maxendcol
), maxendcol
);
2689 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
2690 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
2692 /* Fill out the line with spaces. */
2693 if (maxendcol
> hpos
)
2694 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0, maxendcol
, maxendcol
);
2696 /* Clear the rest of the lines allocated to the menu bar. */
2698 while (vpos
< FRAME_MENU_BAR_LINES (f
))
2699 get_display_line (f
, vpos
++, 0);
2700 #endif /* not USE_X_TOOLKIT */
2703 /* Display the mode line for window w */
2706 display_mode_line (w
)
2709 register int vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
2710 register int left
= XFASTINT (w
->left
);
2711 register int right
= XFASTINT (w
->width
) + left
;
2712 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2714 line_number_displayed
= 0;
2716 get_display_line (f
, vpos
, left
);
2717 display_mode_element (w
, vpos
, left
, 0, right
, right
,
2718 current_buffer
->mode_line_format
);
2719 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
2721 /* Make the mode line inverse video if the entire line
2722 is made of mode lines.
2723 I.e. if this window is full width,
2724 or if it is the child of a full width window
2725 (which implies that that window is split side-by-side
2726 and the rest of this line is mode lines of the sibling windows). */
2727 if (XFASTINT (w
->width
) == FRAME_WIDTH (f
)
2728 || XFASTINT (XWINDOW (w
->parent
)->width
) == FRAME_WIDTH (f
))
2729 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
2731 else if (! FRAME_TERMCAP_P (f
))
2733 /* For a partial width window, explicitly set face of each glyph. */
2735 GLYPH
*ptr
= FRAME_DESIRED_GLYPHS (f
)->glyphs
[vpos
];
2736 for (i
= left
; i
< right
; ++i
)
2737 ptr
[i
] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr
[i
]), 1);
2742 /* Contribute ELT to the mode line for window W.
2743 How it translates into text depends on its data type.
2745 VPOS is the position of the mode line being displayed.
2747 HPOS is the position (absolute on frame) where this element's text
2748 should start. The output is truncated automatically at the right
2751 DEPTH is the depth in recursion. It is used to prevent
2752 infinite recursion here.
2754 MINENDCOL is the hpos before which the element may not end.
2755 The element is padded at the right with spaces if nec
2756 to reach this column.
2758 MAXENDCOL is the hpos past which this element may not extend.
2759 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
2760 (This is necessary to make nested padding and truncation work.)
2762 Returns the hpos of the end of the text generated by ELT.
2763 The next element will receive that value as its HPOS arg,
2764 so as to concatenate the elements. */
2767 display_mode_element (w
, vpos
, hpos
, depth
, minendcol
, maxendcol
, elt
)
2769 register int vpos
, hpos
;
2772 register int maxendcol
;
2773 register Lisp_Object elt
;
2781 #ifdef SWITCH_ENUM_BUG
2782 switch ((int) XTYPE (elt
))
2784 switch (XTYPE (elt
))
2789 /* A string: output it and check for %-constructs within it. */
2790 register unsigned char c
;
2791 register unsigned char *this = XSTRING (elt
)->data
;
2793 while (hpos
< maxendcol
&& *this)
2795 unsigned char *last
= this;
2796 while ((c
= *this++) != '\0' && c
!= '%')
2798 if (this - 1 != last
)
2800 register int lim
= --this - last
+ hpos
;
2801 if (frame_title_ptr
)
2802 hpos
= store_frame_title (last
, hpos
, min (lim
, maxendcol
));
2804 hpos
= display_string (w
, vpos
, last
, -1, hpos
, 0, 1,
2805 hpos
, min (lim
, maxendcol
));
2809 register int spec_width
= 0;
2811 /* We can't allow -ve args due to the "%-" construct */
2812 /* Argument specifies minwidth but not maxwidth
2813 (maxwidth can be specified by
2814 (<negative-number> . <stuff>) mode-line elements) */
2816 while ((c
= *this++) >= '0' && c
<= '9')
2818 spec_width
= spec_width
* 10 + (c
- '0');
2822 if (spec_width
> maxendcol
)
2823 spec_width
= maxendcol
;
2826 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
2827 spec_width
, maxendcol
,
2828 Vglobal_mode_string
);
2831 char *spec
= decode_mode_spec (w
, c
, maxendcol
- hpos
);
2832 if (frame_title_ptr
)
2833 hpos
= store_frame_title (spec
, spec_width
, maxendcol
);
2835 hpos
= display_string (w
, vpos
, spec
, -1,
2837 spec_width
, maxendcol
);
2845 /* A symbol: process the value of the symbol recursively
2846 as if it appeared here directly. Avoid error if symbol void.
2847 Special case: if value of symbol is a string, output the string
2850 register Lisp_Object tem
;
2851 tem
= Fboundp (elt
);
2854 tem
= Fsymbol_value (elt
);
2855 /* If value is a string, output that string literally:
2856 don't check for % within it. */
2859 if (frame_title_ptr
)
2860 hpos
= store_frame_title (XSTRING (tem
)->data
,
2861 minendcol
, maxendcol
);
2863 hpos
= display_string (w
, vpos
, XSTRING (tem
)->data
,
2864 XSTRING (tem
)->size
,
2865 hpos
, 0, 1, minendcol
, maxendcol
);
2867 /* Give up right away for nil or t. */
2868 else if (!EQ (tem
, elt
))
2869 { elt
= tem
; goto tail_recurse
; }
2876 register Lisp_Object car
, tem
;
2878 /* A cons cell: three distinct cases.
2879 If first element is a string or a cons, process all the elements
2880 and effectively concatenate them.
2881 If first element is a negative number, truncate displaying cdr to
2882 at most that many characters. If positive, pad (with spaces)
2883 to at least that many characters.
2884 If first element is a symbol, process the cadr or caddr recursively
2885 according to whether the symbol's value is non-nil or nil. */
2886 car
= XCONS (elt
)->car
;
2889 tem
= Fboundp (car
);
2890 elt
= XCONS (elt
)->cdr
;
2893 /* elt is now the cdr, and we know it is a cons cell.
2894 Use its car if CAR has a non-nil value. */
2897 tem
= Fsymbol_value (car
);
2899 { elt
= XCONS (elt
)->car
; goto tail_recurse
; }
2901 /* Symbol's value is nil (or symbol is unbound)
2902 Get the cddr of the original list
2903 and if possible find the caddr and use that. */
2904 elt
= XCONS (elt
)->cdr
;
2907 else if (!CONSP (elt
))
2909 elt
= XCONS (elt
)->car
;
2912 else if (INTEGERP (car
))
2914 register int lim
= XINT (car
);
2915 elt
= XCONS (elt
)->cdr
;
2917 /* Negative int means reduce maximum width.
2918 DO NOT change MINENDCOL here!
2919 (20 -10 . foo) should truncate foo to 10 col
2920 and then pad to 20. */
2921 maxendcol
= min (maxendcol
, hpos
- lim
);
2924 /* Padding specified. Don't let it be more than
2927 if (lim
> maxendcol
)
2929 /* If that's more padding than already wanted, queue it.
2930 But don't reduce padding already specified even if
2931 that is beyond the current truncation point. */
2932 if (lim
> minendcol
)
2937 else if (STRINGP (car
) || CONSP (car
))
2939 register int limit
= 50;
2940 /* LIMIT is to protect against circular lists. */
2941 while (CONSP (elt
) && --limit
> 0
2942 && hpos
< maxendcol
)
2944 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
2947 elt
= XCONS (elt
)->cdr
;
2955 if (frame_title_ptr
)
2956 hpos
= store_frame_title ("*invalid*", minendcol
, maxendcol
);
2958 hpos
= display_string (w
, vpos
, "*invalid*", -1, hpos
, 0, 1,
2959 minendcol
, maxendcol
);
2963 if (minendcol
> hpos
)
2964 if (frame_title_ptr
)
2965 hpos
= store_frame_title ("", minendcol
, maxendcol
);
2967 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 1, minendcol
, maxendcol
);
2971 /* Return a string for the output of a mode line %-spec for window W,
2972 generated by character C and width MAXWIDTH. */
2974 static char lots_of_dashes
[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
2977 decode_mode_spec (w
, c
, maxwidth
)
2980 register int maxwidth
;
2983 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2984 char *decode_mode_spec_buf
= (char *) FRAME_TEMP_GLYPHS (f
)->total_contents
;
2985 struct buffer
*b
= XBUFFER (w
->buffer
);
2988 if (maxwidth
> FRAME_WIDTH (f
))
2989 maxwidth
= FRAME_WIDTH (f
);
2996 if (maxwidth
>= 3 && XSTRING (obj
)->size
> maxwidth
)
2998 bcopy (XSTRING (obj
)->data
, decode_mode_spec_buf
, maxwidth
- 1);
2999 decode_mode_spec_buf
[maxwidth
- 1] = '\\';
3000 decode_mode_spec_buf
[maxwidth
] = '\0';
3001 return decode_mode_spec_buf
;
3011 else if (STRINGP (obj
) && XSTRING (obj
)->size
> maxwidth
)
3013 bcopy ("...", decode_mode_spec_buf
, 3);
3014 bcopy (XSTRING (obj
)->data
+ XSTRING (obj
)->size
- maxwidth
+ 3,
3015 decode_mode_spec_buf
+ 3, maxwidth
- 3);
3016 return decode_mode_spec_buf
;
3022 sprintf (decode_mode_spec_buf
, "%d", current_column ());
3023 return decode_mode_spec_buf
;
3027 int startpos
= marker_position (w
->start
);
3028 int line
, linepos
, topline
;
3031 int height
= XFASTINT (w
->height
);
3033 /* If we decided that this buffer isn't suitable for line numbers,
3034 don't forget that too fast. */
3035 if (EQ (w
->base_line_pos
, w
->buffer
))
3038 /* If the buffer is very big, don't waste time. */
3039 if (BUF_ZV (b
) - BUF_BEGV (b
) > line_number_display_limit
)
3041 w
->base_line_pos
= Qnil
;
3042 w
->base_line_number
= Qnil
;
3046 if (!NILP (w
->base_line_number
)
3047 && !NILP (w
->base_line_pos
)
3048 && XFASTINT (w
->base_line_pos
) <= marker_position (w
->start
))
3050 line
= XFASTINT (w
->base_line_number
);
3051 linepos
= XFASTINT (w
->base_line_pos
);
3056 linepos
= BUF_BEGV (b
);
3059 /* Count lines from base line to window start position. */
3060 nlines
= display_count_lines (linepos
, startpos
, startpos
, &junk
);
3062 topline
= nlines
+ line
;
3064 /* Determine a new base line, if the old one is too close
3065 or too far away, or if we did not have one.
3066 "Too close" means it's plausible a scroll-down would
3068 if (startpos
== BUF_BEGV (b
))
3070 XSETFASTINT (w
->base_line_number
, topline
);
3071 XSETFASTINT (w
->base_line_pos
, BUF_BEGV (b
));
3073 else if (nlines
< height
+ 25 || nlines
> height
* 3 + 50
3074 || linepos
== BUF_BEGV (b
))
3076 int limit
= BUF_BEGV (b
);
3078 int distance
= (height
* 2 + 30) * 200;
3080 if (startpos
- distance
> limit
)
3081 limit
= startpos
- distance
;
3083 nlines
= display_count_lines (startpos
, limit
,
3086 /* If we couldn't find the lines we wanted within
3088 give up on line numbers for this window. */
3089 if (position
== startpos
- distance
)
3091 w
->base_line_pos
= w
->buffer
;
3092 w
->base_line_number
= Qnil
;
3096 XSETFASTINT (w
->base_line_number
, topline
- nlines
);
3097 XSETFASTINT (w
->base_line_pos
, position
);
3100 /* Now count lines from the start pos to point. */
3101 nlines
= display_count_lines (startpos
, PT
, PT
, &junk
);
3103 /* Record that we did display the line number. */
3104 line_number_displayed
= 1;
3106 /* Make the string to show. */
3107 sprintf (decode_mode_spec_buf
, "%d", topline
+ nlines
);
3108 return decode_mode_spec_buf
;
3117 if (BUF_BEGV (b
) > BUF_BEG (b
) || BUF_ZV (b
) < BUF_Z (b
))
3122 if (!NILP (b
->read_only
))
3124 if (BUF_MODIFF (b
) > b
->save_modified
)
3129 /* This differs from %* only for a modified read-only buffer. */
3130 if (BUF_MODIFF (b
) > b
->save_modified
)
3132 if (!NILP (b
->read_only
))
3137 /* This differs from %* in ignoring read-only-ness. */
3138 if (BUF_MODIFF (b
) > b
->save_modified
)
3143 /* status of process */
3144 obj
= Fget_buffer_process (w
->buffer
);
3146 return "no process";
3148 obj
= Fsymbol_name (Fprocess_status (obj
));
3152 case 't': /* indicate TEXT or BINARY */
3153 #ifdef MODE_LINE_BINARY_TEXT
3154 return MODE_LINE_BINARY_TEXT (b
);
3161 int pos
= marker_position (w
->start
);
3162 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3164 if (XFASTINT (w
->window_end_pos
) <= BUF_Z (b
) - BUF_ZV (b
))
3166 if (pos
<= BUF_BEGV (b
))
3171 else if (pos
<= BUF_BEGV (b
))
3175 total
= ((pos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3176 /* We can't normally display a 3-digit number,
3177 so get us a 2-digit number that is close. */
3180 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3181 return decode_mode_spec_buf
;
3185 /* Display percentage of size above the bottom of the screen. */
3188 int toppos
= marker_position (w
->start
);
3189 int botpos
= BUF_Z (b
) - XFASTINT (w
->window_end_pos
);
3190 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3192 if (botpos
>= BUF_ZV (b
))
3194 if (toppos
<= BUF_BEGV (b
))
3201 total
= ((botpos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3202 /* We can't normally display a 3-digit number,
3203 so get us a 2-digit number that is close. */
3206 if (toppos
<= BUF_BEGV (b
))
3207 sprintf (decode_mode_spec_buf
, "Top%2d%%", total
);
3209 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3210 return decode_mode_spec_buf
;
3222 if (command_loop_level
> 5)
3224 p
= decode_mode_spec_buf
;
3225 for (i
= 0; i
< command_loop_level
; i
++)
3228 return decode_mode_spec_buf
;
3236 if (command_loop_level
> 5)
3238 p
= decode_mode_spec_buf
;
3239 for (i
= 0; i
< command_loop_level
; i
++)
3242 return decode_mode_spec_buf
;
3250 if (maxwidth
< sizeof (lots_of_dashes
))
3251 return lots_of_dashes
;
3254 for (p
= decode_mode_spec_buf
, i
= maxwidth
; i
> 0; i
--)
3258 return decode_mode_spec_buf
;
3263 return (char *) XSTRING (obj
)->data
;
3268 /* Search for COUNT instances of a line boundary, which means either a
3269 newline or (if selective display enabled) a carriage return.
3270 Start at START. If COUNT is negative, search backwards.
3272 If we find COUNT instances, set *SHORTAGE to zero, and return the
3273 position after the COUNTth match. Note that for reverse motion
3274 this is not the same as the usual convention for Emacs motion commands.
3276 If we don't find COUNT instances before reaching the end of the
3277 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3278 the number of line boundaries left unfound, and return the end of the
3279 buffer we bumped up against. */
3282 display_scan_buffer (start
, count
, shortage
)
3283 int *shortage
, start
;
3286 int limit
= ((count
> 0) ? ZV
- 1 : BEGV
);
3287 int direction
= ((count
> 0) ? 1 : -1);
3289 register unsigned char *cursor
;
3290 unsigned char *base
;
3292 register int ceiling
;
3293 register unsigned char *ceiling_addr
;
3295 /* If we are not in selective display mode,
3296 check only for newlines. */
3297 if (! (!NILP (current_buffer
->selective_display
)
3298 && !INTEGERP (current_buffer
->selective_display
)))
3299 return scan_buffer ('\n', start
, 0, count
, shortage
, 0);
3301 /* The code that follows is like scan_buffer
3302 but checks for either newline or carriage return. */
3308 while (start
!= limit
+ 1)
3310 ceiling
= BUFFER_CEILING_OF (start
);
3311 ceiling
= min (limit
, ceiling
);
3312 ceiling_addr
= &FETCH_CHAR (ceiling
) + 1;
3313 base
= (cursor
= &FETCH_CHAR (start
));
3316 while (*cursor
!= '\n' && *cursor
!= 015 && ++cursor
!= ceiling_addr
)
3318 if (cursor
!= ceiling_addr
)
3323 return (start
+ cursor
- base
+ 1);
3326 if (++cursor
== ceiling_addr
)
3332 start
+= cursor
- base
;
3336 start
--; /* first character we scan */
3337 while (start
> limit
- 1)
3338 { /* we WILL scan under start */
3339 ceiling
= BUFFER_FLOOR_OF (start
);
3340 ceiling
= max (limit
, ceiling
);
3341 ceiling_addr
= &FETCH_CHAR (ceiling
) - 1;
3342 base
= (cursor
= &FETCH_CHAR (start
));
3346 while (--cursor
!= ceiling_addr
3347 && *cursor
!= '\n' && *cursor
!= 015)
3349 if (cursor
!= ceiling_addr
)
3354 return (start
+ cursor
- base
+ 1);
3360 start
+= cursor
- base
;
3365 *shortage
= count
* direction
;
3366 return (start
+ ((direction
== 1 ? 0 : 1)));
3369 /* Count up to N lines starting from FROM.
3370 But don't go beyond LIMIT.
3371 Return the number of lines thus found (always positive).
3372 Store the position after what was found into *POS_PTR. */
3375 display_count_lines (from
, limit
, n
, pos_ptr
)
3388 *pos_ptr
= display_scan_buffer (from
, n
, &shortage
);
3394 /* When scanning backwards, scan_buffer stops *after* the last newline
3395 it finds, but does count it. Compensate for that. */
3396 return - n
- shortage
- (*pos_ptr
!= limit
);
3397 return n
- shortage
;
3400 /* Display STRING on one line of window W, starting at HPOS.
3401 Display at position VPOS. Caller should have done get_display_line.
3402 If VPOS == -1, display it as the current frame's title.
3403 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3405 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3407 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3408 MAXCOL is the last column ok to end at. Truncate here.
3409 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3410 Both count from the left edge of the frame, as does HPOS.
3411 The right edge of W is an implicit maximum.
3412 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3414 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3415 at the place where the current window ends in this line
3416 and not display anything beyond there. Otherwise, only MAXCOL
3417 controls where to stop output.
3419 Returns ending hpos. */
3422 display_string (w
, vpos
, string
, length
, hpos
, truncate
,
3423 obey_window_width
, mincol
, maxcol
)
3425 unsigned char *string
;
3429 int obey_window_width
;
3434 int hscroll
= XINT (w
->hscroll
);
3435 int tab_width
= XINT (XBUFFER (w
->buffer
)->tab_width
);
3436 register GLYPH
*start
;
3437 register GLYPH
*end
;
3438 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3439 struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
3440 GLYPH
*p1start
= desired_glyphs
->glyphs
[vpos
] + hpos
;
3441 int window_width
= XFASTINT (w
->width
);
3443 /* Use the standard display table, not the window's display table.
3444 We don't want the mode line in rot13. */
3445 register struct Lisp_Vector
*dp
= 0;
3448 if (VECTORP (Vstandard_display_table
)
3449 && XVECTOR (Vstandard_display_table
)->size
== DISP_TABLE_SIZE
)
3450 dp
= XVECTOR (Vstandard_display_table
);
3452 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
3455 start
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
3457 if (obey_window_width
)
3459 end
= start
+ window_width
- (truncate
!= 0);
3461 if ((window_width
+ XFASTINT (w
->left
)) != FRAME_WIDTH (f
))
3463 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3467 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
3475 if (! obey_window_width
3476 || (maxcol
>= 0 && end
- desired_glyphs
->glyphs
[vpos
] > maxcol
))
3477 end
= desired_glyphs
->glyphs
[vpos
] + maxcol
;
3479 /* Store 0 in charstart for these columns. */
3480 for (i
= (hpos
>= 0 ? hpos
: 0); i
< end
- p1start
+ hpos
; i
++)
3481 desired_glyphs
->charstarts
[vpos
][i
] = 0;
3483 if (maxcol
>= 0 && mincol
> maxcol
)
3491 /* Specified length. */
3494 /* Unspecified length (null-terminated string). */
3498 if (c
>= 040 && c
< 0177
3499 && (dp
== 0 || !VECTORP (DISP_CHAR_VECTOR (dp
, c
))))
3509 if (p1
>= start
&& p1
< end
)
3513 while ((p1
- start
+ hscroll
- (hscroll
> 0)) % tab_width
);
3515 else if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
3517 p1
= copy_part_of_rope (f
, p1
, start
,
3518 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
3519 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
3522 else if (c
< 0200 && ! NILP (buffer_defaults
.ctl_arrow
))
3525 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
3526 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
3529 if (p1
>= start
&& p1
< end
)
3536 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
3537 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
3540 if (p1
>= start
&& p1
< end
)
3541 *p1
= (c
>> 6) + '0';
3543 if (p1
>= start
&& p1
< end
)
3544 *p1
= (7 & (c
>> 3)) + '0';
3546 if (p1
>= start
&& p1
< end
)
3547 *p1
= (7 & c
) + '0';
3552 if (c
&& length
> 0)
3555 if (truncate
) *p1
++ = fix_glyph (f
, truncate
, 0);
3557 else if (mincol
>= 0)
3559 end
= desired_glyphs
->glyphs
[vpos
] + mincol
;
3565 register int len
= p1
- desired_glyphs
->glyphs
[vpos
];
3567 if (len
> desired_glyphs
->used
[vpos
])
3568 desired_glyphs
->used
[vpos
] = len
;
3569 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
3578 staticpro (&Qmenu_bar_update_hook
);
3579 Qmenu_bar_update_hook
= intern ("menu-bar-update-hook");
3581 staticpro (&last_arrow_position
);
3582 staticpro (&last_arrow_string
);
3583 last_arrow_position
= Qnil
;
3584 last_arrow_string
= Qnil
;
3586 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
,
3587 "String (or mode line construct) included (normally) in `mode-line-format'.");
3588 Vglobal_mode_string
= Qnil
;
3590 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
,
3591 "Marker for where to display an arrow on top of the buffer text.\n\
3592 This must be the beginning of a line in order to work.\n\
3593 See also `overlay-arrow-string'.");
3594 Voverlay_arrow_position
= Qnil
;
3596 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
,
3597 "String to display as an arrow. See also `overlay-arrow-position'.");
3598 Voverlay_arrow_string
= Qnil
;
3600 DEFVAR_INT ("scroll-step", &scroll_step
,
3601 "*The number of lines to try scrolling a window by when point moves out.\n\
3602 If that fails to bring point back on frame, point is centered instead.\n\
3603 If this is zero, point is always centered after it moves off frame.");
3605 DEFVAR_INT ("debug-end-pos", &debug_end_pos
, "Don't ask");
3607 DEFVAR_BOOL ("truncate-partial-width-windows",
3608 &truncate_partial_width_windows
,
3609 "*Non-nil means truncate lines in all windows less than full frame wide.");
3610 truncate_partial_width_windows
= 1;
3612 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
,
3613 "*Non-nil means use inverse video for the mode line.");
3614 mode_line_inverse_video
= 1;
3616 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit
,
3617 "*Maximum buffer size for which line number should be displayed.");
3618 line_number_display_limit
= 1000000;
3620 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
,
3621 "*Non-nil means highlight region even in nonselected windows.");
3622 highlight_nonselected_windows
= 1;
3624 DEFVAR_BOOL ("multiple-frames", &multiple_frames
,
3625 "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\
3626 Not guaranteed to be accurate except while parsing frame-title-format.");
3628 DEFVAR_LISP ("frame-title-format", &Vframe_title_format
,
3629 "Template for displaying the titlebar of visible frames.\n\
3630 \(Assuming the window manager supports this feature.)\n\
3631 This variable has the same structure as `mode-line-format' (which see),\n\
3632 and is used only on frames for which no explicit name has been set\n\
3633 \(see `modify-frame-parameters').");
3634 DEFVAR_LISP ("icon-title-format", &Vicon_title_format
,
3635 "Template for displaying the titlebar of an iconified frame.\n\
3636 \(Assuming the window manager supports this feature.)\n\
3637 This variable has the same structure as `mode-line-format' (which see),\n\
3638 and is used only on frames for which no explicit name has been set\n\
3639 \(see `modify-frame-parameters').");
3641 = Vframe_title_format
3642 = Fcons (intern ("multiple-frames"),
3643 Fcons (build_string ("%b"),
3644 Fcons (Fcons (build_string (""),
3645 Fcons (intern ("invocation-name"),
3646 Fcons (build_string ("@"),
3647 Fcons (intern ("system-name"),
3652 /* initialize the window system */
3655 Lisp_Object root_window
;
3656 #ifndef COMPILER_REGISTER_BUG
3658 #endif /* COMPILER_REGISTER_BUG */
3659 struct window
*mini_w
;
3661 this_line_bufpos
= 0;
3663 mini_w
= XWINDOW (minibuf_window
);
3664 root_window
= FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w
)));
3666 echo_area_glyphs
= 0;
3667 previous_echo_glyphs
= 0;
3669 if (!noninteractive
)
3671 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (root_window
)));
3672 XSETFASTINT (XWINDOW (root_window
)->top
, 0);
3673 set_window_height (root_window
, FRAME_HEIGHT (f
) - 1, 0);
3674 XSETFASTINT (mini_w
->top
, FRAME_HEIGHT (f
) - 1);
3675 set_window_height (minibuf_window
, 1, 0);
3677 XSETFASTINT (XWINDOW (root_window
)->width
, FRAME_WIDTH (f
));
3678 XSETFASTINT (mini_w
->width
, FRAME_WIDTH (f
));