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
;
551 register struct window
*w
= XWINDOW (selected_window
);
555 register int tlbufpos
, tlendpos
;
557 extern int input_pending
;
562 /* Set the visible flags for all frames.
563 Do this before checking for resized or garbaged frames; they want
564 to know if their frames are visible.
565 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
567 Lisp_Object tail
, frame
;
569 FOR_EACH_FRAME (tail
, frame
)
570 FRAME_SAMPLE_VISIBILITY (XFRAME (frame
));
573 /* Notice any pending interrupt request to change frame size. */
574 do_pending_window_change ();
578 redraw_garbaged_frames ();
582 if (clip_changed
|| windows_or_buffers_changed
)
585 /* Detect case that we need to write a star in the mode line. */
586 if (XFASTINT (w
->last_modified
) < MODIFF
587 && XFASTINT (w
->last_modified
) <= current_buffer
->save_modified
)
589 w
->update_mode_line
= Qt
;
590 if (buffer_shared
> 1)
594 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w
->frame
)) = -1;
596 all_windows
= update_mode_lines
|| buffer_shared
> 1;
598 /* If specs for an arrow have changed, do thorough redisplay
599 to ensure we remove any arrow that should no longer exist. */
600 if (! EQ (Voverlay_arrow_position
, last_arrow_position
)
601 || ! EQ (Voverlay_arrow_string
, last_arrow_string
))
602 all_windows
= 1, clip_changed
= 1;
604 /* Normally the message* functions will have already displayed and
605 updated the echo area, but the frame may have been trashed, or
606 the update may have been preempted, so display the echo area
608 if (echo_area_glyphs
|| previous_echo_glyphs
)
610 echo_area_display ();
614 /* If showing region, and mark has changed, must redisplay whole window. */
615 if (((!NILP (Vtransient_mark_mode
)
616 && !NILP (XBUFFER (w
->buffer
)->mark_active
))
617 != !NILP (w
->region_showing
))
618 || (!NILP (w
->region_showing
)
619 && !EQ (w
->region_showing
,
620 Fmarker_position (XBUFFER (w
->buffer
)->mark
))))
621 this_line_bufpos
= -1;
623 tlbufpos
= this_line_bufpos
;
624 tlendpos
= this_line_endpos
;
625 if (!all_windows
&& tlbufpos
> 0 && NILP (w
->update_mode_line
)
626 && FRAME_VISIBLE_P (XFRAME (w
->frame
))
627 /* Make sure recorded data applies to current buffer, etc */
628 && this_line_buffer
== current_buffer
629 && current_buffer
== XBUFFER (w
->buffer
)
630 && NILP (w
->force_start
)
631 /* Point must be on the line that we have info recorded about */
633 && PT
<= Z
- tlendpos
634 /* All text outside that line, including its final newline,
636 && (XFASTINT (w
->last_modified
) >= MODIFF
637 || (beg_unchanged
>= tlbufpos
- 1
639 /* If selective display, can't optimize
640 if the changes start at the beginning of the line. */
641 && ((INTEGERP (current_buffer
->selective_display
)
642 && XINT (current_buffer
->selective_display
) > 0
643 ? (beg_unchanged
>= tlbufpos
646 && end_unchanged
>= tlendpos
647 && Z
- GPT
>= tlendpos
)))
649 if (tlbufpos
> BEGV
&& FETCH_CHAR (tlbufpos
- 1) != '\n'
651 || FETCH_CHAR (tlbufpos
) == '\n'))
652 /* Former continuation line has disappeared by becoming empty */
654 else if (XFASTINT (w
->last_modified
) < MODIFF
655 || MINI_WINDOW_P (w
))
658 overlay_arrow_seen
= 0;
659 display_text_line (w
, tlbufpos
, this_line_vpos
, this_line_start_hpos
,
660 pos_tab_offset (w
, tlbufpos
));
661 /* If line contains point, is not continued,
662 and ends at same distance from eob as before, we win */
663 if (cursor_vpos
>= 0 && this_line_bufpos
664 && this_line_endpos
== tlendpos
)
666 /* If this is not the window's last line,
667 we must adjust the charstarts of the lines below. */
668 if (this_line_vpos
+ 1
669 < XFASTINT (w
->top
) + window_internal_height (w
))
671 int left
= XFASTINT (w
->left
);
672 int *charstart_next_line
673 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w
)))->charstarts
[this_line_vpos
+ 1];
677 if (Z
- tlendpos
== ZV
)
678 /* This line ends at end of (accessible part of) buffer.
679 There is no newline to count. */
680 adjust
= Z
- tlendpos
- charstart_next_line
[left
];
682 /* This line ends in a newline.
683 Must take account of the newline and the rest of the
684 text that follows. */
685 adjust
= Z
- tlendpos
+ 1 - charstart_next_line
[left
];
687 adjust_window_charstarts (w
, this_line_vpos
, adjust
);
690 if (XFASTINT (w
->width
) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w
))))
691 preserve_other_columns (w
);
697 else if (PT
== XFASTINT (w
->last_point
))
701 do_pending_window_change ();
706 /* If highlighting the region, we can't just move the cursor. */
707 else if (! (!NILP (Vtransient_mark_mode
)
708 && !NILP (current_buffer
->mark_active
))
709 && NILP (w
->region_showing
))
711 pos
= *compute_motion (tlbufpos
, 0,
712 XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0,
713 PT
, 2, - (1 << (SHORTBITS
- 1)),
714 window_internal_width (w
) - 1,
716 pos_tab_offset (w
, tlbufpos
), w
);
719 FRAME_CURSOR_X (selected_frame
)
720 = XFASTINT (w
->left
) + max (pos
.hpos
, 0);
721 FRAME_CURSOR_Y (selected_frame
) = this_line_vpos
;
728 /* Text changed drastically or point moved off of line */
729 cancel_line (this_line_vpos
, selected_frame
);
732 this_line_bufpos
= 0;
733 all_windows
|= buffer_shared
> 1;
737 Lisp_Object tail
, frame
;
739 #ifdef HAVE_X_WINDOWS
740 /* Since we're doing a thorough redisplay, we might as well
741 recompute all our display faces. */
742 clear_face_vector ();
745 /* Recompute # windows showing selected buffer.
746 This will be incremented each time such a window is displayed. */
749 FOR_EACH_FRAME (tail
, frame
)
751 FRAME_PTR f
= XFRAME (frame
);
753 /* Mark all the scroll bars to be removed; we'll redeem the ones
754 we want when we redisplay their windows. */
755 if (condemn_scroll_bars_hook
)
756 (*condemn_scroll_bars_hook
) (f
);
758 if (FRAME_VISIBLE_P (f
))
759 redisplay_windows (FRAME_ROOT_WINDOW (f
));
761 /* Any scroll bars which redisplay_windows should have nuked
762 should now go away. */
763 if (judge_scroll_bars_hook
)
764 (*judge_scroll_bars_hook
) (f
);
767 else if (FRAME_VISIBLE_P (selected_frame
))
769 redisplay_window (selected_window
, 1);
770 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
771 preserve_other_columns (w
);
775 /* Prevent various kinds of signals during display update.
776 stdio is not robust about handling signals,
777 which can cause an apparent I/O error. */
789 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
793 if (!FRAMEP (XCONS (tail
)->car
))
796 f
= XFRAME (XCONS (tail
)->car
);
797 if (FRAME_VISIBLE_P (f
))
799 pause
|= update_frame (f
, 0, 0);
802 mark_window_display_accurate (f
->root_window
, 1);
803 if (frame_up_to_date_hook
!= 0)
804 (*frame_up_to_date_hook
) (f
);
810 #endif /* MULTI_FRAME */
812 if (FRAME_VISIBLE_P (selected_frame
))
813 pause
= update_frame (selected_frame
, 0, 0);
815 /* We may have called echo_area_display at the top of this
816 function. If the echo area is on another frame, that may
817 have put text on a frame other than the selected one, so the
818 above call to update_frame would not have caught it. Catch
822 = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window
)));
824 if (mini_frame
!= selected_frame
)
825 pause
|= update_frame (mini_frame
, 0, 0);
829 /* If frame does not match, prevent doing single-line-update next time.
830 Also, don't forget to check every line to update the arrow. */
833 this_line_bufpos
= 0;
834 if (!NILP (last_arrow_position
))
836 last_arrow_position
= Qt
;
837 last_arrow_string
= Qt
;
839 /* If we pause after scrolling, some lines in current_frame
840 may be null, so preserve_other_columns won't be able to
841 preserve all the vertical-bar separators. So, avoid using it
843 if (XFASTINT (w
->width
) != FRAME_WIDTH (selected_frame
))
844 update_mode_lines
= 1;
847 /* Now text on frame agrees with windows, so
848 put info into the windows for partial redisplay to follow */
852 register struct buffer
*b
= XBUFFER (w
->buffer
);
854 blank_end_of_window
= 0;
856 unchanged_modified
= BUF_MODIFF (b
);
857 beg_unchanged
= BUF_GPT (b
) - BUF_BEG (b
);
858 end_unchanged
= BUF_Z (b
) - BUF_GPT (b
);
860 XFASTINT (w
->last_point
) = BUF_PT (b
);
861 XFASTINT (w
->last_point_x
) = FRAME_CURSOR_X (selected_frame
);
862 XFASTINT (w
->last_point_y
) = FRAME_CURSOR_Y (selected_frame
);
865 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame
), 1);
868 w
->update_mode_line
= Qnil
;
869 XFASTINT (w
->last_modified
) = BUF_MODIFF (b
);
870 w
->window_end_valid
= w
->buffer
;
871 last_arrow_position
= Voverlay_arrow_position
;
872 last_arrow_string
= Voverlay_arrow_string
;
873 if (do_verify_charstarts
)
874 verify_charstarts (w
);
875 if (frame_up_to_date_hook
!= 0)
876 (*frame_up_to_date_hook
) (selected_frame
);
878 update_mode_lines
= 0;
879 windows_or_buffers_changed
= 0;
882 /* Start SIGIO interrupts coming again.
883 Having them off during the code above
884 makes it less likely one will discard output,
885 but not impossible, since there might be stuff
886 in the system buffer here.
887 But it is much hairier to try to do anything about that. */
893 /* Change frame size now if a change is pending. */
894 do_pending_window_change ();
896 /* If we just did a pending size change, redisplay again
898 if (windows_or_buffers_changed
&& !pause
)
902 /* Redisplay, but leave alone any recent echo area message
903 unless another message has been requested in its place.
905 This is useful in situations where you need to redisplay but no
906 user action has occurred, making it inappropriate for the message
907 area to be cleared. See tracking_off and
908 wait_reading_process_input for examples of these situations. */
910 redisplay_preserve_echo_area ()
912 if (echo_area_glyphs
== 0 && previous_echo_glyphs
!= 0)
914 echo_area_glyphs
= previous_echo_glyphs
;
916 echo_area_glyphs
= 0;
923 mark_window_display_accurate (window
, flag
)
927 register struct window
*w
;
929 for (;!NILP (window
); window
= w
->next
)
931 if (!WINDOWP (window
)) abort ();
932 w
= XWINDOW (window
);
934 if (!NILP (w
->buffer
))
936 XFASTINT (w
->last_modified
)
938 : XBUFFER (w
->buffer
) == current_buffer
939 ? MODIFF
: BUF_MODIFF (XBUFFER (w
->buffer
));
941 /* Record if we are showing a region, so can make sure to
942 update it fully at next redisplay. */
943 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
944 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
945 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
949 w
->window_end_valid
= w
->buffer
;
950 w
->update_mode_line
= Qnil
;
952 if (!NILP (w
->vchild
))
953 mark_window_display_accurate (w
->vchild
, flag
);
954 if (!NILP (w
->hchild
))
955 mark_window_display_accurate (w
->hchild
, flag
);
960 last_arrow_position
= Voverlay_arrow_position
;
961 last_arrow_string
= Voverlay_arrow_string
;
965 /* t is unequal to any useful value of Voverlay_arrow_... */
966 last_arrow_position
= Qt
;
967 last_arrow_string
= Qt
;
971 /* Update the menu bar item list for frame F.
972 This has to be done before we start to fill in any display lines,
973 because it can call eval. */
979 struct buffer
*old
= current_buffer
;
981 register struct window
*w
;
982 window
= FRAME_SELECTED_WINDOW (f
);
983 w
= XWINDOW (window
);
985 if (update_mode_lines
)
986 w
->update_mode_line
= Qt
;
990 FRAME_EXTERNAL_MENU_BAR (f
)
992 FRAME_MENU_BAR_LINES (f
) > 0
996 /* If the user has switched buffers or windows, we need to
997 recompute to reflect the new bindings. But we'll
998 recompute when update_mode_lines is set too; that means
999 that people can use force-mode-line-update to request
1000 that the menu bar be recomputed. The adverse effect on
1001 the rest of the redisplay algorithm is about the same as
1002 windows_or_buffers_changed anyway. */
1003 if (windows_or_buffers_changed
1004 || !NILP (w
->update_mode_line
)
1005 || (XFASTINT (w
->last_modified
) < MODIFF
1006 && (XFASTINT (w
->last_modified
)
1007 <= XBUFFER (w
->buffer
)->save_modified
)))
1009 struct buffer
*prev
= current_buffer
;
1010 call1 (Vrun_hooks
, Qmenu_bar_update_hook
);
1011 current_buffer
= XBUFFER (w
->buffer
);
1012 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1013 current_buffer
= prev
;
1014 #ifdef USE_X_TOOLKIT
1015 set_frame_menubar (f
, 0);
1016 #endif /* USE_X_TOOLKIT */
1023 /* Redisplay WINDOW and its subwindows and siblings. */
1026 redisplay_windows (window
)
1029 for (; !NILP (window
); window
= XWINDOW (window
)->next
)
1030 redisplay_window (window
, 0);
1033 /* Redisplay window WINDOW and its subwindows. */
1036 redisplay_window (window
, just_this_one
)
1040 register struct window
*w
= XWINDOW (window
);
1041 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1043 register int lpoint
= PT
;
1044 struct buffer
*old
= current_buffer
;
1045 register int width
= window_internal_width (w
) - 1;
1046 register int startp
;
1047 register int hscroll
= XINT (w
->hscroll
);
1048 struct position pos
;
1051 int window_needs_modeline
;
1053 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1055 /* If this is a combination window, do its children; that's all. */
1057 if (!NILP (w
->vchild
))
1059 redisplay_windows (w
->vchild
);
1062 if (!NILP (w
->hchild
))
1064 redisplay_windows (w
->hchild
);
1067 if (NILP (w
->buffer
))
1070 height
= window_internal_height (w
);
1072 if (MINI_WINDOW_P (w
))
1074 if (w
== XWINDOW (minibuf_window
))
1076 if (echo_area_glyphs
)
1077 /* We've already displayed the echo area glyphs, if any. */
1078 goto finish_scroll_bars
;
1082 /* This is a minibuffer, but it's not the currently active one, so
1084 int vpos
= XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f
))->top
);
1087 for (i
= 0; i
< height
; i
++)
1089 get_display_line (f
, vpos
+ i
, 0);
1090 display_string (w
, vpos
+ i
, "", 0, 0, 0, 1, 0, width
);
1093 goto finish_scroll_bars
;
1097 if (update_mode_lines
)
1098 w
->update_mode_line
= Qt
;
1100 /* Otherwise set up data on this window; select its buffer and point value */
1102 current_buffer
= XBUFFER (w
->buffer
);
1105 /* Count number of windows showing the selected buffer. */
1108 && current_buffer
== XBUFFER (XWINDOW (selected_window
)->buffer
))
1111 /* POINT refers normally to the selected window.
1112 For any other window, set up appropriate value. */
1114 if (!EQ (window
, selected_window
))
1116 int new_pt
= marker_position (w
->pointm
);
1120 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1122 else if (new_pt
> (ZV
- 1))
1125 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1127 /* We don't use SET_PT so that the point-motion hooks don't run. */
1128 BUF_PT (current_buffer
) = new_pt
;
1131 /* If window-start is screwed up, choose a new one. */
1132 if (XMARKER (w
->start
)->buffer
!= current_buffer
)
1135 startp
= marker_position (w
->start
);
1137 /* Handle case where place to start displaying has been specified,
1138 unless the specified location is outside the accessible range. */
1139 if (!NILP (w
->force_start
))
1141 /* Forget any recorded base line for line number display. */
1142 w
->base_line_number
= Qnil
;
1143 w
->update_mode_line
= Qt
;
1144 w
->force_start
= Qnil
;
1145 XFASTINT (w
->last_modified
) = 0;
1146 if (startp
< BEGV
) startp
= BEGV
;
1147 if (startp
> ZV
) startp
= ZV
;
1148 try_window (window
, startp
);
1149 if (cursor_vpos
< 0)
1151 /* If point does not appear, move point so it does appear */
1152 pos
= *compute_motion (startp
, 0,
1153 ((EQ (window
, minibuf_window
) && startp
== 1)
1154 ? minibuf_prompt_width
: 0)
1156 (hscroll
? 1 - hscroll
: 0),
1158 - (1 << (SHORTBITS
- 1)),
1159 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1160 BUF_PT (current_buffer
) = pos
.bufpos
;
1161 if (w
!= XWINDOW (selected_window
))
1162 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
1165 if (current_buffer
== old
)
1167 FRAME_CURSOR_X (f
) = max (0, pos
.hpos
) + XFASTINT (w
->left
);
1168 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1170 /* If we are highlighting the region,
1171 then we just changed the region, so redisplay to show it. */
1172 cancel_my_columns (XWINDOW (window
));
1173 if (!NILP (Vtransient_mark_mode
)
1174 && !NILP (current_buffer
->mark_active
))
1175 try_window (window
, startp
);
1180 /* Handle case where text has not changed, only point,
1181 and it has not moved off the frame */
1183 /* This code is not used for minibuffer for the sake of
1184 the case of redisplaying to replace an echo area message;
1185 since in that case the minibuffer contents per se are usually unchanged.
1186 This code is of no real use in the minibuffer since
1187 the handling of this_line_bufpos, etc.,
1188 in redisplay handles the same cases. */
1190 if (XFASTINT (w
->last_modified
) >= MODIFF
1191 && PT
>= startp
&& !clip_changed
1192 && (just_this_one
|| XFASTINT (w
->width
) == FRAME_WIDTH (f
))
1193 /* Can't use this case if highlighting a region. */
1194 && !(!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1195 && NILP (w
->region_showing
)
1196 /* If end pos is out of date, scroll bar and percentage will be wrong */
1197 && INTEGERP (w
->window_end_vpos
)
1198 && XFASTINT (w
->window_end_vpos
) < XFASTINT (w
->height
)
1199 && !EQ (window
, minibuf_window
))
1201 pos
= *compute_motion (startp
, 0, (hscroll
? 1 - hscroll
: 0),
1202 PT
, height
+ 1, 10000, width
, hscroll
,
1203 pos_tab_offset (w
, startp
), w
);
1205 if (pos
.vpos
< height
)
1207 /* Ok, point is still on frame */
1208 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
1210 /* These variables are supposed to be origin 1 */
1211 FRAME_CURSOR_X (f
) = max (0, pos
.hpos
) + XFASTINT (w
->left
);
1212 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1214 /* This doesn't do the trick, because if a window to the right of
1215 this one must be redisplayed, this does nothing because there
1216 is nothing in DesiredFrame yet, and then the other window is
1217 redisplayed, making likes that are empty in this window's columns.
1218 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1219 preserve_my_columns (w);
1223 /* Don't bother trying redisplay with same start;
1224 we already know it will lose */
1226 /* If current starting point was originally the beginning of a line
1227 but no longer is, find a new starting point. */
1228 else if (!NILP (w
->start_at_line_beg
)
1230 || FETCH_CHAR (startp
- 1) == '\n'))
1234 else if (just_this_one
&& !MINI_WINDOW_P (w
)
1236 && XFASTINT (w
->last_modified
)
1237 /* or else vmotion on first line won't work. */
1238 && ! NILP (w
->start_at_line_beg
)
1239 && ! EQ (w
->window_end_valid
, Qnil
)
1240 && do_id
&& !clip_changed
1241 && !blank_end_of_window
1242 && XFASTINT (w
->width
) == FRAME_WIDTH (f
)
1243 /* Can't use this case if highlighting a region. */
1244 && !(!NILP (Vtransient_mark_mode
)
1245 && !NILP (current_buffer
->mark_active
))
1246 && NILP (w
->region_showing
)
1247 && EQ (last_arrow_position
, Voverlay_arrow_position
)
1248 && EQ (last_arrow_string
, Voverlay_arrow_string
)
1249 && (tem
= try_window_id (FRAME_SELECTED_WINDOW (f
)))
1252 /* tem > 0 means success. tem == -1 means choose new start.
1253 tem == -2 means try again with same start,
1254 and nothing but whitespace follows the changed stuff.
1255 tem == 0 means try again with same start. */
1259 else if (startp
>= BEGV
&& startp
<= ZV
1260 /* Avoid starting display at end of buffer! */
1261 && (startp
< ZV
|| startp
== BEGV
1262 || (XFASTINT (w
->last_modified
) >= MODIFF
)))
1264 /* Try to redisplay starting at same place as before */
1265 /* If point has not moved off frame, accept the results */
1266 try_window (window
, startp
);
1267 if (cursor_vpos
>= 0)
1269 if (!just_this_one
|| clip_changed
|| beg_unchanged
< startp
)
1270 /* Forget any recorded base line for line number display. */
1271 w
->base_line_number
= Qnil
;
1275 cancel_my_columns (w
);
1278 XFASTINT (w
->last_modified
) = 0;
1279 w
->update_mode_line
= Qt
;
1281 /* Try to scroll by specified few lines */
1283 if (scroll_step
&& !clip_changed
)
1287 pos
= *vmotion (Z
- XFASTINT (w
->window_end_pos
),
1288 scroll_step
, width
, hscroll
, window
);
1289 if (pos
.vpos
>= height
)
1293 pos
= *vmotion (startp
, PT
< startp
? - scroll_step
: scroll_step
,
1294 width
, hscroll
, window
);
1296 if (PT
>= pos
.bufpos
)
1298 try_window (window
, pos
.bufpos
);
1299 if (cursor_vpos
>= 0)
1301 if (!just_this_one
|| clip_changed
|| beg_unchanged
< startp
)
1302 /* Forget any recorded base line for line number display. */
1303 w
->base_line_number
= Qnil
;
1307 cancel_my_columns (w
);
1312 /* Finally, just choose place to start which centers point */
1315 /* Forget any previously recorded base line for line number display. */
1316 w
->base_line_number
= Qnil
;
1318 pos
= *vmotion (PT
, - (height
/ 2), width
, hscroll
, window
);
1319 try_window (window
, pos
.bufpos
);
1321 startp
= marker_position (w
->start
);
1322 w
->start_at_line_beg
1323 = (startp
== BEGV
|| FETCH_CHAR (startp
- 1) == '\n') ? Qt
: Qnil
;
1326 if ((!NILP (w
->update_mode_line
)
1327 /* If window not full width, must redo its mode line
1328 if the window to its side is being redone */
1329 || (!just_this_one
&& width
< FRAME_WIDTH (f
) - 1)
1330 || INTEGERP (w
->base_line_pos
))
1331 && height
!= XFASTINT (w
->height
))
1332 display_mode_line (w
);
1333 if (! line_number_displayed
1334 && ! BUFFERP (w
->base_line_pos
))
1336 w
->base_line_pos
= Qnil
;
1337 w
->base_line_number
= Qnil
;
1340 /* When we reach a frame's selected window, redo the frame's menu bar. */
1341 if (!NILP (w
->update_mode_line
)
1342 #ifdef USE_X_TOOLKIT
1343 && FRAME_EXTERNAL_MENU_BAR (f
)
1345 && FRAME_MENU_BAR_LINES (f
) > 0
1347 && EQ (FRAME_SELECTED_WINDOW (f
), window
))
1348 display_menu_bar (w
);
1351 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1353 int start
, end
, whole
;
1355 /* Calculate the start and end positions for the current window.
1356 At some point, it would be nice to choose between scrollbars
1357 which reflect the whole buffer size, with special markers
1358 indicating narrowing, and scrollbars which reflect only the
1361 Note that minibuffers sometimes aren't displaying any text. */
1362 if (! MINI_WINDOW_P (w
)
1363 || (w
== XWINDOW (minibuf_window
) && ! echo_area_glyphs
))
1366 start
= startp
- BEGV
;
1367 /* I don't think this is guaranteed to be right. For the
1368 moment, we'll pretend it is. */
1369 end
= (Z
- XINT (w
->window_end_pos
)) - BEGV
;
1371 if (end
< start
) end
= start
;
1372 if (whole
< (end
- start
)) whole
= end
- start
;
1375 start
= end
= whole
= 0;
1377 /* Indicate what this scroll bar ought to be displaying now. */
1378 (*set_vertical_scroll_bar_hook
) (w
, end
- start
, whole
, start
);
1380 /* Note that we actually used the scroll bar attached to this window,
1381 so it shouldn't be deleted at the end of redisplay. */
1382 (*redeem_scroll_bar_hook
) (w
);
1385 BUF_PT (current_buffer
) = opoint
;
1386 current_buffer
= old
;
1387 BUF_PT (current_buffer
) = lpoint
;
1390 /* Do full redisplay on one window, starting at position `pos'. */
1393 try_window (window
, pos
)
1397 register struct window
*w
= XWINDOW (window
);
1398 register int height
= window_internal_height (w
);
1399 register int vpos
= XFASTINT (w
->top
);
1400 register int last_text_vpos
= vpos
;
1401 int tab_offset
= pos_tab_offset (w
, pos
);
1402 FRAME_PTR f
= XFRAME (w
->frame
);
1403 int width
= window_internal_width (w
) - 1;
1404 struct position val
;
1406 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1408 overlay_arrow_seen
= 0;
1409 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
1411 while (--height
>= 0)
1413 val
= *display_text_line (w
, pos
, vpos
, val
.hpos
, tab_offset
);
1414 tab_offset
+= width
;
1415 if (val
.vpos
) tab_offset
= 0;
1417 if (pos
!= val
.bufpos
)
1419 /* Next line, unless prev line ended in end of buffer with no cr */
1420 = vpos
- (val
.vpos
&& (FETCH_CHAR (val
.bufpos
- 1) != '\n'
1421 #ifdef USE_TEXT_PROPERTIES
1422 || ! NILP (Fget_char_property (val
.bufpos
-1,
1430 /* If last line is continued in middle of character,
1431 include the split character in the text considered on the frame */
1432 if (val
.hpos
< (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
1435 /* If bottom just moved off end of frame, change mode line percentage. */
1436 if (XFASTINT (w
->window_end_pos
) == 0
1438 w
->update_mode_line
= Qt
;
1440 /* Say where last char on frame will be, once redisplay is finished. */
1441 XFASTINT (w
->window_end_pos
) = Z
- pos
;
1442 XFASTINT (w
->window_end_vpos
) = last_text_vpos
- XFASTINT (w
->top
);
1443 /* But that is not valid info until redisplay finishes. */
1444 w
->window_end_valid
= Qnil
;
1447 /* Try to redisplay when buffer is modified locally,
1448 computing insert/delete line to preserve text outside
1449 the bounds of the changes.
1450 Return 1 if successful, 0 if if cannot tell what to do,
1451 or -1 to tell caller to find a new window start,
1452 or -2 to tell caller to do normal redisplay with same window start. */
1455 try_window_id (window
)
1459 register struct window
*w
= XWINDOW (window
);
1460 register int height
= window_internal_height (w
);
1461 FRAME_PTR f
= XFRAME (w
->frame
);
1462 int top
= XFASTINT (w
->top
);
1463 int start
= marker_position (w
->start
);
1464 int width
= window_internal_width (w
) - 1;
1465 int hscroll
= XINT (w
->hscroll
);
1466 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1468 register int i
, tem
;
1469 int last_text_vpos
= 0;
1471 int selective
= (INTEGERP (current_buffer
->selective_display
)
1472 ? XINT (current_buffer
->selective_display
)
1473 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1475 struct position val
, bp
, ep
, xp
, pp
;
1476 int scroll_amount
= 0;
1478 int tab_offset
, epto
;
1480 if (GPT
- BEG
< beg_unchanged
)
1481 beg_unchanged
= GPT
- BEG
;
1482 if (Z
- GPT
< end_unchanged
)
1483 end_unchanged
= Z
- GPT
;
1485 if (beg_unchanged
+ BEG
< start
)
1486 return 0; /* Give up if changes go above top of window */
1488 /* Find position before which nothing is changed. */
1489 bp
= *compute_motion (start
, 0, lmargin
,
1490 min (ZV
, beg_unchanged
+ BEG
), height
+ 1, 0,
1491 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1492 if (bp
.vpos
>= height
)
1494 if (PT
< bp
.bufpos
&& !bp
.contin
)
1496 /* All changes are below the frame, and point is on the frame.
1497 We don't need to change the frame at all.
1498 But we need to update window_end_pos to account for
1499 any change in buffer size. */
1500 bp
= *compute_motion (start
, 0, lmargin
,
1502 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1503 XFASTINT (w
->window_end_vpos
) = height
;
1504 XFASTINT (w
->window_end_pos
) = Z
- bp
.bufpos
;
1512 /* Find beginning of that frame line. Must display from there. */
1513 bp
= *vmotion (bp
.bufpos
, 0, width
, hscroll
, window
);
1520 /* If about to start displaying at the beginning of a continuation line,
1521 really start with previous frame line, in case it was not
1522 continued when last redisplayed */
1523 if ((bp
.contin
&& bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0)
1525 /* Likewise if we have to worry about selective display. */
1526 (selective
> 0 && bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0))
1528 bp
= *vmotion (bp
.bufpos
, -1, width
, hscroll
, window
);
1533 if (bp
.contin
&& bp
.hpos
!= lmargin
)
1535 val
.hpos
= bp
.prevhpos
- width
+ lmargin
;
1541 /* Find first visible newline after which no more is changed. */
1542 tem
= find_next_newline (Z
- max (end_unchanged
, Z
- ZV
), 1);
1544 while (tem
< ZV
- 1 && (indented_beyond_p (tem
, selective
)))
1545 tem
= find_next_newline (tem
, 1);
1547 /* Compute the cursor position after that newline. */
1548 ep
= *compute_motion (pos
, vpos
, val
.hpos
, tem
,
1549 height
, - (1 << (SHORTBITS
- 1)),
1550 width
, hscroll
, pos_tab_offset (w
, bp
.bufpos
), w
);
1552 /* If changes reach past the text available on the frame,
1553 just display rest of frame. */
1554 if (ep
.bufpos
> Z
- XFASTINT (w
->window_end_pos
))
1557 stop_vpos
= ep
.vpos
;
1559 /* If no newline before ep, the line ep is on includes some changes
1560 that must be displayed. Make sure we don't stop before it. */
1561 /* Also, if changes reach all the way until ep.bufpos,
1562 it is possible that something was deleted after the
1563 newline before it, so the following line must be redrawn. */
1564 if (stop_vpos
== ep
.vpos
1565 && (ep
.bufpos
== BEGV
1566 || FETCH_CHAR (ep
.bufpos
- 1) != '\n'
1567 || ep
.bufpos
== Z
- end_unchanged
))
1568 stop_vpos
= ep
.vpos
+ 1;
1571 overlay_arrow_seen
= 0;
1573 /* If changes do not reach to bottom of window,
1574 figure out how much to scroll the rest of the window */
1575 if (stop_vpos
< height
)
1577 /* Now determine how far up or down the rest of the window has moved */
1578 epto
= pos_tab_offset (w
, ep
.bufpos
);
1579 xp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
,
1580 Z
- XFASTINT (w
->window_end_pos
),
1581 10000, 0, width
, hscroll
, epto
, w
);
1582 scroll_amount
= xp
.vpos
- XFASTINT (w
->window_end_vpos
);
1584 /* Is everything on frame below the changes whitespace?
1585 If so, no scrolling is really necessary. */
1586 for (i
= ep
.bufpos
; i
< xp
.bufpos
; i
++)
1588 tem
= FETCH_CHAR (i
);
1589 if (tem
!= ' ' && tem
!= '\n' && tem
!= '\t')
1595 XFASTINT (w
->window_end_vpos
) += scroll_amount
;
1597 /* Before doing any scrolling, verify that point will be on frame. */
1598 if (PT
> ep
.bufpos
&& !(PT
<= xp
.bufpos
&& xp
.bufpos
< height
))
1600 if (PT
<= xp
.bufpos
)
1602 pp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
,
1603 PT
, height
, - (1 << (SHORTBITS
- 1)),
1604 width
, hscroll
, epto
, w
);
1608 pp
= *compute_motion (xp
.bufpos
, xp
.vpos
, xp
.hpos
,
1609 PT
, height
, - (1 << (SHORTBITS
- 1)),
1611 pos_tab_offset (w
, xp
.bufpos
), w
);
1613 if (pp
.bufpos
< PT
|| pp
.vpos
== height
)
1615 cursor_vpos
= pp
.vpos
+ top
;
1616 cursor_hpos
= pp
.hpos
+ XFASTINT (w
->left
);
1619 if (stop_vpos
- scroll_amount
>= height
1620 || ep
.bufpos
== xp
.bufpos
)
1622 if (scroll_amount
< 0)
1623 stop_vpos
-= scroll_amount
;
1625 /* In this path, we have altered window_end_vpos
1626 and not left it negative.
1627 We must make sure that, in case display is preempted
1628 before the frame changes to reflect what we do here,
1629 further updates will not come to try_window_id
1630 and assume the frame and window_end_vpos match. */
1631 blank_end_of_window
= 1;
1633 else if (!scroll_amount
)
1635 /* Even if we don't need to scroll, we must adjust the
1636 charstarts of subsequent lines (that we won't redisplay)
1637 according to the amount of text inserted or deleted. */
1638 int oldpos
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
1639 int adjust
= ep
.bufpos
- oldpos
;
1640 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1, adjust
);
1642 else if (bp
.bufpos
== Z
- end_unchanged
)
1644 /* If reprinting everything is nearly as fast as scrolling,
1645 don't bother scrolling. Can happen if lines are short. */
1646 if (scroll_cost (f
, bp
.vpos
+ top
- scroll_amount
,
1647 top
+ height
- max (0, scroll_amount
),
1649 > xp
.bufpos
- bp
.bufpos
- 20)
1650 /* Return "try normal display with same window-start."
1651 Too bad we can't prevent further scroll-thinking. */
1653 /* If pure deletion, scroll up as many lines as possible.
1654 In common case of killing a line, this can save the
1655 following line from being overwritten by scrolling
1656 and therefore having to be redrawn. */
1657 tem
= scroll_frame_lines (f
, bp
.vpos
+ top
- scroll_amount
,
1658 top
+ height
- max (0, scroll_amount
),
1659 scroll_amount
, bp
.bufpos
);
1664 /* scroll_frame_lines did not properly adjust subsequent
1665 lines' charstarts in the case where the text of the
1666 screen line at bp.vpos has changed.
1667 (This can happen in a deletion that ends in mid-line.)
1668 To adjust properly, we need to make things constent at
1670 So do a second adjust to make that happen.
1671 Note that stop_vpos >= ep.vpos, so it is sufficient
1672 to update the charstarts for lines at ep.vpos and below. */
1674 = FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
1675 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1,
1676 ep
.bufpos
- oldstart
);
1679 else if (scroll_amount
)
1681 /* If reprinting everything is nearly as fast as scrolling,
1682 don't bother scrolling. Can happen if lines are short. */
1683 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
1684 overestimate of cost of reprinting, since xp.bufpos
1685 would end up below the bottom of the window. */
1686 if (scroll_cost (f
, ep
.vpos
+ top
- scroll_amount
,
1687 top
+ height
- max (0, scroll_amount
),
1689 > xp
.bufpos
- ep
.bufpos
- 20)
1690 /* Return "try normal display with same window-start."
1691 Too bad we can't prevent further scroll-thinking. */
1693 tem
= scroll_frame_lines (f
, ep
.vpos
+ top
- scroll_amount
,
1694 top
+ height
- max (0, scroll_amount
),
1695 scroll_amount
, ep
.bufpos
);
1696 if (!tem
) stop_vpos
= height
;
1700 /* In any case, do not display past bottom of window */
1701 if (stop_vpos
>= height
)
1707 /* Handle case where pos is before w->start --
1708 can happen if part of line had been clipped and is not clipped now */
1709 if (vpos
== 0 && pos
< marker_position (w
->start
))
1710 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1712 /* Redisplay the lines where the text was changed */
1713 last_text_vpos
= vpos
;
1714 tab_offset
= pos_tab_offset (w
, pos
);
1715 /* If we are starting display in mid-character, correct tab_offset
1716 to account for passing the line that that character really starts in. */
1717 if (val
.hpos
< lmargin
)
1718 tab_offset
+= width
;
1719 while (vpos
< stop_vpos
)
1721 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
1722 tab_offset
+= width
;
1723 if (val
.vpos
) tab_offset
= 0;
1724 if (pos
!= val
.bufpos
)
1726 /* Next line, unless prev line ended in end of buffer with no cr */
1727 = vpos
- (val
.vpos
&& FETCH_CHAR (val
.bufpos
- 1) != '\n');
1731 /* There are two cases:
1732 1) we have displayed down to the bottom of the window
1733 2) we have scrolled lines below stop_vpos by scroll_amount */
1737 /* If last line is continued in middle of character,
1738 include the split character in the text considered on the frame */
1739 if (val
.hpos
< lmargin
)
1741 XFASTINT (w
->window_end_vpos
) = last_text_vpos
;
1742 XFASTINT (w
->window_end_pos
) = Z
- val
.bufpos
;
1745 /* If scrolling made blank lines at window bottom,
1746 redisplay to fill those lines */
1747 if (scroll_amount
< 0)
1749 /* Don't consider these lines for general-purpose scrolling.
1750 That will save time in the scrolling computation. */
1751 FRAME_SCROLL_BOTTOM_VPOS (f
) = xp
.vpos
;
1756 vpos
= height
+ scroll_amount
;
1757 else if (xp
.contin
&& xp
.hpos
!= lmargin
)
1759 val
.hpos
= xp
.prevhpos
- width
+ lmargin
;
1763 blank_end_of_window
= 1;
1764 tab_offset
= pos_tab_offset (w
, pos
);
1765 /* If we are starting display in mid-character, correct tab_offset
1766 to account for passing the line that that character starts in. */
1767 if (val
.hpos
< lmargin
)
1768 tab_offset
+= width
;
1770 while (vpos
< height
)
1772 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
1773 tab_offset
+= width
;
1774 if (val
.vpos
) tab_offset
= 0;
1778 /* Here is a case where display_text_line sets cursor_vpos wrong.
1779 Make it be fixed up, below. */
1785 /* If bottom just moved off end of frame, change mode line percentage. */
1786 if (XFASTINT (w
->window_end_pos
) == 0
1788 w
->update_mode_line
= Qt
;
1790 /* Attempt to adjust end-of-text positions to new bottom line */
1793 delta
= height
- xp
.vpos
;
1795 || (delta
> 0 && xp
.bufpos
<= ZV
)
1796 || (delta
== 0 && xp
.hpos
))
1798 val
= *vmotion (Z
- XFASTINT (w
->window_end_pos
),
1799 delta
, width
, hscroll
, window
);
1800 XFASTINT (w
->window_end_pos
) = Z
- val
.bufpos
;
1801 XFASTINT (w
->window_end_vpos
) += val
.vpos
;
1805 w
->window_end_valid
= Qnil
;
1807 /* If point was not in a line that was displayed, find it */
1808 if (cursor_vpos
< 0)
1810 val
= *compute_motion (start
, 0, lmargin
, PT
, 10000, 10000,
1811 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1812 /* Admit failure if point is off frame now */
1813 if (val
.vpos
>= height
)
1815 for (vpos
= 0; vpos
< height
; vpos
++)
1816 cancel_line (vpos
+ top
, f
);
1819 cursor_vpos
= val
.vpos
+ top
;
1820 cursor_hpos
= val
.hpos
+ XFASTINT (w
->left
);
1823 FRAME_CURSOR_X (f
) = max (0, cursor_hpos
);
1824 FRAME_CURSOR_Y (f
) = cursor_vpos
;
1828 val
= *compute_motion (start
, 0, lmargin
, ZV
,
1829 height
, - (1 << (SHORTBITS
- 1)),
1830 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1831 if (val
.vpos
!= XFASTINT (w
->window_end_vpos
))
1833 if (XFASTINT (w
->window_end_pos
)
1841 /* Mark a section of BUF as modified, but only for the sake of redisplay.
1842 This is useful for recording changes to overlays.
1844 We increment the buffer's modification timestamp and set the
1845 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
1846 as if the region of text between START and END had been modified;
1847 the redisplay code will check this against the windows' timestamps,
1848 and redraw the appropriate area of the buffer.
1850 However, if the buffer is unmodified, we bump the last-save
1851 timestamp as well, so that incrementing the timestamp doesn't fool
1852 Emacs into thinking that the buffer's text has been modified.
1854 Tweaking the timestamps shouldn't hurt the first-modification
1855 timestamps recorded in the undo records; those values aren't
1856 written until just before a real text modification is made, so they
1857 will never catch the timestamp value just before this function gets
1861 redisplay_region (buf
, start
, end
)
1871 start
= end
; end
= temp
;
1874 /* If this is a buffer not in the selected window,
1875 we must do other windows. */
1876 if (buf
!= XBUFFER (XWINDOW (selected_window
)->buffer
))
1877 windows_or_buffers_changed
= 1;
1878 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
1879 else if (buf
!= current_buffer
)
1880 windows_or_buffers_changed
= 1;
1881 /* If multiple windows show this buffer, we must do other windows. */
1882 else if (buffer_shared
> 1)
1883 windows_or_buffers_changed
= 1;
1886 if (unchanged_modified
== MODIFF
)
1888 beg_unchanged
= start
- BEG
;
1889 end_unchanged
= Z
- end
;
1893 if (Z
- end
< end_unchanged
)
1894 end_unchanged
= Z
- end
;
1895 if (start
- BEG
< beg_unchanged
)
1896 beg_unchanged
= start
- BEG
;
1900 /* Increment the buffer's time stamp, but also increment the save
1901 and autosave timestamps, so as not to screw up that timekeeping. */
1902 if (BUF_MODIFF (buf
) == buf
->save_modified
)
1903 buf
->save_modified
++;
1904 if (BUF_MODIFF (buf
) == buf
->auto_save_modified
)
1905 buf
->auto_save_modified
++;
1907 BUF_MODIFF (buf
) ++;
1911 /* Copy LEN glyphs starting address FROM to the rope TO.
1912 But don't actually copy the parts that would come in before S.
1913 Value is TO, advanced past the copied data.
1914 F is the frame we are displaying in. */
1917 copy_part_of_rope (f
, to
, s
, from
, len
, face
)
1919 register GLYPH
*to
; /* Copy to here. */
1920 register GLYPH
*s
; /* Starting point. */
1921 Lisp_Object
*from
; /* Data to copy. */
1923 int face
; /* Face to apply to glyphs which don't specify one. */
1926 register Lisp_Object
*fp
= from
;
1927 /* These cache the results of the last call to compute_glyph_face. */
1929 int last_merged
= 0;
1931 #ifdef HAVE_X_WINDOWS
1932 if (! FRAME_TERMCAP_P (f
))
1935 int glyph
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
1938 if (FAST_GLYPH_FACE (glyph
) == 0)
1939 /* If GLYPH has no face code, use FACE. */
1941 else if (FAST_GLYPH_FACE (glyph
) == last_code
)
1942 /* If it's same as previous glyph, use same result. */
1943 facecode
= last_merged
;
1946 /* Merge this glyph's face and remember the result. */
1947 last_code
= FAST_GLYPH_FACE (glyph
);
1948 last_merged
= facecode
= compute_glyph_face (f
, last_code
, face
);
1952 *to
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), facecode
);
1960 if (to
>= s
) *to
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
1967 /* Correct a glyph by replacing its specified user-level face code
1968 with a displayable computed face code. */
1971 fix_glyph (f
, glyph
, cface
)
1976 #ifdef HAVE_X_WINDOWS
1977 if (! FRAME_TERMCAP_P (f
))
1979 if (FAST_GLYPH_FACE (glyph
) != 0)
1980 cface
= compute_glyph_face (f
, FAST_GLYPH_FACE (glyph
), cface
);
1981 glyph
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), cface
);
1987 /* Display one line of window w, starting at position START in W's buffer.
1988 Display starting at horizontal position HPOS, which is normally zero
1989 or negative. A negative value causes output up to hpos = 0 to be discarded.
1990 This is done for negative hscroll, or when this is a continuation line
1991 and the continuation occurred in the middle of a multi-column character.
1993 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
1995 Display on position VPOS on the frame. (origin 0).
1997 Returns a STRUCT POSITION giving character to start next line with
1998 and where to display it, including a zero or negative hpos.
1999 The vpos field is not really a vpos; it is 1 unless the line is continued */
2001 struct position val_display_text_line
;
2003 static struct position
*
2004 display_text_line (w
, start
, vpos
, hpos
, taboffset
)
2011 register int pos
= start
;
2016 register unsigned char *p
;
2018 register GLYPH
*leftmargin
;
2019 register GLYPH
*p1prev
= 0;
2020 register GLYPH
*p1start
;
2022 FRAME_PTR f
= XFRAME (w
->frame
);
2023 int tab_width
= XINT (current_buffer
->tab_width
);
2024 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
2025 int width
= window_internal_width (w
) - 1;
2026 struct position val
;
2029 int hscroll
= XINT (w
->hscroll
);
2030 int truncate
= (hscroll
2031 || (truncate_partial_width_windows
2032 && XFASTINT (w
->width
) < FRAME_WIDTH (f
))
2033 || !NILP (current_buffer
->truncate_lines
));
2035 /* 1 if we should highlight the region. */
2036 int highlight_region
2037 = !NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
);
2038 int region_beg
, region_end
;
2040 int selective
= (INTEGERP (current_buffer
->selective_display
)
2041 ? XINT (current_buffer
->selective_display
)
2042 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2043 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
2044 register struct Lisp_Vector
*dp
= window_display_table (w
);
2046 Lisp_Object default_invis_vector
[3];
2047 /* Nonzero means display something where there are invisible lines.
2048 The precise value is the number of glyphs to display. */
2050 = (selective
&& dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2051 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
2052 : selective
&& !NILP (current_buffer
->selective_display_ellipses
)
2054 /* This is the sequence of Lisp objects to display
2055 when there are invisible lines. */
2056 Lisp_Object
*invis_vector_contents
2057 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2058 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->contents
2059 : default_invis_vector
);
2061 GLYPH truncator
= (dp
== 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp
))
2062 ? '$' : XINT (DISP_TRUNC_GLYPH (dp
)));
2063 GLYPH continuer
= (dp
== 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp
))
2064 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp
)));
2066 /* The next buffer location at which the face should change, due
2067 to overlays or text property changes. */
2068 int next_face_change
;
2070 #ifdef USE_TEXT_PROPERTIES
2071 /* The next location where the `invisible' property changes */
2075 /* The face we're currently using. */
2076 int current_face
= 0;
2079 XFASTINT (default_invis_vector
[2]) = '.';
2080 default_invis_vector
[0] = default_invis_vector
[1] = default_invis_vector
[2];
2082 hpos
+= XFASTINT (w
->left
);
2083 get_display_line (f
, vpos
, XFASTINT (w
->left
));
2084 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
2086 /* Show where to highlight the region. */
2087 if (highlight_region
&& XMARKER (current_buffer
->mark
)->buffer
!= 0
2088 /* Maybe highlight only in selected window. */
2089 && (highlight_nonselected_windows
2090 || w
== XWINDOW (selected_window
)))
2092 region_beg
= marker_position (current_buffer
->mark
);
2093 if (PT
< region_beg
)
2095 region_end
= region_beg
;
2100 w
->region_showing
= Qt
;
2103 region_beg
= region_end
= -1;
2105 if (MINI_WINDOW_P (w
) && start
== 1
2106 && vpos
== XFASTINT (w
->top
))
2108 if (! NILP (minibuf_prompt
))
2110 minibuf_prompt_width
2111 = (display_string (w
, vpos
, XSTRING (minibuf_prompt
)->data
,
2112 XSTRING (minibuf_prompt
)->size
, hpos
,
2113 (!truncate
? continuer
: truncator
),
2116 hpos
+= minibuf_prompt_width
;
2119 minibuf_prompt_width
= 0;
2122 desired_glyphs
->bufp
[vpos
] = pos
;
2123 p1
= desired_glyphs
->glyphs
[vpos
] + hpos
;
2125 charstart
= desired_glyphs
->charstarts
[vpos
] + hpos
;
2126 /* In case we don't ever write anything into it... */
2127 desired_glyphs
->charstarts
[vpos
][XFASTINT (w
->left
)] = -1;
2129 leftmargin
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
2130 endp
= leftmargin
+ width
;
2132 /* Arrange the overlays nicely for our purposes. Usually, we call
2133 display_text_line on only one line at a time, in which case this
2134 can't really hurt too much, or we call it on lines which appear
2135 one after another in the buffer, in which case all calls to
2136 recenter_overlay_lists but the first will be pretty cheap. */
2137 recenter_overlay_lists (current_buffer
, pos
);
2139 /* Loop generating characters.
2140 Stop at end of buffer, before newline,
2141 if reach or pass continuation column,
2142 or at face change. */
2144 next_face_change
= pos
;
2145 #ifdef USE_TEXT_PROPERTIES
2146 next_invisible
= pos
;
2150 /* Record which glyph starts a character,
2151 and the character position of that character. */
2152 if (p1
>= leftmargin
)
2153 charstart
[p1
- p1start
] = pos
;
2161 /* Did we hit the end of the visible region of the buffer?
2166 /* Did we reach point? Record the cursor location. */
2167 if (pos
== PT
&& cursor_vpos
< 0)
2170 cursor_hpos
= p1
- leftmargin
;
2173 #ifdef USE_TEXT_PROPERTIES
2174 /* if the `invisible' property is set to t, we can skip to
2175 the next property change */
2176 while (pos
== next_invisible
&& pos
< end
)
2178 Lisp_Object position
, limit
, endpos
, prop
, ww
;
2179 XFASTINT (position
) = pos
;
2181 prop
= Fget_char_property (position
, Qinvisible
, ww
);
2182 /* This is just an estimate to give reasonable
2183 performance; nothing should go wrong if it is too small. */
2184 limit
= Fnext_overlay_change (position
);
2185 if (XFASTINT (limit
) > pos
+ 50)
2186 XFASTINT (limit
) = pos
+ 50;
2187 endpos
= Fnext_single_property_change (position
, Qinvisible
,
2188 Fcurrent_buffer (), limit
);
2189 if (INTEGERP (endpos
))
2190 next_invisible
= XINT (endpos
);
2192 next_invisible
= end
;
2195 if (pos
< PT
&& next_invisible
>= PT
)
2198 cursor_hpos
= p1
- leftmargin
;
2200 pos
= next_invisible
;
2207 #ifdef HAVE_X_WINDOWS
2208 /* Did we hit a face change? Figure out what face we should
2209 use now. We also hit this the first time through the
2210 loop, to see what face we should start with. */
2211 if (pos
>= next_face_change
&& FRAME_X_P (f
))
2212 current_face
= compute_char_face (f
, w
, pos
,
2213 region_beg
, region_end
,
2214 &next_face_change
, pos
+ 50, 0);
2219 #ifdef USE_TEXT_PROPERTIES
2220 if (pos
< next_invisible
&& next_invisible
< pause
)
2221 pause
= next_invisible
;
2223 if (pos
< next_face_change
&& next_face_change
< pause
)
2224 pause
= next_face_change
;
2226 /* Wouldn't you hate to read the next line to someone over
2228 if (pos
< PT
&& PT
< pause
)
2230 if (pos
< GPT
&& GPT
< pause
)
2233 p
= &FETCH_CHAR (pos
);
2236 if (c
>= 040 && c
< 0177
2237 && (dp
== 0 || !VECTORP (DISP_CHAR_VECTOR (dp
, c
))))
2239 if (p1
>= leftmargin
)
2240 *p1
= MAKE_GLYPH (f
, c
, current_face
);
2246 while (pos
+ 1 < end
2248 && indented_beyond_p (pos
+ 1, selective
))
2251 pos
= find_next_newline (pos
+ 1, 1);
2252 if (FETCH_CHAR (pos
- 1) == '\n')
2255 if (invis
&& selective_rlen
> 0 && p1
>= leftmargin
)
2257 p1
+= selective_rlen
;
2258 if (p1
- leftmargin
> width
)
2260 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2261 (p1
- p1prev
), current_face
);
2263 #ifdef HAVE_X_WINDOWS
2264 /* Draw the face of the newline character as extending all the
2265 way to the end of the frame line. */
2268 if (p1
< leftmargin
)
2271 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2280 if (p1
>= leftmargin
&& p1
< endp
)
2281 *p1
= MAKE_GLYPH (f
, ' ', current_face
);
2284 while ((p1
- leftmargin
+ taboffset
+ hscroll
- (hscroll
> 0))
2287 else if (c
== Ctl ('M') && selective
== -1)
2289 pos
= find_next_newline (pos
, 1);
2290 if (FETCH_CHAR (pos
- 1) == '\n')
2292 if (selective_rlen
> 0)
2294 p1
+= selective_rlen
;
2295 if (p1
- leftmargin
> width
)
2297 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2298 (p1
- p1prev
), current_face
);
2300 #ifdef HAVE_X_WINDOWS
2301 /* Draw the face of the newline character as extending all the
2302 way to the end of the frame line. */
2305 if (p1
< leftmargin
)
2308 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2313 else if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
2315 p1
= copy_part_of_rope (f
, p1
, leftmargin
,
2316 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
2317 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
2320 else if (c
< 0200 && ctl_arrow
)
2322 if (p1
>= leftmargin
)
2323 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
2324 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
2327 if (p1
>= leftmargin
&& p1
< endp
)
2328 *p1
= MAKE_GLYPH (f
, c
^ 0100, current_face
);
2333 if (p1
>= leftmargin
)
2334 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
2335 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
2338 if (p1
>= leftmargin
&& p1
< endp
)
2339 *p1
= MAKE_GLYPH (f
, (c
>> 6) + '0', current_face
);
2341 if (p1
>= leftmargin
&& p1
< endp
)
2342 *p1
= MAKE_GLYPH (f
, (7 & (c
>> 3)) + '0', current_face
);
2344 if (p1
>= leftmargin
&& p1
< endp
)
2345 *p1
= MAKE_GLYPH (f
, (7 & c
) + '0', current_face
);
2349 /* Do nothing here for a char that's entirely off the left edge. */
2350 if (p1
>= leftmargin
)
2352 /* For all the glyphs occupied by this character, except for the
2353 first, store -1 in charstarts. */
2356 int *p2x
= &charstart
[p1prev
- p1start
];
2357 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2359 /* The window's left column should always
2360 contain a character position.
2361 And don't clobber anything to the left of that. */
2362 if (p1prev
< leftmargin
)
2364 p2x
= charstart
+ (leftmargin
- p1start
);
2368 /* This loop skips over the char p2x initially points to. */
2377 val
.hpos
= - XINT (w
->hscroll
);
2385 /* Store 0 in this charstart line for the positions where
2386 there is no character. But do leave what was recorded
2387 for the character that ended the line. */
2388 /* Add 1 in the endtest to compensate for the fact that ENDP was
2389 made from WIDTH, which is 1 less than the window's actual
2391 i
= p1
- p1start
+ 1;
2392 if (p1
< leftmargin
)
2393 i
+= leftmargin
- p1
;
2394 for (; i
< endp
- p1start
+ 1; i
++)
2397 /* Handle continuation in middle of a character */
2398 /* by backing up over it */
2401 /* Don't back up if we never actually displayed any text.
2402 This occurs when the minibuffer prompt takes up the whole line. */
2405 /* Start the next line with that same character */
2407 /* but at negative hpos, to skip the columns output on this line. */
2408 val
.hpos
+= p1prev
- endp
;
2411 /* Keep in this line everything up to the continuation column. */
2415 /* Finish deciding which character to start the next line on,
2416 and what hpos to start it at.
2417 Also set `lastpos' to the last position which counts as "on this line"
2418 for cursor-positioning. */
2422 if (FETCH_CHAR (pos
) == '\n')
2424 /* If stopped due to a newline, start next line after it */
2426 /* Check again for hidden lines, in case the newline occurred exactly
2427 at the right margin. */
2428 while (pos
< ZV
&& selective
> 0
2429 && indented_beyond_p (pos
, selective
))
2430 pos
= find_next_newline (pos
, 1);
2433 /* Stopped due to right margin of window */
2437 *p1
++ = fix_glyph (f
, truncator
, 0);
2438 /* Truncating => start next line after next newline,
2439 and point is on this line if it is before the newline,
2440 and skip none of first char of next line */
2442 pos
= find_next_newline (pos
, 1);
2443 while (pos
< ZV
&& selective
> 0
2444 && indented_beyond_p (pos
, selective
));
2445 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
2447 lastpos
= pos
- (FETCH_CHAR (pos
- 1) == '\n');
2451 *p1
++ = fix_glyph (f
, continuer
, 0);
2458 /* If point is at eol or in invisible text at eol,
2459 record its frame location now. */
2461 if (start
<= PT
&& PT
<= lastpos
&& cursor_vpos
< 0)
2464 cursor_hpos
= p1
- leftmargin
;
2467 if (cursor_vpos
== vpos
)
2469 if (cursor_hpos
< 0) cursor_hpos
= 0;
2470 if (cursor_hpos
> width
) cursor_hpos
= width
;
2471 cursor_hpos
+= XFASTINT (w
->left
);
2472 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
2474 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2475 FRAME_CURSOR_X (f
) = cursor_hpos
;
2477 if (w
== XWINDOW (selected_window
))
2479 /* Line is not continued and did not start
2480 in middle of character */
2481 if ((hpos
- XFASTINT (w
->left
)
2482 == (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
2485 this_line_bufpos
= start
;
2486 this_line_buffer
= current_buffer
;
2487 this_line_vpos
= cursor_vpos
;
2488 this_line_start_hpos
= hpos
;
2489 this_line_endpos
= Z
- lastpos
;
2492 this_line_bufpos
= 0;
2497 /* If hscroll and line not empty, insert truncation-at-left marker */
2498 if (hscroll
&& lastpos
!= start
)
2500 *leftmargin
= fix_glyph (f
, truncator
, 0);
2501 if (p1
<= leftmargin
)
2502 p1
= leftmargin
+ 1;
2505 if (XFASTINT (w
->width
) + XFASTINT (w
->left
) != FRAME_WIDTH (f
))
2508 if (p1
< leftmargin
) p1
= leftmargin
;
2509 while (p1
< endp
) *p1
++ = SPACEGLYPH
;
2511 /* Don't draw vertical bars if we're using scroll bars. They're
2512 covered up by the scroll bars, and it's distracting to see
2513 them when the scroll bar windows are flickering around to be
2515 *p1
++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2517 : (dp
&& INTEGERP (DISP_BORDER_GLYPH (dp
))
2518 ? DISP_BORDER_GLYPH (dp
)
2521 desired_glyphs
->used
[vpos
] = max (desired_glyphs
->used
[vpos
],
2522 p1
- desired_glyphs
->glyphs
[vpos
]);
2523 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
2525 /* If the start of this line is the overlay arrow-position,
2526 then put the arrow string into the display-line. */
2528 if (MARKERP (Voverlay_arrow_position
)
2529 && current_buffer
== XMARKER (Voverlay_arrow_position
)->buffer
2530 && start
== marker_position (Voverlay_arrow_position
)
2531 && STRINGP (Voverlay_arrow_string
)
2532 && ! overlay_arrow_seen
)
2534 unsigned char *p
= XSTRING (Voverlay_arrow_string
)->data
;
2536 int len
= XSTRING (Voverlay_arrow_string
)->size
;
2541 #ifdef HAVE_X_WINDOWS
2542 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string
)->intervals
))
2544 /* If the arrow string has text props, obey them when displaying. */
2545 for (i
= 0; i
< len
; i
++)
2548 Lisp_Object face
, ilisp
;
2551 XFASTINT (ilisp
) = i
;
2552 face
= Fget_text_property (ilisp
, Qface
, Voverlay_arrow_string
);
2553 newface
= compute_glyph_face_1 (f
, face
, 0);
2554 leftmargin
[i
] = FAST_MAKE_GLYPH (c
, newface
);
2558 #endif /* HAVE_X_WINDOWS */
2560 for (i
= 0; i
< len
; i
++)
2561 leftmargin
[i
] = p
[i
];
2564 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
2565 arrow_end
= (leftmargin
- desired_glyphs
->glyphs
[vpos
]) + len
;
2566 if (desired_glyphs
->used
[vpos
] < arrow_end
)
2567 desired_glyphs
->used
[vpos
] = arrow_end
;
2569 overlay_arrow_seen
= 1;
2573 val_display_text_line
= val
;
2574 return &val_display_text_line
;
2577 /* Redisplay the menu bar in the frame for window W. */
2580 display_menu_bar (w
)
2583 Lisp_Object items
, tail
;
2584 register int vpos
= 0;
2585 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2586 int maxendcol
= FRAME_WIDTH (f
);
2590 #ifndef USE_X_TOOLKIT
2591 if (FRAME_MENU_BAR_LINES (f
) <= 0)
2594 get_display_line (f
, vpos
, 0);
2596 items
= FRAME_MENU_BAR_ITEMS (f
);
2597 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 3)
2599 Lisp_Object pos
, string
;
2600 string
= XVECTOR (items
)->contents
[i
+ 1];
2604 XFASTINT (XVECTOR (items
)->contents
[i
+ 2]) = hpos
;
2606 if (hpos
< maxendcol
)
2607 hpos
= display_string (XWINDOW (FRAME_ROOT_WINDOW (f
)), vpos
,
2608 XSTRING (string
)->data
,
2609 XSTRING (string
)->size
,
2610 hpos
, 0, 0, hpos
, maxendcol
);
2611 /* Put a gap of 3 spaces between items. */
2612 if (hpos
< maxendcol
)
2614 int hpos1
= hpos
+ 3;
2615 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0,
2616 min (hpos1
, maxendcol
), maxendcol
);
2620 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
2621 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
2623 /* Fill out the line with spaces. */
2624 if (maxendcol
> hpos
)
2625 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0, maxendcol
, maxendcol
);
2627 /* Clear the rest of the lines allocated to the menu bar. */
2629 while (vpos
< FRAME_MENU_BAR_LINES (f
))
2630 get_display_line (f
, vpos
++, 0);
2631 #endif /* not USE_X_TOOLKIT */
2634 /* Display the mode line for window w */
2637 display_mode_line (w
)
2640 register int vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
2641 register int left
= XFASTINT (w
->left
);
2642 register int right
= XFASTINT (w
->width
) + left
;
2643 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2645 line_number_displayed
= 0;
2647 get_display_line (f
, vpos
, left
);
2648 display_mode_element (w
, vpos
, left
, 0, right
, right
,
2649 current_buffer
->mode_line_format
);
2650 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
2652 /* Make the mode line inverse video if the entire line
2653 is made of mode lines.
2654 I.e. if this window is full width,
2655 or if it is the child of a full width window
2656 (which implies that that window is split side-by-side
2657 and the rest of this line is mode lines of the sibling windows). */
2658 if (XFASTINT (w
->width
) == FRAME_WIDTH (f
)
2659 || XFASTINT (XWINDOW (w
->parent
)->width
) == FRAME_WIDTH (f
))
2660 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
2661 #ifdef HAVE_X_WINDOWS
2662 else if (! FRAME_TERMCAP_P (f
))
2664 /* For a partial width window, explicitly set face of each glyph. */
2666 GLYPH
*ptr
= FRAME_DESIRED_GLYPHS (f
)->glyphs
[vpos
];
2667 for (i
= left
; i
< right
; ++i
)
2668 ptr
[i
] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr
[i
]), 1);
2673 /* Contribute ELT to the mode line for window W.
2674 How it translates into text depends on its data type.
2676 VPOS is the position of the mode line being displayed.
2678 HPOS is the position (absolute on frame) where this element's text
2679 should start. The output is truncated automatically at the right
2682 DEPTH is the depth in recursion. It is used to prevent
2683 infinite recursion here.
2685 MINENDCOL is the hpos before which the element may not end.
2686 The element is padded at the right with spaces if nec
2687 to reach this column.
2689 MAXENDCOL is the hpos past which this element may not extend.
2690 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
2691 (This is necessary to make nested padding and truncation work.)
2693 Returns the hpos of the end of the text generated by ELT.
2694 The next element will receive that value as its HPOS arg,
2695 so as to concatenate the elements. */
2698 display_mode_element (w
, vpos
, hpos
, depth
, minendcol
, maxendcol
, elt
)
2700 register int vpos
, hpos
;
2703 register int maxendcol
;
2704 register Lisp_Object elt
;
2712 #ifdef SWITCH_ENUM_BUG
2713 switch ((int) XTYPE (elt
))
2715 switch (XTYPE (elt
))
2720 /* A string: output it and check for %-constructs within it. */
2721 register unsigned char c
;
2722 register unsigned char *this = XSTRING (elt
)->data
;
2724 while (hpos
< maxendcol
&& *this)
2726 unsigned char *last
= this;
2727 while ((c
= *this++) != '\0' && c
!= '%')
2729 if (this - 1 != last
)
2731 register int lim
= --this - last
+ hpos
;
2732 if (frame_title_ptr
)
2733 hpos
= store_frame_title (last
, hpos
, min (lim
, maxendcol
));
2735 hpos
= display_string (w
, vpos
, last
, -1, hpos
, 0, 1,
2736 hpos
, min (lim
, maxendcol
));
2740 register int spec_width
= 0;
2742 /* We can't allow -ve args due to the "%-" construct */
2743 /* Argument specifies minwidth but not maxwidth
2744 (maxwidth can be specified by
2745 (<negative-number> . <stuff>) mode-line elements) */
2747 while ((c
= *this++) >= '0' && c
<= '9')
2749 spec_width
= spec_width
* 10 + (c
- '0');
2753 if (spec_width
> maxendcol
)
2754 spec_width
= maxendcol
;
2757 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
2758 spec_width
, maxendcol
,
2759 Vglobal_mode_string
);
2762 char *spec
= decode_mode_spec (w
, c
, maxendcol
- hpos
);
2763 if (frame_title_ptr
)
2764 hpos
= store_frame_title (spec
, spec_width
, maxendcol
);
2766 hpos
= display_string (w
, vpos
, spec
, -1,
2768 spec_width
, maxendcol
);
2776 /* A symbol: process the value of the symbol recursively
2777 as if it appeared here directly. Avoid error if symbol void.
2778 Special case: if value of symbol is a string, output the string
2781 register Lisp_Object tem
;
2782 tem
= Fboundp (elt
);
2785 tem
= Fsymbol_value (elt
);
2786 /* If value is a string, output that string literally:
2787 don't check for % within it. */
2790 if (frame_title_ptr
)
2791 hpos
= store_frame_title (XSTRING (tem
)->data
,
2792 minendcol
, maxendcol
);
2794 hpos
= display_string (w
, vpos
, XSTRING (tem
)->data
,
2795 XSTRING (tem
)->size
,
2796 hpos
, 0, 1, minendcol
, maxendcol
);
2798 /* Give up right away for nil or t. */
2799 else if (!EQ (tem
, elt
))
2800 { elt
= tem
; goto tail_recurse
; }
2807 register Lisp_Object car
, tem
;
2809 /* A cons cell: three distinct cases.
2810 If first element is a string or a cons, process all the elements
2811 and effectively concatenate them.
2812 If first element is a negative number, truncate displaying cdr to
2813 at most that many characters. If positive, pad (with spaces)
2814 to at least that many characters.
2815 If first element is a symbol, process the cadr or caddr recursively
2816 according to whether the symbol's value is non-nil or nil. */
2817 car
= XCONS (elt
)->car
;
2820 tem
= Fboundp (car
);
2821 elt
= XCONS (elt
)->cdr
;
2824 /* elt is now the cdr, and we know it is a cons cell.
2825 Use its car if CAR has a non-nil value. */
2828 tem
= Fsymbol_value (car
);
2830 { elt
= XCONS (elt
)->car
; goto tail_recurse
; }
2832 /* Symbol's value is nil (or symbol is unbound)
2833 Get the cddr of the original list
2834 and if possible find the caddr and use that. */
2835 elt
= XCONS (elt
)->cdr
;
2838 else if (!CONSP (elt
))
2840 elt
= XCONS (elt
)->car
;
2843 else if (INTEGERP (car
))
2845 register int lim
= XINT (car
);
2846 elt
= XCONS (elt
)->cdr
;
2848 /* Negative int means reduce maximum width.
2849 DO NOT change MINENDCOL here!
2850 (20 -10 . foo) should truncate foo to 10 col
2851 and then pad to 20. */
2852 maxendcol
= min (maxendcol
, hpos
- lim
);
2855 /* Padding specified. Don't let it be more than
2858 if (lim
> maxendcol
)
2860 /* If that's more padding than already wanted, queue it.
2861 But don't reduce padding already specified even if
2862 that is beyond the current truncation point. */
2863 if (lim
> minendcol
)
2868 else if (STRINGP (car
) || CONSP (car
))
2870 register int limit
= 50;
2871 /* LIMIT is to protect against circular lists. */
2872 while (CONSP (elt
) && --limit
> 0
2873 && hpos
< maxendcol
)
2875 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
2878 elt
= XCONS (elt
)->cdr
;
2886 if (frame_title_ptr
)
2887 hpos
= store_frame_title ("*invalid*", minendcol
, maxendcol
);
2889 hpos
= display_string (w
, vpos
, "*invalid*", -1, hpos
, 0, 1,
2890 minendcol
, maxendcol
);
2894 if (minendcol
> hpos
)
2895 if (frame_title_ptr
)
2896 hpos
= store_frame_title ("", minendcol
, maxendcol
);
2898 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 1, minendcol
, maxendcol
);
2902 /* Return a string for the output of a mode line %-spec for window W,
2903 generated by character C and width MAXWIDTH. */
2905 static char lots_of_dashes
[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
2908 decode_mode_spec (w
, c
, maxwidth
)
2911 register int maxwidth
;
2914 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2915 char *decode_mode_spec_buf
= (char *) FRAME_TEMP_GLYPHS (f
)->total_contents
;
2916 struct buffer
*b
= XBUFFER (w
->buffer
);
2919 if (maxwidth
> FRAME_WIDTH (f
))
2920 maxwidth
= FRAME_WIDTH (f
);
2927 if (maxwidth
>= 3 && XSTRING (obj
)->size
> maxwidth
)
2929 bcopy (XSTRING (obj
)->data
, decode_mode_spec_buf
, maxwidth
- 1);
2930 decode_mode_spec_buf
[maxwidth
- 1] = '\\';
2931 decode_mode_spec_buf
[maxwidth
] = '\0';
2932 return decode_mode_spec_buf
;
2942 else if (STRINGP (obj
) && XSTRING (obj
)->size
> maxwidth
)
2944 bcopy ("...", decode_mode_spec_buf
, 3);
2945 bcopy (XSTRING (obj
)->data
+ XSTRING (obj
)->size
- maxwidth
+ 3,
2946 decode_mode_spec_buf
+ 3, maxwidth
- 3);
2947 return decode_mode_spec_buf
;
2954 int startpos
= marker_position (w
->start
);
2955 int line
, linepos
, topline
;
2958 int height
= XFASTINT (w
->height
);
2960 /* If we decided that this buffer isn't suitable for line numbers,
2961 don't forget that too fast. */
2962 if (EQ (w
->base_line_pos
, w
->buffer
))
2965 /* If the buffer is very big, don't waste time. */
2966 if (BUF_ZV (b
) - BUF_BEGV (b
) > line_number_display_limit
)
2968 w
->base_line_pos
= Qnil
;
2969 w
->base_line_number
= Qnil
;
2973 if (!NILP (w
->base_line_number
)
2974 && !NILP (w
->base_line_pos
)
2975 && XFASTINT (w
->base_line_pos
) <= marker_position (w
->start
))
2977 line
= XFASTINT (w
->base_line_number
);
2978 linepos
= XFASTINT (w
->base_line_pos
);
2983 linepos
= BUF_BEGV (b
);
2986 /* Count lines from base line to window start position. */
2987 nlines
= display_count_lines (linepos
, startpos
, startpos
, &junk
);
2989 topline
= nlines
+ line
;
2991 /* Determine a new base line, if the old one is too close
2992 or too far away, or if we did not have one.
2993 "Too close" means it's plausible a scroll-down would
2995 if (startpos
== BUF_BEGV (b
))
2997 XFASTINT (w
->base_line_number
) = topline
;
2998 XFASTINT (w
->base_line_pos
) = BUF_BEGV (b
);
3000 else if (nlines
< height
+ 25 || nlines
> height
* 3 + 50
3001 || linepos
== BUF_BEGV (b
))
3003 int limit
= BUF_BEGV (b
);
3005 int distance
= (height
* 2 + 30) * 200;
3007 if (startpos
- distance
> limit
)
3008 limit
= startpos
- distance
;
3010 nlines
= display_count_lines (startpos
, limit
,
3013 /* If we couldn't find the lines we wanted within
3015 give up on line numbers for this window. */
3016 if (position
== startpos
- distance
)
3018 w
->base_line_pos
= w
->buffer
;
3019 w
->base_line_number
= Qnil
;
3023 XFASTINT (w
->base_line_number
) = topline
- nlines
;
3024 XFASTINT (w
->base_line_pos
) = position
;
3027 /* Now count lines from the start pos to point. */
3028 nlines
= display_count_lines (startpos
, PT
, PT
, &junk
);
3030 /* Record that we did display the line number. */
3031 line_number_displayed
= 1;
3033 /* Make the string to show. */
3034 sprintf (decode_mode_spec_buf
, "%d", topline
+ nlines
);
3035 return decode_mode_spec_buf
;
3044 if (BUF_BEGV (b
) > BUF_BEG (b
) || BUF_ZV (b
) < BUF_Z (b
))
3049 if (!NILP (b
->read_only
))
3051 if (BUF_MODIFF (b
) > b
->save_modified
)
3056 /* This differs from %* only for a modified read-only buffer. */
3057 if (BUF_MODIFF (b
) > b
->save_modified
)
3059 if (!NILP (b
->read_only
))
3064 /* This differs from %* in ignoring read-only-ness. */
3065 if (BUF_MODIFF (b
) > b
->save_modified
)
3070 /* status of process */
3071 obj
= Fget_buffer_process (w
->buffer
);
3073 return "no process";
3075 obj
= Fsymbol_name (Fprocess_status (obj
));
3079 case 't': /* indicate TEXT or BINARY */
3080 #ifdef MODE_LINE_BINARY_TEXT
3081 return MODE_LINE_BINARY_TEXT (b
);
3088 int pos
= marker_position (w
->start
);
3089 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3091 if (XFASTINT (w
->window_end_pos
) <= BUF_Z (b
) - BUF_ZV (b
))
3093 if (pos
<= BUF_BEGV (b
))
3098 else if (pos
<= BUF_BEGV (b
))
3102 total
= ((pos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3103 /* We can't normally display a 3-digit number,
3104 so get us a 2-digit number that is close. */
3107 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3108 return decode_mode_spec_buf
;
3112 /* Display percentage of size above the bottom of the screen. */
3115 int toppos
= marker_position (w
->start
);
3116 int botpos
= BUF_Z (b
) - XFASTINT (w
->window_end_pos
);
3117 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3119 if (botpos
>= BUF_ZV (b
))
3121 if (toppos
<= BUF_BEGV (b
))
3128 total
= ((botpos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3129 /* We can't normally display a 3-digit number,
3130 so get us a 2-digit number that is close. */
3133 if (toppos
<= BUF_BEGV (b
))
3134 sprintf (decode_mode_spec_buf
, "Top%2d%%", total
);
3136 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3137 return decode_mode_spec_buf
;
3149 if (command_loop_level
> 5)
3151 p
= decode_mode_spec_buf
;
3152 for (i
= 0; i
< command_loop_level
; i
++)
3155 return decode_mode_spec_buf
;
3163 if (command_loop_level
> 5)
3165 p
= decode_mode_spec_buf
;
3166 for (i
= 0; i
< command_loop_level
; i
++)
3169 return decode_mode_spec_buf
;
3177 if (maxwidth
< sizeof (lots_of_dashes
))
3178 return lots_of_dashes
;
3181 for (p
= decode_mode_spec_buf
, i
= maxwidth
; i
> 0; i
--)
3185 return decode_mode_spec_buf
;
3190 return (char *) XSTRING (obj
)->data
;
3195 /* Search for COUNT instances of a line boundary, which means either a
3196 newline or (if selective display enabled) a carriage return.
3197 Start at START. If COUNT is negative, search backwards.
3199 If we find COUNT instances, set *SHORTAGE to zero, and return the
3200 position after the COUNTth match. Note that for reverse motion
3201 this is not the same as the usual convention for Emacs motion commands.
3203 If we don't find COUNT instances before reaching the end of the
3204 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3205 the number of line boundaries left unfound, and return the end of the
3206 buffer we bumped up against. */
3209 display_scan_buffer (start
, count
, shortage
)
3210 int *shortage
, start
;
3213 int limit
= ((count
> 0) ? ZV
- 1 : BEGV
);
3214 int direction
= ((count
> 0) ? 1 : -1);
3216 register unsigned char *cursor
;
3217 unsigned char *base
;
3219 register int ceiling
;
3220 register unsigned char *ceiling_addr
;
3222 /* If we are not in selective display mode,
3223 check only for newlines. */
3224 if (! (!NILP (current_buffer
->selective_display
)
3225 && !INTEGERP (current_buffer
->selective_display
)))
3226 return scan_buffer ('\n', start
, count
, shortage
, 0);
3228 /* The code that follows is like scan_buffer
3229 but checks for either newline or carriage return. */
3235 while (start
!= limit
+ 1)
3237 ceiling
= BUFFER_CEILING_OF (start
);
3238 ceiling
= min (limit
, ceiling
);
3239 ceiling_addr
= &FETCH_CHAR (ceiling
) + 1;
3240 base
= (cursor
= &FETCH_CHAR (start
));
3243 while (*cursor
!= '\n' && *cursor
!= 015 && ++cursor
!= ceiling_addr
)
3245 if (cursor
!= ceiling_addr
)
3250 return (start
+ cursor
- base
+ 1);
3253 if (++cursor
== ceiling_addr
)
3259 start
+= cursor
- base
;
3263 start
--; /* first character we scan */
3264 while (start
> limit
- 1)
3265 { /* we WILL scan under start */
3266 ceiling
= BUFFER_FLOOR_OF (start
);
3267 ceiling
= max (limit
, ceiling
);
3268 ceiling_addr
= &FETCH_CHAR (ceiling
) - 1;
3269 base
= (cursor
= &FETCH_CHAR (start
));
3273 while (--cursor
!= ceiling_addr
3274 && *cursor
!= '\n' && *cursor
!= 015)
3276 if (cursor
!= ceiling_addr
)
3281 return (start
+ cursor
- base
+ 1);
3287 start
+= cursor
- base
;
3292 *shortage
= count
* direction
;
3293 return (start
+ ((direction
== 1 ? 0 : 1)));
3296 /* Count up to N lines starting from FROM.
3297 But don't go beyond LIMIT.
3298 Return the number of lines thus found (always positive).
3299 Store the position after what was found into *POS_PTR. */
3302 display_count_lines (from
, limit
, n
, pos_ptr
)
3315 *pos_ptr
= display_scan_buffer (from
, n
, &shortage
);
3321 /* When scanning backwards, scan_buffer stops *after* the last newline
3322 it finds, but does count it. Compensate for that. */
3323 return - n
- shortage
- (*pos_ptr
!= limit
);
3324 return n
- shortage
;
3327 /* Display STRING on one line of window W, starting at HPOS.
3328 Display at position VPOS. Caller should have done get_display_line.
3329 If VPOS == -1, display it as the current frame's title.
3330 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3332 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3334 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3335 MAXCOL is the last column ok to end at. Truncate here.
3336 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3337 Both count from the left edge of the frame, as does HPOS.
3338 The right edge of W is an implicit maximum.
3339 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3341 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3342 at the place where the current window ends in this line
3343 and not display anything beyond there. Otherwise, only MAXCOL
3344 controls where to stop output.
3346 Returns ending hpos. */
3349 display_string (w
, vpos
, string
, length
, hpos
, truncate
,
3350 obey_window_width
, mincol
, maxcol
)
3352 unsigned char *string
;
3356 int obey_window_width
;
3361 int hscroll
= XINT (w
->hscroll
);
3362 int tab_width
= XINT (XBUFFER (w
->buffer
)->tab_width
);
3363 register GLYPH
*start
;
3364 register GLYPH
*end
;
3365 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3366 struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
3367 GLYPH
*p1start
= desired_glyphs
->glyphs
[vpos
] + hpos
;
3368 int window_width
= XFASTINT (w
->width
);
3370 /* Use the standard display table, not the window's display table.
3371 We don't want the mode line in rot13. */
3372 register struct Lisp_Vector
*dp
= 0;
3375 if (VECTORP (Vstandard_display_table
)
3376 && XVECTOR (Vstandard_display_table
)->size
== DISP_TABLE_SIZE
)
3377 dp
= XVECTOR (Vstandard_display_table
);
3379 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
3382 start
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
3384 if (obey_window_width
)
3386 end
= start
+ window_width
- (truncate
!= 0);
3388 if ((window_width
+ XFASTINT (w
->left
)) != FRAME_WIDTH (f
))
3390 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3394 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
3402 if (! obey_window_width
3403 || (maxcol
>= 0 && end
- desired_glyphs
->glyphs
[vpos
] > maxcol
))
3404 end
= desired_glyphs
->glyphs
[vpos
] + maxcol
;
3406 /* Store 0 in charstart for these columns. */
3407 for (i
= (hpos
>= 0 ? hpos
: 0); i
< end
- p1start
+ hpos
; i
++)
3408 desired_glyphs
->charstarts
[vpos
][i
] = 0;
3410 if (maxcol
>= 0 && mincol
> maxcol
)
3418 /* Specified length. */
3421 /* Unspecified length (null-terminated string). */
3425 if (c
>= 040 && c
< 0177
3426 && (dp
== 0 || !VECTORP (DISP_CHAR_VECTOR (dp
, c
))))
3436 if (p1
>= start
&& p1
< end
)
3440 while ((p1
- start
+ hscroll
- (hscroll
> 0)) % tab_width
);
3442 else if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
3444 p1
= copy_part_of_rope (f
, p1
, start
,
3445 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
3446 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
3449 else if (c
< 0200 && ! NILP (buffer_defaults
.ctl_arrow
))
3452 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
3453 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
3456 if (p1
>= start
&& p1
< end
)
3463 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
3464 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
3467 if (p1
>= start
&& p1
< end
)
3468 *p1
= (c
>> 6) + '0';
3470 if (p1
>= start
&& p1
< end
)
3471 *p1
= (7 & (c
>> 3)) + '0';
3473 if (p1
>= start
&& p1
< end
)
3474 *p1
= (7 & c
) + '0';
3479 if (c
&& length
> 0)
3482 if (truncate
) *p1
++ = fix_glyph (f
, truncate
, 0);
3484 else if (mincol
>= 0)
3486 end
= desired_glyphs
->glyphs
[vpos
] + mincol
;
3492 register int len
= p1
- desired_glyphs
->glyphs
[vpos
];
3494 if (len
> desired_glyphs
->used
[vpos
])
3495 desired_glyphs
->used
[vpos
] = len
;
3496 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
3505 staticpro (&Qmenu_bar_update_hook
);
3506 Qmenu_bar_update_hook
= intern ("menu-bar-update-hook");
3508 staticpro (&last_arrow_position
);
3509 staticpro (&last_arrow_string
);
3510 last_arrow_position
= Qnil
;
3511 last_arrow_string
= Qnil
;
3513 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
,
3514 "String (or mode line construct) included (normally) in `mode-line-format'.");
3515 Vglobal_mode_string
= Qnil
;
3517 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
,
3518 "Marker for where to display an arrow on top of the buffer text.\n\
3519 This must be the beginning of a line in order to work.\n\
3520 See also `overlay-arrow-string'.");
3521 Voverlay_arrow_position
= Qnil
;
3523 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
,
3524 "String to display as an arrow. See also `overlay-arrow-position'.");
3525 Voverlay_arrow_string
= Qnil
;
3527 DEFVAR_INT ("scroll-step", &scroll_step
,
3528 "*The number of lines to try scrolling a window by when point moves out.\n\
3529 If that fails to bring point back on frame, point is centered instead.\n\
3530 If this is zero, point is always centered after it moves off frame.");
3532 DEFVAR_INT ("debug-end-pos", &debug_end_pos
, "Don't ask");
3534 DEFVAR_BOOL ("truncate-partial-width-windows",
3535 &truncate_partial_width_windows
,
3536 "*Non-nil means truncate lines in all windows less than full frame wide.");
3537 truncate_partial_width_windows
= 1;
3539 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
,
3540 "*Non-nil means use inverse video for the mode line.");
3541 mode_line_inverse_video
= 1;
3543 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit
,
3544 "*Maximum buffer size for which line number should be displayed.");
3545 line_number_display_limit
= 1000000;
3547 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
,
3548 "*Non-nil means highlight region even in nonselected windows.");
3549 highlight_nonselected_windows
= 1;
3551 DEFVAR_BOOL ("multiple-frames", &multiple_frames
,
3552 "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\
3553 Not guaranteed to be accurate except while parsing frame-title-format.");
3555 DEFVAR_LISP ("frame-title-format", &Vframe_title_format
,
3556 "Template for displaying the titlebar of visible frames.\n\
3557 \(Assuming the window manager supports this feature.)\n\
3558 This variable has the same structure as `mode-line-format' (which see),\n\
3559 and is used only on frames for which no explicit name has been set\n\
3560 \(see `modify-frame-parameters').");
3561 DEFVAR_LISP ("icon-title-format", &Vicon_title_format
,
3562 "Template for displaying the titlebar of an iconified frame.\n\
3563 \(Assuming the window manager supports this feature.)\n\
3564 This variable has the same structure as `mode-line-format' (which see),\n\
3565 and is used only on frames for which no explicit name has been set\n\
3566 \(see `modify-frame-parameters').");
3568 = Vframe_title_format
3569 = Fcons (intern ("multiple-frames"),
3570 Fcons (build_string ("%b"),
3571 Fcons (Fcons (build_string (""),
3572 Fcons (intern ("invocation-name"),
3573 Fcons (build_string ("@"),
3574 Fcons (intern ("system-name"),
3579 /* initialize the window system */
3582 Lisp_Object root_window
;
3583 #ifndef COMPILER_REGISTER_BUG
3585 #endif /* COMPILER_REGISTER_BUG */
3586 struct window
*mini_w
;
3588 this_line_bufpos
= 0;
3590 mini_w
= XWINDOW (minibuf_window
);
3591 root_window
= FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w
)));
3593 echo_area_glyphs
= 0;
3594 previous_echo_glyphs
= 0;
3596 if (!noninteractive
)
3598 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (root_window
)));
3599 XFASTINT (XWINDOW (root_window
)->top
) = 0;
3600 set_window_height (root_window
, FRAME_HEIGHT (f
) - 1, 0);
3601 XFASTINT (mini_w
->top
) = FRAME_HEIGHT (f
) - 1;
3602 set_window_height (minibuf_window
, 1, 0);
3604 XFASTINT (XWINDOW (root_window
)->width
) = FRAME_WIDTH (f
);
3605 XFASTINT (mini_w
->width
) = FRAME_WIDTH (f
);