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 XSETFASTINT (w
->last_point
, BUF_PT (b
));
861 XSETFASTINT (w
->last_point_x
, FRAME_CURSOR_X (selected_frame
));
862 XSETFASTINT (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 XSETFASTINT (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 XSETFASTINT (w
->last_modified
,
937 !flag
? 0 : BUF_MODIFF (XBUFFER (w
->buffer
)));
939 /* Record if we are showing a region, so can make sure to
940 update it fully at next redisplay. */
941 w
->region_showing
= (!NILP (Vtransient_mark_mode
)
942 && !NILP (XBUFFER (w
->buffer
)->mark_active
)
943 ? Fmarker_position (XBUFFER (w
->buffer
)->mark
)
947 w
->window_end_valid
= w
->buffer
;
948 w
->update_mode_line
= Qnil
;
950 if (!NILP (w
->vchild
))
951 mark_window_display_accurate (w
->vchild
, flag
);
952 if (!NILP (w
->hchild
))
953 mark_window_display_accurate (w
->hchild
, flag
);
958 last_arrow_position
= Voverlay_arrow_position
;
959 last_arrow_string
= Voverlay_arrow_string
;
963 /* t is unequal to any useful value of Voverlay_arrow_... */
964 last_arrow_position
= Qt
;
965 last_arrow_string
= Qt
;
969 /* Update the menu bar item list for frame F.
970 This has to be done before we start to fill in any display lines,
971 because it can call eval. */
977 struct buffer
*old
= current_buffer
;
979 register struct window
*w
;
980 window
= FRAME_SELECTED_WINDOW (f
);
981 w
= XWINDOW (window
);
983 if (update_mode_lines
)
984 w
->update_mode_line
= Qt
;
988 FRAME_EXTERNAL_MENU_BAR (f
)
990 FRAME_MENU_BAR_LINES (f
) > 0
994 /* If the user has switched buffers or windows, we need to
995 recompute to reflect the new bindings. But we'll
996 recompute when update_mode_lines is set too; that means
997 that people can use force-mode-line-update to request
998 that the menu bar be recomputed. The adverse effect on
999 the rest of the redisplay algorithm is about the same as
1000 windows_or_buffers_changed anyway. */
1001 if (windows_or_buffers_changed
1002 || !NILP (w
->update_mode_line
)
1003 || (XFASTINT (w
->last_modified
) < MODIFF
1004 && (XFASTINT (w
->last_modified
)
1005 <= XBUFFER (w
->buffer
)->save_modified
)))
1007 struct buffer
*prev
= current_buffer
;
1008 call1 (Vrun_hooks
, Qmenu_bar_update_hook
);
1009 current_buffer
= XBUFFER (w
->buffer
);
1010 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1011 current_buffer
= prev
;
1012 #ifdef USE_X_TOOLKIT
1013 set_frame_menubar (f
, 0);
1014 #endif /* USE_X_TOOLKIT */
1021 /* Redisplay WINDOW and its subwindows and siblings. */
1024 redisplay_windows (window
)
1027 for (; !NILP (window
); window
= XWINDOW (window
)->next
)
1028 redisplay_window (window
, 0);
1031 /* Redisplay window WINDOW and its subwindows. */
1034 redisplay_window (window
, just_this_one
)
1038 register struct window
*w
= XWINDOW (window
);
1039 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
1041 register int lpoint
= PT
;
1042 struct buffer
*old
= current_buffer
;
1043 register int width
= window_internal_width (w
) - 1;
1044 register int startp
;
1045 register int hscroll
= XINT (w
->hscroll
);
1046 struct position pos
;
1049 int window_needs_modeline
;
1051 if (FRAME_HEIGHT (f
) == 0) abort (); /* Some bug zeros some core */
1053 /* If this is a combination window, do its children; that's all. */
1055 if (!NILP (w
->vchild
))
1057 redisplay_windows (w
->vchild
);
1060 if (!NILP (w
->hchild
))
1062 redisplay_windows (w
->hchild
);
1065 if (NILP (w
->buffer
))
1068 height
= window_internal_height (w
);
1070 if (MINI_WINDOW_P (w
))
1072 if (w
== XWINDOW (minibuf_window
))
1074 if (echo_area_glyphs
)
1075 /* We've already displayed the echo area glyphs, if any. */
1076 goto finish_scroll_bars
;
1080 /* This is a minibuffer, but it's not the currently active one, so
1082 int vpos
= XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f
))->top
);
1085 for (i
= 0; i
< height
; i
++)
1087 get_display_line (f
, vpos
+ i
, 0);
1088 display_string (w
, vpos
+ i
, "", 0, 0, 0, 1, 0, width
);
1091 goto finish_scroll_bars
;
1095 if (update_mode_lines
)
1096 w
->update_mode_line
= Qt
;
1098 /* Otherwise set up data on this window; select its buffer and point value */
1100 current_buffer
= XBUFFER (w
->buffer
);
1103 /* Count number of windows showing the selected buffer. */
1106 && current_buffer
== XBUFFER (XWINDOW (selected_window
)->buffer
))
1109 /* POINT refers normally to the selected window.
1110 For any other window, set up appropriate value. */
1112 if (!EQ (window
, selected_window
))
1114 int new_pt
= marker_position (w
->pointm
);
1118 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1120 else if (new_pt
> (ZV
- 1))
1123 Fset_marker (w
->pointm
, make_number (new_pt
), Qnil
);
1125 /* We don't use SET_PT so that the point-motion hooks don't run. */
1126 BUF_PT (current_buffer
) = new_pt
;
1129 /* If any of the character widths specified in the display table
1130 have changed, invalidate the width run cache. It's true that this
1131 may be a bit late to catch such changes, but the rest of
1132 redisplay goes (non-fatally) haywire when the display table is
1133 changed, so why should we worry about doing any better? */
1134 if (current_buffer
->width_run_cache
)
1136 struct Lisp_Vector
*disptab
= buffer_display_table ();
1138 if (! disptab_matches_widthtab (disptab
,
1139 XVECTOR (current_buffer
->width_table
)))
1141 invalidate_region_cache (current_buffer
,
1142 current_buffer
->width_run_cache
,
1144 recompute_width_table (current_buffer
, disptab
);
1148 /* If window-start is screwed up, choose a new one. */
1149 if (XMARKER (w
->start
)->buffer
!= current_buffer
)
1152 startp
= marker_position (w
->start
);
1154 /* Handle case where place to start displaying has been specified,
1155 unless the specified location is outside the accessible range. */
1156 if (!NILP (w
->force_start
))
1158 /* Forget any recorded base line for line number display. */
1159 w
->base_line_number
= Qnil
;
1160 w
->update_mode_line
= Qt
;
1161 w
->force_start
= Qnil
;
1162 XSETFASTINT (w
->last_modified
, 0);
1163 if (startp
< BEGV
) startp
= BEGV
;
1164 if (startp
> ZV
) startp
= ZV
;
1165 try_window (window
, startp
);
1166 if (cursor_vpos
< 0)
1168 /* If point does not appear, move point so it does appear */
1169 pos
= *compute_motion (startp
, 0,
1170 ((EQ (window
, minibuf_window
) && startp
== 1)
1171 ? minibuf_prompt_width
: 0)
1173 (hscroll
? 1 - hscroll
: 0),
1175 - (1 << (SHORTBITS
- 1)),
1176 width
, hscroll
, pos_tab_offset (w
, startp
), w
);
1177 BUF_PT (current_buffer
) = pos
.bufpos
;
1178 if (w
!= XWINDOW (selected_window
))
1179 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
1182 if (current_buffer
== old
)
1184 FRAME_CURSOR_X (f
) = max (0, pos
.hpos
) + XFASTINT (w
->left
);
1185 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1187 /* If we are highlighting the region,
1188 then we just changed the region, so redisplay to show it. */
1189 if (!NILP (Vtransient_mark_mode
)
1190 && !NILP (current_buffer
->mark_active
))
1192 cancel_my_columns (XWINDOW (window
));
1193 try_window (window
, startp
);
1199 /* Handle case where text has not changed, only point,
1200 and it has not moved off the frame */
1202 /* This code is not used for minibuffer for the sake of
1203 the case of redisplaying to replace an echo area message;
1204 since in that case the minibuffer contents per se are usually unchanged.
1205 This code is of no real use in the minibuffer since
1206 the handling of this_line_bufpos, etc.,
1207 in redisplay handles the same cases. */
1209 if (XFASTINT (w
->last_modified
) >= MODIFF
1210 && PT
>= startp
&& !clip_changed
1211 && (just_this_one
|| XFASTINT (w
->width
) == FRAME_WIDTH (f
))
1212 /* Can't use this case if highlighting a region. */
1213 && !(!NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
))
1214 && NILP (w
->region_showing
)
1215 /* If end pos is out of date, scroll bar and percentage will be wrong */
1216 && INTEGERP (w
->window_end_vpos
)
1217 && XFASTINT (w
->window_end_vpos
) < XFASTINT (w
->height
)
1218 && !EQ (window
, minibuf_window
))
1220 pos
= *compute_motion (startp
, 0, (hscroll
? 1 - hscroll
: 0),
1221 PT
, height
+ 1, 10000, width
, hscroll
,
1222 pos_tab_offset (w
, startp
), w
);
1224 if (pos
.vpos
< height
)
1226 /* Ok, point is still on frame */
1227 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
1229 /* These variables are supposed to be origin 1 */
1230 FRAME_CURSOR_X (f
) = max (0, pos
.hpos
) + XFASTINT (w
->left
);
1231 FRAME_CURSOR_Y (f
) = pos
.vpos
+ XFASTINT (w
->top
);
1233 /* This doesn't do the trick, because if a window to the right of
1234 this one must be redisplayed, this does nothing because there
1235 is nothing in DesiredFrame yet, and then the other window is
1236 redisplayed, making likes that are empty in this window's columns.
1237 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1238 preserve_my_columns (w);
1242 /* Don't bother trying redisplay with same start;
1243 we already know it will lose */
1245 /* If current starting point was originally the beginning of a line
1246 but no longer is, find a new starting point. */
1247 else if (!NILP (w
->start_at_line_beg
)
1249 || FETCH_CHAR (startp
- 1) == '\n'))
1253 else if (just_this_one
&& !MINI_WINDOW_P (w
)
1255 && XFASTINT (w
->last_modified
)
1256 /* or else vmotion on first line won't work. */
1257 && ! NILP (w
->start_at_line_beg
)
1258 && ! EQ (w
->window_end_valid
, Qnil
)
1259 && do_id
&& !clip_changed
1260 && !blank_end_of_window
1261 && XFASTINT (w
->width
) == FRAME_WIDTH (f
)
1262 /* Can't use this case if highlighting a region. */
1263 && !(!NILP (Vtransient_mark_mode
)
1264 && !NILP (current_buffer
->mark_active
))
1265 && NILP (w
->region_showing
)
1266 && EQ (last_arrow_position
, Voverlay_arrow_position
)
1267 && EQ (last_arrow_string
, Voverlay_arrow_string
)
1268 && (tem
= try_window_id (FRAME_SELECTED_WINDOW (f
)))
1271 /* tem > 0 means success. tem == -1 means choose new start.
1272 tem == -2 means try again with same start,
1273 and nothing but whitespace follows the changed stuff.
1274 tem == 0 means try again with same start. */
1278 else if (startp
>= BEGV
&& startp
<= ZV
1279 /* Avoid starting display at end of buffer! */
1280 && (startp
< ZV
|| startp
== BEGV
1281 || (XFASTINT (w
->last_modified
) >= MODIFF
)))
1283 /* Try to redisplay starting at same place as before */
1284 /* If point has not moved off frame, accept the results */
1285 try_window (window
, startp
);
1286 if (cursor_vpos
>= 0)
1288 if (!just_this_one
|| clip_changed
|| beg_unchanged
< startp
)
1289 /* Forget any recorded base line for line number display. */
1290 w
->base_line_number
= Qnil
;
1294 cancel_my_columns (w
);
1297 XSETFASTINT (w
->last_modified
, 0);
1298 w
->update_mode_line
= Qt
;
1300 /* Try to scroll by specified few lines */
1302 if (scroll_step
&& !clip_changed
)
1306 pos
= *vmotion (Z
- XFASTINT (w
->window_end_pos
),
1307 scroll_step
, width
, hscroll
, window
);
1308 if (pos
.vpos
>= height
)
1312 pos
= *vmotion (startp
, PT
< startp
? - scroll_step
: scroll_step
,
1313 width
, hscroll
, window
);
1315 if (PT
>= pos
.bufpos
)
1317 try_window (window
, pos
.bufpos
);
1318 if (cursor_vpos
>= 0)
1320 if (!just_this_one
|| clip_changed
|| beg_unchanged
< startp
)
1321 /* Forget any recorded base line for line number display. */
1322 w
->base_line_number
= Qnil
;
1326 cancel_my_columns (w
);
1331 /* Finally, just choose place to start which centers point */
1334 /* Forget any previously recorded base line for line number display. */
1335 w
->base_line_number
= Qnil
;
1337 pos
= *vmotion (PT
, - (height
/ 2), width
, hscroll
, window
);
1338 try_window (window
, pos
.bufpos
);
1340 startp
= marker_position (w
->start
);
1341 w
->start_at_line_beg
1342 = (startp
== BEGV
|| FETCH_CHAR (startp
- 1) == '\n') ? Qt
: Qnil
;
1345 if ((!NILP (w
->update_mode_line
)
1346 /* If window not full width, must redo its mode line
1347 if the window to its side is being redone */
1348 || (!just_this_one
&& width
< FRAME_WIDTH (f
) - 1)
1349 || INTEGERP (w
->base_line_pos
))
1350 && height
!= XFASTINT (w
->height
))
1351 display_mode_line (w
);
1352 if (! line_number_displayed
1353 && ! BUFFERP (w
->base_line_pos
))
1355 w
->base_line_pos
= Qnil
;
1356 w
->base_line_number
= Qnil
;
1359 /* When we reach a frame's selected window, redo the frame's menu bar. */
1360 if (!NILP (w
->update_mode_line
)
1361 #ifdef USE_X_TOOLKIT
1362 && FRAME_EXTERNAL_MENU_BAR (f
)
1364 && FRAME_MENU_BAR_LINES (f
) > 0
1366 && EQ (FRAME_SELECTED_WINDOW (f
), window
))
1367 display_menu_bar (w
);
1370 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
1372 int start
, end
, whole
;
1374 /* Calculate the start and end positions for the current window.
1375 At some point, it would be nice to choose between scrollbars
1376 which reflect the whole buffer size, with special markers
1377 indicating narrowing, and scrollbars which reflect only the
1380 Note that minibuffers sometimes aren't displaying any text. */
1381 if (! MINI_WINDOW_P (w
)
1382 || (w
== XWINDOW (minibuf_window
) && ! echo_area_glyphs
))
1385 start
= startp
- BEGV
;
1386 /* I don't think this is guaranteed to be right. For the
1387 moment, we'll pretend it is. */
1388 end
= (Z
- XINT (w
->window_end_pos
)) - BEGV
;
1390 if (end
< start
) end
= start
;
1391 if (whole
< (end
- start
)) whole
= end
- start
;
1394 start
= end
= whole
= 0;
1396 /* Indicate what this scroll bar ought to be displaying now. */
1397 (*set_vertical_scroll_bar_hook
) (w
, end
- start
, whole
, start
);
1399 /* Note that we actually used the scroll bar attached to this window,
1400 so it shouldn't be deleted at the end of redisplay. */
1401 (*redeem_scroll_bar_hook
) (w
);
1404 BUF_PT (current_buffer
) = opoint
;
1405 current_buffer
= old
;
1406 BUF_PT (current_buffer
) = lpoint
;
1409 /* Do full redisplay on one window, starting at position `pos'. */
1412 try_window (window
, pos
)
1416 register struct window
*w
= XWINDOW (window
);
1417 register int height
= window_internal_height (w
);
1418 register int vpos
= XFASTINT (w
->top
);
1419 register int last_text_vpos
= vpos
;
1420 int tab_offset
= pos_tab_offset (w
, pos
);
1421 FRAME_PTR f
= XFRAME (w
->frame
);
1422 int width
= window_internal_width (w
) - 1;
1423 struct position val
;
1425 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1427 overlay_arrow_seen
= 0;
1428 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
1430 while (--height
>= 0)
1432 val
= *display_text_line (w
, pos
, vpos
, val
.hpos
, tab_offset
);
1433 tab_offset
+= width
;
1434 if (val
.vpos
) tab_offset
= 0;
1436 if (pos
!= val
.bufpos
)
1438 /* Next line, unless prev line ended in end of buffer with no cr */
1439 = vpos
- (val
.vpos
&& (FETCH_CHAR (val
.bufpos
- 1) != '\n'
1440 #ifdef USE_TEXT_PROPERTIES
1441 || ! NILP (Fget_char_property (val
.bufpos
-1,
1449 /* If last line is continued in middle of character,
1450 include the split character in the text considered on the frame */
1451 if (val
.hpos
< (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
1454 /* If bottom just moved off end of frame, change mode line percentage. */
1455 if (XFASTINT (w
->window_end_pos
) == 0
1457 w
->update_mode_line
= Qt
;
1459 /* Say where last char on frame will be, once redisplay is finished. */
1460 XSETFASTINT (w
->window_end_pos
, Z
- pos
);
1461 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
- XFASTINT (w
->top
));
1462 /* But that is not valid info until redisplay finishes. */
1463 w
->window_end_valid
= Qnil
;
1466 /* Try to redisplay when buffer is modified locally,
1467 computing insert/delete line to preserve text outside
1468 the bounds of the changes.
1469 Return 1 if successful, 0 if if cannot tell what to do,
1470 or -1 to tell caller to find a new window start,
1471 or -2 to tell caller to do normal redisplay with same window start. */
1474 try_window_id (window
)
1478 register struct window
*w
= XWINDOW (window
);
1479 register int height
= window_internal_height (w
);
1480 FRAME_PTR f
= XFRAME (w
->frame
);
1481 int top
= XFASTINT (w
->top
);
1482 int start
= marker_position (w
->start
);
1483 int width
= window_internal_width (w
) - 1;
1484 int hscroll
= XINT (w
->hscroll
);
1485 int lmargin
= hscroll
> 0 ? 1 - hscroll
: 0;
1487 register int i
, tem
;
1488 int last_text_vpos
= 0;
1490 int selective
= (INTEGERP (current_buffer
->selective_display
)
1491 ? XINT (current_buffer
->selective_display
)
1492 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
1494 struct position val
, bp
, ep
, xp
, pp
;
1495 int scroll_amount
= 0;
1497 int tab_offset
, epto
;
1499 if (GPT
- BEG
< beg_unchanged
)
1500 beg_unchanged
= GPT
- BEG
;
1501 if (Z
- GPT
< end_unchanged
)
1502 end_unchanged
= Z
- GPT
;
1504 if (beg_unchanged
+ BEG
< start
)
1505 return 0; /* Give up if changes go above top of window */
1507 /* Find position before which nothing is changed. */
1508 bp
= *compute_motion (start
, 0, lmargin
,
1509 min (ZV
, beg_unchanged
+ BEG
), height
+ 1, 0,
1510 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1511 if (bp
.vpos
>= height
)
1513 if (PT
< bp
.bufpos
&& !bp
.contin
)
1515 /* All changes are below the frame, and point is on the frame.
1516 We don't need to change the frame at all.
1517 But we need to update window_end_pos to account for
1518 any change in buffer size. */
1519 bp
= *compute_motion (start
, 0, lmargin
,
1521 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1522 XSETFASTINT (w
->window_end_vpos
, height
);
1523 XSETFASTINT (w
->window_end_pos
, Z
- bp
.bufpos
);
1531 /* Find beginning of that frame line. Must display from there. */
1532 bp
= *vmotion (bp
.bufpos
, 0, width
, hscroll
, window
);
1539 /* If about to start displaying at the beginning of a continuation line,
1540 really start with previous frame line, in case it was not
1541 continued when last redisplayed */
1542 if ((bp
.contin
&& bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0)
1544 /* Likewise if we have to worry about selective display. */
1545 (selective
> 0 && bp
.bufpos
- 1 == beg_unchanged
&& vpos
> 0))
1547 bp
= *vmotion (bp
.bufpos
, -1, width
, hscroll
, window
);
1552 if (bp
.contin
&& bp
.hpos
!= lmargin
)
1554 val
.hpos
= bp
.prevhpos
- width
+ lmargin
;
1560 /* Find first visible newline after which no more is changed. */
1561 tem
= find_next_newline (Z
- max (end_unchanged
, Z
- ZV
), 1);
1563 while (tem
< ZV
- 1 && (indented_beyond_p (tem
, selective
)))
1564 tem
= find_next_newline (tem
, 1);
1566 /* Compute the cursor position after that newline. */
1567 ep
= *compute_motion (pos
, vpos
, val
.hpos
, tem
,
1568 height
, - (1 << (SHORTBITS
- 1)),
1569 width
, hscroll
, pos_tab_offset (w
, bp
.bufpos
), w
);
1571 /* If changes reach past the text available on the frame,
1572 just display rest of frame. */
1573 if (ep
.bufpos
> Z
- XFASTINT (w
->window_end_pos
))
1576 stop_vpos
= ep
.vpos
;
1578 /* If no newline before ep, the line ep is on includes some changes
1579 that must be displayed. Make sure we don't stop before it. */
1580 /* Also, if changes reach all the way until ep.bufpos,
1581 it is possible that something was deleted after the
1582 newline before it, so the following line must be redrawn. */
1583 if (stop_vpos
== ep
.vpos
1584 && (ep
.bufpos
== BEGV
1585 || FETCH_CHAR (ep
.bufpos
- 1) != '\n'
1586 || ep
.bufpos
== Z
- end_unchanged
))
1587 stop_vpos
= ep
.vpos
+ 1;
1590 overlay_arrow_seen
= 0;
1592 /* If changes do not reach to bottom of window,
1593 figure out how much to scroll the rest of the window */
1594 if (stop_vpos
< height
)
1596 /* Now determine how far up or down the rest of the window has moved */
1597 epto
= pos_tab_offset (w
, ep
.bufpos
);
1598 xp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
,
1599 Z
- XFASTINT (w
->window_end_pos
),
1600 10000, 0, width
, hscroll
, epto
, w
);
1601 scroll_amount
= xp
.vpos
- XFASTINT (w
->window_end_vpos
);
1603 /* Is everything on frame below the changes whitespace?
1604 If so, no scrolling is really necessary. */
1605 for (i
= ep
.bufpos
; i
< xp
.bufpos
; i
++)
1607 tem
= FETCH_CHAR (i
);
1608 if (tem
!= ' ' && tem
!= '\n' && tem
!= '\t')
1614 XSETFASTINT (w
->window_end_vpos
,
1615 XFASTINT (w
->window_end_vpos
) + scroll_amount
);
1617 /* Before doing any scrolling, verify that point will be on frame. */
1618 if (PT
> ep
.bufpos
&& !(PT
<= xp
.bufpos
&& xp
.bufpos
< height
))
1620 if (PT
<= xp
.bufpos
)
1622 pp
= *compute_motion (ep
.bufpos
, ep
.vpos
, ep
.hpos
,
1623 PT
, height
, - (1 << (SHORTBITS
- 1)),
1624 width
, hscroll
, epto
, w
);
1628 pp
= *compute_motion (xp
.bufpos
, xp
.vpos
, xp
.hpos
,
1629 PT
, height
, - (1 << (SHORTBITS
- 1)),
1631 pos_tab_offset (w
, xp
.bufpos
), w
);
1633 if (pp
.bufpos
< PT
|| pp
.vpos
== height
)
1635 cursor_vpos
= pp
.vpos
+ top
;
1636 cursor_hpos
= pp
.hpos
+ XFASTINT (w
->left
);
1639 if (stop_vpos
- scroll_amount
>= height
1640 || ep
.bufpos
== xp
.bufpos
)
1642 if (scroll_amount
< 0)
1643 stop_vpos
-= scroll_amount
;
1645 /* In this path, we have altered window_end_vpos
1646 and not left it negative.
1647 We must make sure that, in case display is preempted
1648 before the frame changes to reflect what we do here,
1649 further updates will not come to try_window_id
1650 and assume the frame and window_end_vpos match. */
1651 blank_end_of_window
= 1;
1653 else if (!scroll_amount
)
1655 /* Even if we don't need to scroll, we must adjust the
1656 charstarts of subsequent lines (that we won't redisplay)
1657 according to the amount of text inserted or deleted. */
1658 int oldpos
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
1659 int adjust
= ep
.bufpos
- oldpos
;
1660 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1, adjust
);
1662 else if (bp
.bufpos
== Z
- end_unchanged
)
1664 /* If reprinting everything is nearly as fast as scrolling,
1665 don't bother scrolling. Can happen if lines are short. */
1666 if (scroll_cost (f
, bp
.vpos
+ top
- scroll_amount
,
1667 top
+ height
- max (0, scroll_amount
),
1669 > xp
.bufpos
- bp
.bufpos
- 20)
1670 /* Return "try normal display with same window-start."
1671 Too bad we can't prevent further scroll-thinking. */
1673 /* If pure deletion, scroll up as many lines as possible.
1674 In common case of killing a line, this can save the
1675 following line from being overwritten by scrolling
1676 and therefore having to be redrawn. */
1677 tem
= scroll_frame_lines (f
, bp
.vpos
+ top
- scroll_amount
,
1678 top
+ height
- max (0, scroll_amount
),
1679 scroll_amount
, bp
.bufpos
);
1684 /* scroll_frame_lines did not properly adjust subsequent
1685 lines' charstarts in the case where the text of the
1686 screen line at bp.vpos has changed.
1687 (This can happen in a deletion that ends in mid-line.)
1688 To adjust properly, we need to make things constent at
1690 So do a second adjust to make that happen.
1691 Note that stop_vpos >= ep.vpos, so it is sufficient
1692 to update the charstarts for lines at ep.vpos and below. */
1694 = FRAME_CURRENT_GLYPHS (f
)->charstarts
[ep
.vpos
+ top
][0];
1695 adjust_window_charstarts (w
, ep
.vpos
+ top
- 1,
1696 ep
.bufpos
- oldstart
);
1699 else if (scroll_amount
)
1701 /* If reprinting everything is nearly as fast as scrolling,
1702 don't bother scrolling. Can happen if lines are short. */
1703 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
1704 overestimate of cost of reprinting, since xp.bufpos
1705 would end up below the bottom of the window. */
1706 if (scroll_cost (f
, ep
.vpos
+ top
- scroll_amount
,
1707 top
+ height
- max (0, scroll_amount
),
1709 > xp
.bufpos
- ep
.bufpos
- 20)
1710 /* Return "try normal display with same window-start."
1711 Too bad we can't prevent further scroll-thinking. */
1713 tem
= scroll_frame_lines (f
, ep
.vpos
+ top
- scroll_amount
,
1714 top
+ height
- max (0, scroll_amount
),
1715 scroll_amount
, ep
.bufpos
);
1716 if (!tem
) stop_vpos
= height
;
1720 /* In any case, do not display past bottom of window */
1721 if (stop_vpos
>= height
)
1727 /* Handle case where pos is before w->start --
1728 can happen if part of line had been clipped and is not clipped now */
1729 if (vpos
== 0 && pos
< marker_position (w
->start
))
1730 Fset_marker (w
->start
, make_number (pos
), Qnil
);
1732 /* Redisplay the lines where the text was changed */
1733 last_text_vpos
= vpos
;
1734 tab_offset
= pos_tab_offset (w
, pos
);
1735 /* If we are starting display in mid-character, correct tab_offset
1736 to account for passing the line that that character really starts in. */
1737 if (val
.hpos
< lmargin
)
1738 tab_offset
+= width
;
1739 while (vpos
< stop_vpos
)
1741 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
1742 tab_offset
+= width
;
1743 if (val
.vpos
) tab_offset
= 0;
1744 if (pos
!= val
.bufpos
)
1746 /* Next line, unless prev line ended in end of buffer with no cr */
1747 = vpos
- (val
.vpos
&& FETCH_CHAR (val
.bufpos
- 1) != '\n');
1751 /* There are two cases:
1752 1) we have displayed down to the bottom of the window
1753 2) we have scrolled lines below stop_vpos by scroll_amount */
1757 /* If last line is continued in middle of character,
1758 include the split character in the text considered on the frame */
1759 if (val
.hpos
< lmargin
)
1761 XSETFASTINT (w
->window_end_vpos
, last_text_vpos
);
1762 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
1765 /* If scrolling made blank lines at window bottom,
1766 redisplay to fill those lines */
1767 if (scroll_amount
< 0)
1769 /* Don't consider these lines for general-purpose scrolling.
1770 That will save time in the scrolling computation. */
1771 FRAME_SCROLL_BOTTOM_VPOS (f
) = xp
.vpos
;
1776 vpos
= height
+ scroll_amount
;
1777 else if (xp
.contin
&& xp
.hpos
!= lmargin
)
1779 val
.hpos
= xp
.prevhpos
- width
+ lmargin
;
1783 blank_end_of_window
= 1;
1784 tab_offset
= pos_tab_offset (w
, pos
);
1785 /* If we are starting display in mid-character, correct tab_offset
1786 to account for passing the line that that character starts in. */
1787 if (val
.hpos
< lmargin
)
1788 tab_offset
+= width
;
1790 while (vpos
< height
)
1792 val
= *display_text_line (w
, pos
, top
+ vpos
++, val
.hpos
, tab_offset
);
1793 tab_offset
+= width
;
1794 if (val
.vpos
) tab_offset
= 0;
1798 /* Here is a case where display_text_line sets cursor_vpos wrong.
1799 Make it be fixed up, below. */
1805 /* If bottom just moved off end of frame, change mode line percentage. */
1806 if (XFASTINT (w
->window_end_pos
) == 0
1808 w
->update_mode_line
= Qt
;
1810 /* Attempt to adjust end-of-text positions to new bottom line */
1813 delta
= height
- xp
.vpos
;
1815 || (delta
> 0 && xp
.bufpos
<= ZV
)
1816 || (delta
== 0 && xp
.hpos
))
1818 val
= *vmotion (Z
- XFASTINT (w
->window_end_pos
),
1819 delta
, width
, hscroll
, window
);
1820 XSETFASTINT (w
->window_end_pos
, Z
- val
.bufpos
);
1821 XSETFASTINT (w
->window_end_vpos
,
1822 XFASTINT (w
->window_end_vpos
) + val
.vpos
);
1826 w
->window_end_valid
= Qnil
;
1828 /* If point was not in a line that was displayed, find it */
1829 if (cursor_vpos
< 0)
1831 val
= *compute_motion (start
, 0, lmargin
, PT
, 10000, 10000,
1832 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1833 /* Admit failure if point is off frame now */
1834 if (val
.vpos
>= height
)
1836 for (vpos
= 0; vpos
< height
; vpos
++)
1837 cancel_line (vpos
+ top
, f
);
1840 cursor_vpos
= val
.vpos
+ top
;
1841 cursor_hpos
= val
.hpos
+ XFASTINT (w
->left
);
1844 FRAME_CURSOR_X (f
) = max (0, cursor_hpos
);
1845 FRAME_CURSOR_Y (f
) = cursor_vpos
;
1849 val
= *compute_motion (start
, 0, lmargin
, ZV
,
1850 height
, - (1 << (SHORTBITS
- 1)),
1851 width
, hscroll
, pos_tab_offset (w
, start
), w
);
1852 if (val
.vpos
!= XFASTINT (w
->window_end_vpos
))
1854 if (XFASTINT (w
->window_end_pos
)
1862 /* Mark a section of BUF as modified, but only for the sake of redisplay.
1863 This is useful for recording changes to overlays.
1865 We increment the buffer's modification timestamp and set the
1866 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
1867 as if the region of text between START and END had been modified;
1868 the redisplay code will check this against the windows' timestamps,
1869 and redraw the appropriate area of the buffer.
1871 However, if the buffer is unmodified, we bump the last-save
1872 timestamp as well, so that incrementing the timestamp doesn't fool
1873 Emacs into thinking that the buffer's text has been modified.
1875 Tweaking the timestamps shouldn't hurt the first-modification
1876 timestamps recorded in the undo records; those values aren't
1877 written until just before a real text modification is made, so they
1878 will never catch the timestamp value just before this function gets
1882 redisplay_region (buf
, start
, end
)
1892 start
= end
; end
= temp
;
1895 /* If this is a buffer not in the selected window,
1896 we must do other windows. */
1897 if (buf
!= XBUFFER (XWINDOW (selected_window
)->buffer
))
1898 windows_or_buffers_changed
= 1;
1899 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
1900 else if (buf
!= current_buffer
)
1901 windows_or_buffers_changed
= 1;
1902 /* If multiple windows show this buffer, we must do other windows. */
1903 else if (buffer_shared
> 1)
1904 windows_or_buffers_changed
= 1;
1907 if (unchanged_modified
== MODIFF
)
1909 beg_unchanged
= start
- BEG
;
1910 end_unchanged
= Z
- end
;
1914 if (Z
- end
< end_unchanged
)
1915 end_unchanged
= Z
- end
;
1916 if (start
- BEG
< beg_unchanged
)
1917 beg_unchanged
= start
- BEG
;
1921 /* Increment the buffer's time stamp, but also increment the save
1922 and autosave timestamps, so as not to screw up that timekeeping. */
1923 if (BUF_MODIFF (buf
) == buf
->save_modified
)
1924 buf
->save_modified
++;
1925 if (BUF_MODIFF (buf
) == buf
->auto_save_modified
)
1926 buf
->auto_save_modified
++;
1928 BUF_MODIFF (buf
) ++;
1932 /* Copy LEN glyphs starting address FROM to the rope TO.
1933 But don't actually copy the parts that would come in before S.
1934 Value is TO, advanced past the copied data.
1935 F is the frame we are displaying in. */
1938 copy_part_of_rope (f
, to
, s
, from
, len
, face
)
1940 register GLYPH
*to
; /* Copy to here. */
1941 register GLYPH
*s
; /* Starting point. */
1942 Lisp_Object
*from
; /* Data to copy. */
1944 int face
; /* Face to apply to glyphs which don't specify one. */
1947 register Lisp_Object
*fp
= from
;
1948 /* These cache the results of the last call to compute_glyph_face. */
1950 int last_merged
= 0;
1952 #ifdef HAVE_X_WINDOWS
1953 if (! FRAME_TERMCAP_P (f
))
1956 int glyph
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
1959 if (FAST_GLYPH_FACE (glyph
) == 0)
1960 /* If GLYPH has no face code, use FACE. */
1962 else if (FAST_GLYPH_FACE (glyph
) == last_code
)
1963 /* If it's same as previous glyph, use same result. */
1964 facecode
= last_merged
;
1967 /* Merge this glyph's face and remember the result. */
1968 last_code
= FAST_GLYPH_FACE (glyph
);
1969 last_merged
= facecode
= compute_glyph_face (f
, last_code
, face
);
1973 *to
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), facecode
);
1981 if (to
>= s
) *to
= (INTEGERP (*fp
) ? XFASTINT (*fp
) : 0);
1988 /* Correct a glyph by replacing its specified user-level face code
1989 with a displayable computed face code. */
1992 fix_glyph (f
, glyph
, cface
)
1997 #ifdef HAVE_X_WINDOWS
1998 if (! FRAME_TERMCAP_P (f
))
2000 if (FAST_GLYPH_FACE (glyph
) != 0)
2001 cface
= compute_glyph_face (f
, FAST_GLYPH_FACE (glyph
), cface
);
2002 glyph
= FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph
), cface
);
2008 /* Display one line of window W, starting at position START in W's buffer.
2010 Display starting at horizontal position HPOS, expressed relative to
2011 W's left edge. In situations where the text at START shouldn't
2012 start at the left margin (i.e. when the window is hscrolled, or
2013 we're continuing a line which left off in the midst of a
2014 multi-column character), HPOS should be negative; we throw away
2015 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2018 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2020 Display on position VPOS on the frame. It is origin 0, relative to
2021 the top of the frame, not W.
2023 Returns a STRUCT POSITION giving character to start next line with
2024 and where to display it, including a zero or negative hpos.
2025 The vpos field is not really a vpos; it is 1 unless the line is continued */
2027 struct position val_display_text_line
;
2029 static struct position
*
2030 display_text_line (w
, start
, vpos
, hpos
, taboffset
)
2037 register int pos
= start
;
2042 register unsigned char *p
;
2044 register GLYPH
*leftmargin
;
2045 register GLYPH
*p1prev
= 0;
2046 register GLYPH
*p1start
;
2048 FRAME_PTR f
= XFRAME (w
->frame
);
2049 int tab_width
= XINT (current_buffer
->tab_width
);
2050 int ctl_arrow
= !NILP (current_buffer
->ctl_arrow
);
2051 int width
= window_internal_width (w
) - 1;
2052 struct position val
;
2055 int hscroll
= XINT (w
->hscroll
);
2056 int truncate
= (hscroll
2057 || (truncate_partial_width_windows
2058 && XFASTINT (w
->width
) < FRAME_WIDTH (f
))
2059 || !NILP (current_buffer
->truncate_lines
));
2061 /* 1 if we should highlight the region. */
2062 int highlight_region
2063 = !NILP (Vtransient_mark_mode
) && !NILP (current_buffer
->mark_active
);
2064 int region_beg
, region_end
;
2066 int selective
= (INTEGERP (current_buffer
->selective_display
)
2067 ? XINT (current_buffer
->selective_display
)
2068 : !NILP (current_buffer
->selective_display
) ? -1 : 0);
2069 register struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
2070 register struct Lisp_Vector
*dp
= window_display_table (w
);
2072 Lisp_Object default_invis_vector
[3];
2073 /* Nonzero means display something where there are invisible lines.
2074 The precise value is the number of glyphs to display. */
2076 = (selective
&& dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2077 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->size
2078 : selective
&& !NILP (current_buffer
->selective_display_ellipses
)
2080 /* This is the sequence of Lisp objects to display
2081 when there are invisible lines. */
2082 Lisp_Object
*invis_vector_contents
2083 = (dp
&& VECTORP (DISP_INVIS_VECTOR (dp
))
2084 ? XVECTOR (DISP_INVIS_VECTOR (dp
))->contents
2085 : default_invis_vector
);
2087 GLYPH truncator
= (dp
== 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp
))
2088 ? '$' : XINT (DISP_TRUNC_GLYPH (dp
)));
2089 GLYPH continuer
= (dp
== 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp
))
2090 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp
)));
2092 /* The next buffer location at which the face should change, due
2093 to overlays or text property changes. */
2094 int next_face_change
;
2096 #ifdef USE_TEXT_PROPERTIES
2097 /* The next location where the `invisible' property changes */
2101 /* The face we're currently using. */
2102 int current_face
= 0;
2105 XSETFASTINT (default_invis_vector
[2], '.');
2106 default_invis_vector
[0] = default_invis_vector
[1] = default_invis_vector
[2];
2108 hpos
+= XFASTINT (w
->left
);
2109 get_display_line (f
, vpos
, XFASTINT (w
->left
));
2110 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
2112 /* Show where to highlight the region. */
2113 if (highlight_region
&& XMARKER (current_buffer
->mark
)->buffer
!= 0
2114 /* Maybe highlight only in selected window. */
2115 && (highlight_nonselected_windows
2116 || w
== XWINDOW (selected_window
)))
2118 region_beg
= marker_position (current_buffer
->mark
);
2119 if (PT
< region_beg
)
2121 region_end
= region_beg
;
2126 w
->region_showing
= Qt
;
2129 region_beg
= region_end
= -1;
2131 if (MINI_WINDOW_P (w
)
2133 && vpos
== XFASTINT (w
->top
))
2135 if (! NILP (minibuf_prompt
))
2137 minibuf_prompt_width
2138 = (display_string (w
, vpos
, XSTRING (minibuf_prompt
)->data
,
2139 XSTRING (minibuf_prompt
)->size
, hpos
,
2140 (!truncate
? continuer
: truncator
),
2143 hpos
+= minibuf_prompt_width
;
2146 minibuf_prompt_width
= 0;
2151 /* If we're hscrolled at all, use compute_motion to skip over any
2152 text off the left edge of the window. compute_motion may know
2153 tricks to do this faster than we can. */
2156 struct position
*left_edge
2157 = compute_motion (pos
, vpos
, hpos
,
2159 width
, hscroll
, taboffset
, w
);
2161 /* Retrieve the buffer position and column provided by
2162 compute_motion. We can't assume that the column will be
2163 zero, because you may have multi-column characters crossing
2166 compute_motion may have moved us past the screen position we
2167 requested, if we hit a multi-column character, or the end of
2168 the line. If so, back up. */
2169 if (left_edge
->vpos
> vpos
2170 || left_edge
->hpos
> 0)
2172 pos
= left_edge
->bufpos
- 1;
2173 hpos
= left_edge
->prevhpos
;
2177 pos
= left_edge
->bufpos
;
2178 hpos
= left_edge
->hpos
;
2182 desired_glyphs
->bufp
[vpos
] = start
;
2183 p1
= desired_glyphs
->glyphs
[vpos
] + hpos
;
2185 charstart
= desired_glyphs
->charstarts
[vpos
] + hpos
;
2186 /* In case we don't ever write anything into it... */
2187 desired_glyphs
->charstarts
[vpos
][XFASTINT (w
->left
)] = -1;
2188 leftmargin
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
2189 endp
= leftmargin
+ width
;
2191 /* Arrange the overlays nicely for our purposes. Usually, we call
2192 display_text_line on only one line at a time, in which case this
2193 can't really hurt too much, or we call it on lines which appear
2194 one after another in the buffer, in which case all calls to
2195 recenter_overlay_lists but the first will be pretty cheap. */
2196 recenter_overlay_lists (current_buffer
, pos
);
2198 /* Loop generating characters.
2199 Stop at end of buffer, before newline,
2200 if reach or pass continuation column,
2201 or at face change. */
2203 next_face_change
= pos
;
2204 #ifdef USE_TEXT_PROPERTIES
2205 next_invisible
= pos
;
2209 /* Record which glyph starts a character,
2210 and the character position of that character. */
2211 if (p1
>= leftmargin
)
2212 charstart
[p1
- p1start
] = pos
;
2220 /* Did we hit the end of the visible region of the buffer?
2225 /* Did we reach point? Record the cursor location. */
2226 if (pos
== PT
&& cursor_vpos
< 0)
2229 cursor_hpos
= p1
- leftmargin
;
2232 #ifdef USE_TEXT_PROPERTIES
2233 /* if the `invisible' property is set to t, we can skip to
2234 the next property change */
2235 while (pos
== next_invisible
&& pos
< end
)
2237 Lisp_Object position
, limit
, endpos
, prop
, ww
;
2238 XSETFASTINT (position
, pos
);
2240 prop
= Fget_char_property (position
, Qinvisible
, ww
);
2241 /* This is just an estimate to give reasonable
2242 performance; nothing should go wrong if it is too small. */
2243 limit
= Fnext_overlay_change (position
);
2244 if (XFASTINT (limit
) > pos
+ 50)
2245 XSETFASTINT (limit
, pos
+ 50);
2246 endpos
= Fnext_single_property_change (position
, Qinvisible
,
2247 Fcurrent_buffer (), limit
);
2248 if (INTEGERP (endpos
))
2249 next_invisible
= XINT (endpos
);
2251 next_invisible
= end
;
2254 if (pos
< PT
&& next_invisible
>= PT
)
2257 cursor_hpos
= p1
- leftmargin
;
2259 pos
= next_invisible
;
2266 #ifdef HAVE_X_WINDOWS
2267 /* Did we hit a face change? Figure out what face we should
2268 use now. We also hit this the first time through the
2269 loop, to see what face we should start with. */
2270 if (pos
>= next_face_change
&& FRAME_X_P (f
))
2271 current_face
= compute_char_face (f
, w
, pos
,
2272 region_beg
, region_end
,
2273 &next_face_change
, pos
+ 50, 0);
2278 #ifdef USE_TEXT_PROPERTIES
2279 if (pos
< next_invisible
&& next_invisible
< pause
)
2280 pause
= next_invisible
;
2282 if (pos
< next_face_change
&& next_face_change
< pause
)
2283 pause
= next_face_change
;
2285 /* Wouldn't you hate to read the next line to someone over
2287 if (pos
< PT
&& PT
< pause
)
2289 if (pos
< GPT
&& GPT
< pause
)
2292 p
= &FETCH_CHAR (pos
);
2295 if (c
>= 040 && c
< 0177
2296 && (dp
== 0 || !VECTORP (DISP_CHAR_VECTOR (dp
, c
))))
2298 if (p1
>= leftmargin
)
2299 *p1
= MAKE_GLYPH (f
, c
, current_face
);
2305 while (pos
+ 1 < end
2307 && indented_beyond_p (pos
+ 1, selective
))
2310 pos
= find_next_newline (pos
+ 1, 1);
2311 if (FETCH_CHAR (pos
- 1) == '\n')
2314 if (invis
&& selective_rlen
> 0 && p1
>= leftmargin
)
2316 p1
+= selective_rlen
;
2317 if (p1
- leftmargin
> width
)
2319 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2320 (p1
- p1prev
), current_face
);
2322 #ifdef HAVE_X_WINDOWS
2323 /* Draw the face of the newline character as extending all the
2324 way to the end of the frame line. */
2327 if (p1
< leftmargin
)
2330 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2339 if (p1
>= leftmargin
&& p1
< endp
)
2340 *p1
= MAKE_GLYPH (f
, ' ', current_face
);
2343 while ((p1
- leftmargin
+ taboffset
+ hscroll
- (hscroll
> 0))
2346 else if (c
== Ctl ('M') && selective
== -1)
2348 pos
= find_next_newline (pos
, 1);
2349 if (FETCH_CHAR (pos
- 1) == '\n')
2351 if (selective_rlen
> 0)
2353 p1
+= selective_rlen
;
2354 if (p1
- leftmargin
> width
)
2356 copy_part_of_rope (f
, p1prev
, p1prev
, invis_vector_contents
,
2357 (p1
- p1prev
), current_face
);
2359 #ifdef HAVE_X_WINDOWS
2360 /* Draw the face of the newline character as extending all the
2361 way to the end of the frame line. */
2364 if (p1
< leftmargin
)
2367 *p1
++ = FAST_MAKE_GLYPH (' ', current_face
);
2372 else if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
2374 p1
= copy_part_of_rope (f
, p1
, leftmargin
,
2375 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
2376 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
2379 else if (c
< 0200 && ctl_arrow
)
2381 if (p1
>= leftmargin
)
2382 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
2383 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
2386 if (p1
>= leftmargin
&& p1
< endp
)
2387 *p1
= MAKE_GLYPH (f
, c
^ 0100, current_face
);
2392 if (p1
>= leftmargin
)
2393 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
2394 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
2397 if (p1
>= leftmargin
&& p1
< endp
)
2398 *p1
= MAKE_GLYPH (f
, (c
>> 6) + '0', current_face
);
2400 if (p1
>= leftmargin
&& p1
< endp
)
2401 *p1
= MAKE_GLYPH (f
, (7 & (c
>> 3)) + '0', current_face
);
2403 if (p1
>= leftmargin
&& p1
< endp
)
2404 *p1
= MAKE_GLYPH (f
, (7 & c
) + '0', current_face
);
2408 /* Do nothing here for a char that's entirely off the left edge. */
2409 if (p1
>= leftmargin
)
2411 /* For all the glyphs occupied by this character, except for the
2412 first, store -1 in charstarts. */
2415 int *p2x
= &charstart
[p1prev
- p1start
];
2416 int *p2
= &charstart
[(p1
< endp
? p1
: endp
) - p1start
];
2418 /* The window's left column should always
2419 contain a character position.
2420 And don't clobber anything to the left of that. */
2421 if (p1prev
< leftmargin
)
2423 p2x
= charstart
+ (leftmargin
- p1start
);
2427 /* This loop skips over the char p2x initially points to. */
2436 val
.hpos
= - XINT (w
->hscroll
);
2444 /* Store 0 in this charstart line for the positions where
2445 there is no character. But do leave what was recorded
2446 for the character that ended the line. */
2447 /* Add 1 in the endtest to compensate for the fact that ENDP was
2448 made from WIDTH, which is 1 less than the window's actual
2450 i
= p1
- p1start
+ 1;
2451 if (p1
< leftmargin
)
2452 i
+= leftmargin
- p1
;
2453 for (; i
< endp
- p1start
+ 1; i
++)
2456 /* Handle continuation in middle of a character */
2457 /* by backing up over it */
2460 /* Don't back up if we never actually displayed any text.
2461 This occurs when the minibuffer prompt takes up the whole line. */
2464 /* Start the next line with that same character */
2466 /* but at negative hpos, to skip the columns output on this line. */
2467 val
.hpos
+= p1prev
- endp
;
2470 /* Keep in this line everything up to the continuation column. */
2474 /* Finish deciding which character to start the next line on,
2475 and what hpos to start it at.
2476 Also set `lastpos' to the last position which counts as "on this line"
2477 for cursor-positioning. */
2481 if (FETCH_CHAR (pos
) == '\n')
2483 /* If stopped due to a newline, start next line after it */
2485 /* Check again for hidden lines, in case the newline occurred exactly
2486 at the right margin. */
2487 while (pos
< ZV
&& selective
> 0
2488 && indented_beyond_p (pos
, selective
))
2489 pos
= find_next_newline (pos
, 1);
2492 /* Stopped due to right margin of window */
2496 *p1
++ = fix_glyph (f
, truncator
, 0);
2497 /* Truncating => start next line after next newline,
2498 and point is on this line if it is before the newline,
2499 and skip none of first char of next line */
2501 pos
= find_next_newline (pos
, 1);
2502 while (pos
< ZV
&& selective
> 0
2503 && indented_beyond_p (pos
, selective
));
2504 val
.hpos
= XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0;
2506 lastpos
= pos
- (FETCH_CHAR (pos
- 1) == '\n');
2510 *p1
++ = fix_glyph (f
, continuer
, 0);
2517 /* If point is at eol or in invisible text at eol,
2518 record its frame location now. */
2520 if (start
<= PT
&& PT
<= lastpos
&& cursor_vpos
< 0)
2523 cursor_hpos
= p1
- leftmargin
;
2526 if (cursor_vpos
== vpos
)
2528 if (cursor_hpos
< 0) cursor_hpos
= 0;
2529 if (cursor_hpos
> width
) cursor_hpos
= width
;
2530 cursor_hpos
+= XFASTINT (w
->left
);
2531 if (w
== XWINDOW (FRAME_SELECTED_WINDOW (f
)))
2533 FRAME_CURSOR_Y (f
) = cursor_vpos
;
2534 FRAME_CURSOR_X (f
) = cursor_hpos
;
2536 if (w
== XWINDOW (selected_window
))
2538 /* Line is not continued and did not start
2539 in middle of character */
2540 if ((hpos
- XFASTINT (w
->left
)
2541 == (XINT (w
->hscroll
) ? 1 - XINT (w
->hscroll
) : 0))
2544 this_line_bufpos
= start
;
2545 this_line_buffer
= current_buffer
;
2546 this_line_vpos
= cursor_vpos
;
2547 this_line_start_hpos
= hpos
;
2548 this_line_endpos
= Z
- lastpos
;
2551 this_line_bufpos
= 0;
2556 /* If hscroll and line not empty, insert truncation-at-left marker */
2557 if (hscroll
&& lastpos
!= start
)
2559 *leftmargin
= fix_glyph (f
, truncator
, 0);
2560 if (p1
<= leftmargin
)
2561 p1
= leftmargin
+ 1;
2564 if (XFASTINT (w
->width
) + XFASTINT (w
->left
) != FRAME_WIDTH (f
))
2567 if (p1
< leftmargin
) p1
= leftmargin
;
2568 while (p1
< endp
) *p1
++ = SPACEGLYPH
;
2570 /* Don't draw vertical bars if we're using scroll bars. They're
2571 covered up by the scroll bars, and it's distracting to see
2572 them when the scroll bar windows are flickering around to be
2574 *p1
++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
2576 : (dp
&& INTEGERP (DISP_BORDER_GLYPH (dp
))
2577 ? DISP_BORDER_GLYPH (dp
)
2580 desired_glyphs
->used
[vpos
] = max (desired_glyphs
->used
[vpos
],
2581 p1
- desired_glyphs
->glyphs
[vpos
]);
2582 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
2584 /* If the start of this line is the overlay arrow-position,
2585 then put the arrow string into the display-line. */
2587 if (MARKERP (Voverlay_arrow_position
)
2588 && current_buffer
== XMARKER (Voverlay_arrow_position
)->buffer
2589 && start
== marker_position (Voverlay_arrow_position
)
2590 && STRINGP (Voverlay_arrow_string
)
2591 && ! overlay_arrow_seen
)
2593 unsigned char *p
= XSTRING (Voverlay_arrow_string
)->data
;
2595 int len
= XSTRING (Voverlay_arrow_string
)->size
;
2600 #ifdef HAVE_X_WINDOWS
2601 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string
)->intervals
))
2603 /* If the arrow string has text props, obey them when displaying. */
2604 for (i
= 0; i
< len
; i
++)
2607 Lisp_Object face
, ilisp
;
2610 XSETFASTINT (ilisp
, i
);
2611 face
= Fget_text_property (ilisp
, Qface
, Voverlay_arrow_string
);
2612 newface
= compute_glyph_face_1 (f
, face
, 0);
2613 leftmargin
[i
] = FAST_MAKE_GLYPH (c
, newface
);
2617 #endif /* HAVE_X_WINDOWS */
2619 for (i
= 0; i
< len
; i
++)
2620 leftmargin
[i
] = p
[i
];
2623 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
2624 arrow_end
= (leftmargin
- desired_glyphs
->glyphs
[vpos
]) + len
;
2625 if (desired_glyphs
->used
[vpos
] < arrow_end
)
2626 desired_glyphs
->used
[vpos
] = arrow_end
;
2628 overlay_arrow_seen
= 1;
2632 val_display_text_line
= val
;
2633 return &val_display_text_line
;
2636 /* Redisplay the menu bar in the frame for window W. */
2639 display_menu_bar (w
)
2642 Lisp_Object items
, tail
;
2643 register int vpos
= 0;
2644 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2645 int maxendcol
= FRAME_WIDTH (f
);
2649 #ifndef USE_X_TOOLKIT
2650 if (FRAME_MENU_BAR_LINES (f
) <= 0)
2653 get_display_line (f
, vpos
, 0);
2655 items
= FRAME_MENU_BAR_ITEMS (f
);
2656 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 3)
2658 Lisp_Object pos
, string
;
2659 string
= XVECTOR (items
)->contents
[i
+ 1];
2663 XSETFASTINT (XVECTOR (items
)->contents
[i
+ 2], hpos
);
2665 if (hpos
< maxendcol
)
2666 hpos
= display_string (XWINDOW (FRAME_ROOT_WINDOW (f
)), vpos
,
2667 XSTRING (string
)->data
,
2668 XSTRING (string
)->size
,
2669 hpos
, 0, 0, hpos
, maxendcol
);
2670 /* Put a gap of 3 spaces between items. */
2671 if (hpos
< maxendcol
)
2673 int hpos1
= hpos
+ 3;
2674 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0,
2675 min (hpos1
, maxendcol
), maxendcol
);
2679 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
2680 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
2682 /* Fill out the line with spaces. */
2683 if (maxendcol
> hpos
)
2684 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 0, maxendcol
, maxendcol
);
2686 /* Clear the rest of the lines allocated to the menu bar. */
2688 while (vpos
< FRAME_MENU_BAR_LINES (f
))
2689 get_display_line (f
, vpos
++, 0);
2690 #endif /* not USE_X_TOOLKIT */
2693 /* Display the mode line for window w */
2696 display_mode_line (w
)
2699 register int vpos
= XFASTINT (w
->height
) + XFASTINT (w
->top
) - 1;
2700 register int left
= XFASTINT (w
->left
);
2701 register int right
= XFASTINT (w
->width
) + left
;
2702 register FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2704 line_number_displayed
= 0;
2706 get_display_line (f
, vpos
, left
);
2707 display_mode_element (w
, vpos
, left
, 0, right
, right
,
2708 current_buffer
->mode_line_format
);
2709 FRAME_DESIRED_GLYPHS (f
)->bufp
[vpos
] = 0;
2711 /* Make the mode line inverse video if the entire line
2712 is made of mode lines.
2713 I.e. if this window is full width,
2714 or if it is the child of a full width window
2715 (which implies that that window is split side-by-side
2716 and the rest of this line is mode lines of the sibling windows). */
2717 if (XFASTINT (w
->width
) == FRAME_WIDTH (f
)
2718 || XFASTINT (XWINDOW (w
->parent
)->width
) == FRAME_WIDTH (f
))
2719 FRAME_DESIRED_GLYPHS (f
)->highlight
[vpos
] = mode_line_inverse_video
;
2720 #ifdef HAVE_X_WINDOWS
2721 else if (! FRAME_TERMCAP_P (f
))
2723 /* For a partial width window, explicitly set face of each glyph. */
2725 GLYPH
*ptr
= FRAME_DESIRED_GLYPHS (f
)->glyphs
[vpos
];
2726 for (i
= left
; i
< right
; ++i
)
2727 ptr
[i
] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr
[i
]), 1);
2732 /* Contribute ELT to the mode line for window W.
2733 How it translates into text depends on its data type.
2735 VPOS is the position of the mode line being displayed.
2737 HPOS is the position (absolute on frame) where this element's text
2738 should start. The output is truncated automatically at the right
2741 DEPTH is the depth in recursion. It is used to prevent
2742 infinite recursion here.
2744 MINENDCOL is the hpos before which the element may not end.
2745 The element is padded at the right with spaces if nec
2746 to reach this column.
2748 MAXENDCOL is the hpos past which this element may not extend.
2749 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
2750 (This is necessary to make nested padding and truncation work.)
2752 Returns the hpos of the end of the text generated by ELT.
2753 The next element will receive that value as its HPOS arg,
2754 so as to concatenate the elements. */
2757 display_mode_element (w
, vpos
, hpos
, depth
, minendcol
, maxendcol
, elt
)
2759 register int vpos
, hpos
;
2762 register int maxendcol
;
2763 register Lisp_Object elt
;
2771 #ifdef SWITCH_ENUM_BUG
2772 switch ((int) XTYPE (elt
))
2774 switch (XTYPE (elt
))
2779 /* A string: output it and check for %-constructs within it. */
2780 register unsigned char c
;
2781 register unsigned char *this = XSTRING (elt
)->data
;
2783 while (hpos
< maxendcol
&& *this)
2785 unsigned char *last
= this;
2786 while ((c
= *this++) != '\0' && c
!= '%')
2788 if (this - 1 != last
)
2790 register int lim
= --this - last
+ hpos
;
2791 if (frame_title_ptr
)
2792 hpos
= store_frame_title (last
, hpos
, min (lim
, maxendcol
));
2794 hpos
= display_string (w
, vpos
, last
, -1, hpos
, 0, 1,
2795 hpos
, min (lim
, maxendcol
));
2799 register int spec_width
= 0;
2801 /* We can't allow -ve args due to the "%-" construct */
2802 /* Argument specifies minwidth but not maxwidth
2803 (maxwidth can be specified by
2804 (<negative-number> . <stuff>) mode-line elements) */
2806 while ((c
= *this++) >= '0' && c
<= '9')
2808 spec_width
= spec_width
* 10 + (c
- '0');
2812 if (spec_width
> maxendcol
)
2813 spec_width
= maxendcol
;
2816 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
2817 spec_width
, maxendcol
,
2818 Vglobal_mode_string
);
2821 char *spec
= decode_mode_spec (w
, c
, maxendcol
- hpos
);
2822 if (frame_title_ptr
)
2823 hpos
= store_frame_title (spec
, spec_width
, maxendcol
);
2825 hpos
= display_string (w
, vpos
, spec
, -1,
2827 spec_width
, maxendcol
);
2835 /* A symbol: process the value of the symbol recursively
2836 as if it appeared here directly. Avoid error if symbol void.
2837 Special case: if value of symbol is a string, output the string
2840 register Lisp_Object tem
;
2841 tem
= Fboundp (elt
);
2844 tem
= Fsymbol_value (elt
);
2845 /* If value is a string, output that string literally:
2846 don't check for % within it. */
2849 if (frame_title_ptr
)
2850 hpos
= store_frame_title (XSTRING (tem
)->data
,
2851 minendcol
, maxendcol
);
2853 hpos
= display_string (w
, vpos
, XSTRING (tem
)->data
,
2854 XSTRING (tem
)->size
,
2855 hpos
, 0, 1, minendcol
, maxendcol
);
2857 /* Give up right away for nil or t. */
2858 else if (!EQ (tem
, elt
))
2859 { elt
= tem
; goto tail_recurse
; }
2866 register Lisp_Object car
, tem
;
2868 /* A cons cell: three distinct cases.
2869 If first element is a string or a cons, process all the elements
2870 and effectively concatenate them.
2871 If first element is a negative number, truncate displaying cdr to
2872 at most that many characters. If positive, pad (with spaces)
2873 to at least that many characters.
2874 If first element is a symbol, process the cadr or caddr recursively
2875 according to whether the symbol's value is non-nil or nil. */
2876 car
= XCONS (elt
)->car
;
2879 tem
= Fboundp (car
);
2880 elt
= XCONS (elt
)->cdr
;
2883 /* elt is now the cdr, and we know it is a cons cell.
2884 Use its car if CAR has a non-nil value. */
2887 tem
= Fsymbol_value (car
);
2889 { elt
= XCONS (elt
)->car
; goto tail_recurse
; }
2891 /* Symbol's value is nil (or symbol is unbound)
2892 Get the cddr of the original list
2893 and if possible find the caddr and use that. */
2894 elt
= XCONS (elt
)->cdr
;
2897 else if (!CONSP (elt
))
2899 elt
= XCONS (elt
)->car
;
2902 else if (INTEGERP (car
))
2904 register int lim
= XINT (car
);
2905 elt
= XCONS (elt
)->cdr
;
2907 /* Negative int means reduce maximum width.
2908 DO NOT change MINENDCOL here!
2909 (20 -10 . foo) should truncate foo to 10 col
2910 and then pad to 20. */
2911 maxendcol
= min (maxendcol
, hpos
- lim
);
2914 /* Padding specified. Don't let it be more than
2917 if (lim
> maxendcol
)
2919 /* If that's more padding than already wanted, queue it.
2920 But don't reduce padding already specified even if
2921 that is beyond the current truncation point. */
2922 if (lim
> minendcol
)
2927 else if (STRINGP (car
) || CONSP (car
))
2929 register int limit
= 50;
2930 /* LIMIT is to protect against circular lists. */
2931 while (CONSP (elt
) && --limit
> 0
2932 && hpos
< maxendcol
)
2934 hpos
= display_mode_element (w
, vpos
, hpos
, depth
,
2937 elt
= XCONS (elt
)->cdr
;
2945 if (frame_title_ptr
)
2946 hpos
= store_frame_title ("*invalid*", minendcol
, maxendcol
);
2948 hpos
= display_string (w
, vpos
, "*invalid*", -1, hpos
, 0, 1,
2949 minendcol
, maxendcol
);
2953 if (minendcol
> hpos
)
2954 if (frame_title_ptr
)
2955 hpos
= store_frame_title ("", minendcol
, maxendcol
);
2957 hpos
= display_string (w
, vpos
, "", 0, hpos
, 0, 1, minendcol
, maxendcol
);
2961 /* Return a string for the output of a mode line %-spec for window W,
2962 generated by character C and width MAXWIDTH. */
2964 static char lots_of_dashes
[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
2967 decode_mode_spec (w
, c
, maxwidth
)
2970 register int maxwidth
;
2973 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2974 char *decode_mode_spec_buf
= (char *) FRAME_TEMP_GLYPHS (f
)->total_contents
;
2975 struct buffer
*b
= XBUFFER (w
->buffer
);
2978 if (maxwidth
> FRAME_WIDTH (f
))
2979 maxwidth
= FRAME_WIDTH (f
);
2986 if (maxwidth
>= 3 && XSTRING (obj
)->size
> maxwidth
)
2988 bcopy (XSTRING (obj
)->data
, decode_mode_spec_buf
, maxwidth
- 1);
2989 decode_mode_spec_buf
[maxwidth
- 1] = '\\';
2990 decode_mode_spec_buf
[maxwidth
] = '\0';
2991 return decode_mode_spec_buf
;
3001 else if (STRINGP (obj
) && XSTRING (obj
)->size
> maxwidth
)
3003 bcopy ("...", decode_mode_spec_buf
, 3);
3004 bcopy (XSTRING (obj
)->data
+ XSTRING (obj
)->size
- maxwidth
+ 3,
3005 decode_mode_spec_buf
+ 3, maxwidth
- 3);
3006 return decode_mode_spec_buf
;
3013 int startpos
= marker_position (w
->start
);
3014 int line
, linepos
, topline
;
3017 int height
= XFASTINT (w
->height
);
3019 /* If we decided that this buffer isn't suitable for line numbers,
3020 don't forget that too fast. */
3021 if (EQ (w
->base_line_pos
, w
->buffer
))
3024 /* If the buffer is very big, don't waste time. */
3025 if (BUF_ZV (b
) - BUF_BEGV (b
) > line_number_display_limit
)
3027 w
->base_line_pos
= Qnil
;
3028 w
->base_line_number
= Qnil
;
3032 if (!NILP (w
->base_line_number
)
3033 && !NILP (w
->base_line_pos
)
3034 && XFASTINT (w
->base_line_pos
) <= marker_position (w
->start
))
3036 line
= XFASTINT (w
->base_line_number
);
3037 linepos
= XFASTINT (w
->base_line_pos
);
3042 linepos
= BUF_BEGV (b
);
3045 /* Count lines from base line to window start position. */
3046 nlines
= display_count_lines (linepos
, startpos
, startpos
, &junk
);
3048 topline
= nlines
+ line
;
3050 /* Determine a new base line, if the old one is too close
3051 or too far away, or if we did not have one.
3052 "Too close" means it's plausible a scroll-down would
3054 if (startpos
== BUF_BEGV (b
))
3056 XSETFASTINT (w
->base_line_number
, topline
);
3057 XSETFASTINT (w
->base_line_pos
, BUF_BEGV (b
));
3059 else if (nlines
< height
+ 25 || nlines
> height
* 3 + 50
3060 || linepos
== BUF_BEGV (b
))
3062 int limit
= BUF_BEGV (b
);
3064 int distance
= (height
* 2 + 30) * 200;
3066 if (startpos
- distance
> limit
)
3067 limit
= startpos
- distance
;
3069 nlines
= display_count_lines (startpos
, limit
,
3072 /* If we couldn't find the lines we wanted within
3074 give up on line numbers for this window. */
3075 if (position
== startpos
- distance
)
3077 w
->base_line_pos
= w
->buffer
;
3078 w
->base_line_number
= Qnil
;
3082 XSETFASTINT (w
->base_line_number
, topline
- nlines
);
3083 XSETFASTINT (w
->base_line_pos
, position
);
3086 /* Now count lines from the start pos to point. */
3087 nlines
= display_count_lines (startpos
, PT
, PT
, &junk
);
3089 /* Record that we did display the line number. */
3090 line_number_displayed
= 1;
3092 /* Make the string to show. */
3093 sprintf (decode_mode_spec_buf
, "%d", topline
+ nlines
);
3094 return decode_mode_spec_buf
;
3103 if (BUF_BEGV (b
) > BUF_BEG (b
) || BUF_ZV (b
) < BUF_Z (b
))
3108 if (!NILP (b
->read_only
))
3110 if (BUF_MODIFF (b
) > b
->save_modified
)
3115 /* This differs from %* only for a modified read-only buffer. */
3116 if (BUF_MODIFF (b
) > b
->save_modified
)
3118 if (!NILP (b
->read_only
))
3123 /* This differs from %* in ignoring read-only-ness. */
3124 if (BUF_MODIFF (b
) > b
->save_modified
)
3129 /* status of process */
3130 obj
= Fget_buffer_process (w
->buffer
);
3132 return "no process";
3134 obj
= Fsymbol_name (Fprocess_status (obj
));
3138 case 't': /* indicate TEXT or BINARY */
3139 #ifdef MODE_LINE_BINARY_TEXT
3140 return MODE_LINE_BINARY_TEXT (b
);
3147 int pos
= marker_position (w
->start
);
3148 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3150 if (XFASTINT (w
->window_end_pos
) <= BUF_Z (b
) - BUF_ZV (b
))
3152 if (pos
<= BUF_BEGV (b
))
3157 else if (pos
<= BUF_BEGV (b
))
3161 total
= ((pos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3162 /* We can't normally display a 3-digit number,
3163 so get us a 2-digit number that is close. */
3166 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3167 return decode_mode_spec_buf
;
3171 /* Display percentage of size above the bottom of the screen. */
3174 int toppos
= marker_position (w
->start
);
3175 int botpos
= BUF_Z (b
) - XFASTINT (w
->window_end_pos
);
3176 int total
= BUF_ZV (b
) - BUF_BEGV (b
);
3178 if (botpos
>= BUF_ZV (b
))
3180 if (toppos
<= BUF_BEGV (b
))
3187 total
= ((botpos
- BUF_BEGV (b
)) * 100 + total
- 1) / total
;
3188 /* We can't normally display a 3-digit number,
3189 so get us a 2-digit number that is close. */
3192 if (toppos
<= BUF_BEGV (b
))
3193 sprintf (decode_mode_spec_buf
, "Top%2d%%", total
);
3195 sprintf (decode_mode_spec_buf
, "%2d%%", total
);
3196 return decode_mode_spec_buf
;
3208 if (command_loop_level
> 5)
3210 p
= decode_mode_spec_buf
;
3211 for (i
= 0; i
< command_loop_level
; i
++)
3214 return decode_mode_spec_buf
;
3222 if (command_loop_level
> 5)
3224 p
= decode_mode_spec_buf
;
3225 for (i
= 0; i
< command_loop_level
; i
++)
3228 return decode_mode_spec_buf
;
3236 if (maxwidth
< sizeof (lots_of_dashes
))
3237 return lots_of_dashes
;
3240 for (p
= decode_mode_spec_buf
, i
= maxwidth
; i
> 0; i
--)
3244 return decode_mode_spec_buf
;
3249 return (char *) XSTRING (obj
)->data
;
3254 /* Search for COUNT instances of a line boundary, which means either a
3255 newline or (if selective display enabled) a carriage return.
3256 Start at START. If COUNT is negative, search backwards.
3258 If we find COUNT instances, set *SHORTAGE to zero, and return the
3259 position after the COUNTth match. Note that for reverse motion
3260 this is not the same as the usual convention for Emacs motion commands.
3262 If we don't find COUNT instances before reaching the end of the
3263 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3264 the number of line boundaries left unfound, and return the end of the
3265 buffer we bumped up against. */
3268 display_scan_buffer (start
, count
, shortage
)
3269 int *shortage
, start
;
3272 int limit
= ((count
> 0) ? ZV
- 1 : BEGV
);
3273 int direction
= ((count
> 0) ? 1 : -1);
3275 register unsigned char *cursor
;
3276 unsigned char *base
;
3278 register int ceiling
;
3279 register unsigned char *ceiling_addr
;
3281 /* If we are not in selective display mode,
3282 check only for newlines. */
3283 if (! (!NILP (current_buffer
->selective_display
)
3284 && !INTEGERP (current_buffer
->selective_display
)))
3285 return scan_buffer ('\n', start
, count
, shortage
, 0);
3287 /* The code that follows is like scan_buffer
3288 but checks for either newline or carriage return. */
3294 while (start
!= limit
+ 1)
3296 ceiling
= BUFFER_CEILING_OF (start
);
3297 ceiling
= min (limit
, ceiling
);
3298 ceiling_addr
= &FETCH_CHAR (ceiling
) + 1;
3299 base
= (cursor
= &FETCH_CHAR (start
));
3302 while (*cursor
!= '\n' && *cursor
!= 015 && ++cursor
!= ceiling_addr
)
3304 if (cursor
!= ceiling_addr
)
3309 return (start
+ cursor
- base
+ 1);
3312 if (++cursor
== ceiling_addr
)
3318 start
+= cursor
- base
;
3322 start
--; /* first character we scan */
3323 while (start
> limit
- 1)
3324 { /* we WILL scan under start */
3325 ceiling
= BUFFER_FLOOR_OF (start
);
3326 ceiling
= max (limit
, ceiling
);
3327 ceiling_addr
= &FETCH_CHAR (ceiling
) - 1;
3328 base
= (cursor
= &FETCH_CHAR (start
));
3332 while (--cursor
!= ceiling_addr
3333 && *cursor
!= '\n' && *cursor
!= 015)
3335 if (cursor
!= ceiling_addr
)
3340 return (start
+ cursor
- base
+ 1);
3346 start
+= cursor
- base
;
3351 *shortage
= count
* direction
;
3352 return (start
+ ((direction
== 1 ? 0 : 1)));
3355 /* Count up to N lines starting from FROM.
3356 But don't go beyond LIMIT.
3357 Return the number of lines thus found (always positive).
3358 Store the position after what was found into *POS_PTR. */
3361 display_count_lines (from
, limit
, n
, pos_ptr
)
3374 *pos_ptr
= display_scan_buffer (from
, n
, &shortage
);
3380 /* When scanning backwards, scan_buffer stops *after* the last newline
3381 it finds, but does count it. Compensate for that. */
3382 return - n
- shortage
- (*pos_ptr
!= limit
);
3383 return n
- shortage
;
3386 /* Display STRING on one line of window W, starting at HPOS.
3387 Display at position VPOS. Caller should have done get_display_line.
3388 If VPOS == -1, display it as the current frame's title.
3389 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3391 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3393 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3394 MAXCOL is the last column ok to end at. Truncate here.
3395 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3396 Both count from the left edge of the frame, as does HPOS.
3397 The right edge of W is an implicit maximum.
3398 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3400 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3401 at the place where the current window ends in this line
3402 and not display anything beyond there. Otherwise, only MAXCOL
3403 controls where to stop output.
3405 Returns ending hpos. */
3408 display_string (w
, vpos
, string
, length
, hpos
, truncate
,
3409 obey_window_width
, mincol
, maxcol
)
3411 unsigned char *string
;
3415 int obey_window_width
;
3420 int hscroll
= XINT (w
->hscroll
);
3421 int tab_width
= XINT (XBUFFER (w
->buffer
)->tab_width
);
3422 register GLYPH
*start
;
3423 register GLYPH
*end
;
3424 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
3425 struct frame_glyphs
*desired_glyphs
= FRAME_DESIRED_GLYPHS (f
);
3426 GLYPH
*p1start
= desired_glyphs
->glyphs
[vpos
] + hpos
;
3427 int window_width
= XFASTINT (w
->width
);
3429 /* Use the standard display table, not the window's display table.
3430 We don't want the mode line in rot13. */
3431 register struct Lisp_Vector
*dp
= 0;
3434 if (VECTORP (Vstandard_display_table
)
3435 && XVECTOR (Vstandard_display_table
)->size
== DISP_TABLE_SIZE
)
3436 dp
= XVECTOR (Vstandard_display_table
);
3438 if (tab_width
<= 0 || tab_width
> 1000) tab_width
= 8;
3441 start
= desired_glyphs
->glyphs
[vpos
] + XFASTINT (w
->left
);
3443 if (obey_window_width
)
3445 end
= start
+ window_width
- (truncate
!= 0);
3447 if ((window_width
+ XFASTINT (w
->left
)) != FRAME_WIDTH (f
))
3449 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3453 for (i
= 0; i
< FRAME_SCROLL_BAR_COLS (f
); i
++)
3461 if (! obey_window_width
3462 || (maxcol
>= 0 && end
- desired_glyphs
->glyphs
[vpos
] > maxcol
))
3463 end
= desired_glyphs
->glyphs
[vpos
] + maxcol
;
3465 /* Store 0 in charstart for these columns. */
3466 for (i
= (hpos
>= 0 ? hpos
: 0); i
< end
- p1start
+ hpos
; i
++)
3467 desired_glyphs
->charstarts
[vpos
][i
] = 0;
3469 if (maxcol
>= 0 && mincol
> maxcol
)
3477 /* Specified length. */
3480 /* Unspecified length (null-terminated string). */
3484 if (c
>= 040 && c
< 0177
3485 && (dp
== 0 || !VECTORP (DISP_CHAR_VECTOR (dp
, c
))))
3495 if (p1
>= start
&& p1
< end
)
3499 while ((p1
- start
+ hscroll
- (hscroll
> 0)) % tab_width
);
3501 else if (dp
!= 0 && VECTORP (DISP_CHAR_VECTOR (dp
, c
)))
3503 p1
= copy_part_of_rope (f
, p1
, start
,
3504 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->contents
,
3505 XVECTOR (DISP_CHAR_VECTOR (dp
, c
))->size
,
3508 else if (c
< 0200 && ! NILP (buffer_defaults
.ctl_arrow
))
3511 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_CTRL_GLYPH (dp
))
3512 ? XINT (DISP_CTRL_GLYPH (dp
)) : '^'),
3515 if (p1
>= start
&& p1
< end
)
3522 *p1
= fix_glyph (f
, (dp
&& INTEGERP (DISP_ESCAPE_GLYPH (dp
))
3523 ? XINT (DISP_ESCAPE_GLYPH (dp
)) : '\\'),
3526 if (p1
>= start
&& p1
< end
)
3527 *p1
= (c
>> 6) + '0';
3529 if (p1
>= start
&& p1
< end
)
3530 *p1
= (7 & (c
>> 3)) + '0';
3532 if (p1
>= start
&& p1
< end
)
3533 *p1
= (7 & c
) + '0';
3538 if (c
&& length
> 0)
3541 if (truncate
) *p1
++ = fix_glyph (f
, truncate
, 0);
3543 else if (mincol
>= 0)
3545 end
= desired_glyphs
->glyphs
[vpos
] + mincol
;
3551 register int len
= p1
- desired_glyphs
->glyphs
[vpos
];
3553 if (len
> desired_glyphs
->used
[vpos
])
3554 desired_glyphs
->used
[vpos
] = len
;
3555 desired_glyphs
->glyphs
[vpos
][desired_glyphs
->used
[vpos
]] = 0;
3564 staticpro (&Qmenu_bar_update_hook
);
3565 Qmenu_bar_update_hook
= intern ("menu-bar-update-hook");
3567 staticpro (&last_arrow_position
);
3568 staticpro (&last_arrow_string
);
3569 last_arrow_position
= Qnil
;
3570 last_arrow_string
= Qnil
;
3572 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
,
3573 "String (or mode line construct) included (normally) in `mode-line-format'.");
3574 Vglobal_mode_string
= Qnil
;
3576 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
,
3577 "Marker for where to display an arrow on top of the buffer text.\n\
3578 This must be the beginning of a line in order to work.\n\
3579 See also `overlay-arrow-string'.");
3580 Voverlay_arrow_position
= Qnil
;
3582 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
,
3583 "String to display as an arrow. See also `overlay-arrow-position'.");
3584 Voverlay_arrow_string
= Qnil
;
3586 DEFVAR_INT ("scroll-step", &scroll_step
,
3587 "*The number of lines to try scrolling a window by when point moves out.\n\
3588 If that fails to bring point back on frame, point is centered instead.\n\
3589 If this is zero, point is always centered after it moves off frame.");
3591 DEFVAR_INT ("debug-end-pos", &debug_end_pos
, "Don't ask");
3593 DEFVAR_BOOL ("truncate-partial-width-windows",
3594 &truncate_partial_width_windows
,
3595 "*Non-nil means truncate lines in all windows less than full frame wide.");
3596 truncate_partial_width_windows
= 1;
3598 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
,
3599 "*Non-nil means use inverse video for the mode line.");
3600 mode_line_inverse_video
= 1;
3602 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit
,
3603 "*Maximum buffer size for which line number should be displayed.");
3604 line_number_display_limit
= 1000000;
3606 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
,
3607 "*Non-nil means highlight region even in nonselected windows.");
3608 highlight_nonselected_windows
= 1;
3610 DEFVAR_BOOL ("multiple-frames", &multiple_frames
,
3611 "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\
3612 Not guaranteed to be accurate except while parsing frame-title-format.");
3614 DEFVAR_LISP ("frame-title-format", &Vframe_title_format
,
3615 "Template for displaying the titlebar of visible frames.\n\
3616 \(Assuming the window manager supports this feature.)\n\
3617 This variable has the same structure as `mode-line-format' (which see),\n\
3618 and is used only on frames for which no explicit name has been set\n\
3619 \(see `modify-frame-parameters').");
3620 DEFVAR_LISP ("icon-title-format", &Vicon_title_format
,
3621 "Template for displaying the titlebar of an iconified frame.\n\
3622 \(Assuming the window manager supports this feature.)\n\
3623 This variable has the same structure as `mode-line-format' (which see),\n\
3624 and is used only on frames for which no explicit name has been set\n\
3625 \(see `modify-frame-parameters').");
3627 = Vframe_title_format
3628 = Fcons (intern ("multiple-frames"),
3629 Fcons (build_string ("%b"),
3630 Fcons (Fcons (build_string (""),
3631 Fcons (intern ("invocation-name"),
3632 Fcons (build_string ("@"),
3633 Fcons (intern ("system-name"),
3638 /* initialize the window system */
3641 Lisp_Object root_window
;
3642 #ifndef COMPILER_REGISTER_BUG
3644 #endif /* COMPILER_REGISTER_BUG */
3645 struct window
*mini_w
;
3647 this_line_bufpos
= 0;
3649 mini_w
= XWINDOW (minibuf_window
);
3650 root_window
= FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w
)));
3652 echo_area_glyphs
= 0;
3653 previous_echo_glyphs
= 0;
3655 if (!noninteractive
)
3657 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (root_window
)));
3658 XSETFASTINT (XWINDOW (root_window
)->top
, 0);
3659 set_window_height (root_window
, FRAME_HEIGHT (f
) - 1, 0);
3660 XSETFASTINT (mini_w
->top
, FRAME_HEIGHT (f
) - 1);
3661 set_window_height (minibuf_window
, 1, 0);
3663 XSETFASTINT (XWINDOW (root_window
)->width
, FRAME_WIDTH (f
));
3664 XSETFASTINT (mini_w
->width
, FRAME_WIDTH (f
));