]> code.delx.au - gnu-emacs/blob - src/xdisp.c
(display_text_line): Deduct minibuf prompt from taboffset.
[gnu-emacs] / src / xdisp.c
1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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)
9 any later version.
10
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.
15
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. */
19
20
21 #include <config.h>
22 #include <stdio.h>
23 /*#include <ctype.h>*/
24 #undef NULL
25 #include "lisp.h"
26 #include "frame.h"
27 #include "window.h"
28 #include "termchar.h"
29 #include "dispextern.h"
30 #include "buffer.h"
31 #include "indent.h"
32 #include "commands.h"
33 #include "macros.h"
34 #include "disptab.h"
35 #include "termhooks.h"
36 #include "intervals.h"
37
38 #ifdef USE_X_TOOLKIT
39 extern void set_frame_menubar ();
40 #endif
41
42 extern int interrupt_input;
43 extern int command_loop_level;
44
45 extern Lisp_Object Qface;
46
47 /* Nonzero means print newline to stdout before next minibuffer message. */
48
49 int noninteractive_need_newline;
50
51 /* Nonzero means print newline to message log before next message. */
52
53 static int message_log_need_newline;
54
55 #define min(a, b) ((a) < (b) ? (a) : (b))
56 #define max(a, b) ((a) > (b) ? (a) : (b))
57
58 /* The buffer position of the first character appearing
59 entirely or partially on the current frame line.
60 Or zero, which disables the optimization for the current frame line. */
61 static int this_line_bufpos;
62
63 /* Number of characters past the end of this line,
64 including the terminating newline */
65 static int this_line_endpos;
66
67 /* The vertical position of this frame line. */
68 static int this_line_vpos;
69
70 /* Hpos value for start of display on this frame line.
71 Usually zero, but negative if first character really began
72 on previous line */
73 static int this_line_start_hpos;
74
75 /* Buffer that this_line variables are describing. */
76 static struct buffer *this_line_buffer;
77
78 /* Set by try_window_id to the vpos of first of any lines
79 scrolled on to the bottom of the frame. These lines should
80 not be included in any general scroll computation. */
81 static int scroll_bottom_vpos;
82
83 /* Value of echo_area_glyphs when it was last acted on.
84 If this is nonzero, there is a message on the frame
85 in the minibuffer and it should be erased as soon
86 as it is no longer requested to appear. */
87 char *previous_echo_glyphs;
88
89 /* Nonzero means truncate lines in all windows less wide than the frame */
90 int truncate_partial_width_windows;
91
92 /* Nonzero means we have more than one non-minibuffer-only frame.
93 Not guaranteed to be accurate except while parsing frame-title-format. */
94 int multiple_frames;
95
96 Lisp_Object Vglobal_mode_string;
97
98 /* Marker for where to display an arrow on top of the buffer text. */
99 Lisp_Object Voverlay_arrow_position;
100
101 /* String to display for the arrow. */
102 Lisp_Object Voverlay_arrow_string;
103
104 /* Like mode-line-format, but for the titlebar on a visible frame. */
105 Lisp_Object Vframe_title_format;
106
107 /* Like mode-line-format, but for the titlebar on an iconified frame. */
108 Lisp_Object Vicon_title_format;
109
110 /* Values of those variables at last redisplay. */
111 static Lisp_Object last_arrow_position, last_arrow_string;
112
113 Lisp_Object Qmenu_bar_update_hook;
114
115 /* Nonzero if overlay arrow has been displayed once in this window. */
116 static int overlay_arrow_seen;
117
118 /* Nonzero means highlight the region even in nonselected windows. */
119 static int highlight_nonselected_windows;
120
121 /* If cursor motion alone moves point off frame,
122 Try scrolling this many lines up or down if that will bring it back. */
123 int scroll_step;
124
125 /* Nonzero if try_window_id has made blank lines at window bottom
126 since the last redisplay that paused */
127 static int blank_end_of_window;
128
129 /* Number of windows showing the buffer of the selected window
130 (or another buffer with the same base buffer).
131 keyboard.c refers to this. */
132 int buffer_shared;
133
134 /* display_text_line sets these to the frame position (origin 0) of point,
135 whether the window is selected or not.
136 Set one to -1 first to determine whether point was found afterwards. */
137
138 static int cursor_vpos;
139 static int cursor_hpos;
140
141 int debug_end_pos;
142
143 /* Nonzero means display mode line highlighted */
144 int mode_line_inverse_video;
145
146 static void echo_area_display ();
147 void mark_window_display_accurate ();
148 static void redisplay_windows ();
149 static void redisplay_window ();
150 static void update_menu_bars ();
151 static void update_menu_bar ();
152 static void try_window ();
153 static int try_window_id ();
154 static struct position *display_text_line ();
155 static void display_mode_line ();
156 static int display_mode_element ();
157 static char *fmodetrunc ();
158 static char *decode_mode_spec ();
159 static int display_string ();
160 static void display_menu_bar ();
161 static int display_count_lines ();
162
163 /* Prompt to display in front of the minibuffer contents */
164 Lisp_Object minibuf_prompt;
165
166 /* Width in columns of current minibuffer prompt. */
167 int minibuf_prompt_width;
168
169 /* Message to display instead of minibuffer contents
170 This is what the functions error and message make,
171 and command echoing uses it as well.
172 It overrides the minibuf_prompt as well as the buffer. */
173 char *echo_area_glyphs;
174
175 /* This is the length of the message in echo_area_glyphs. */
176 int echo_area_glyphs_length;
177
178 /* true iff we should redraw the mode lines on the next redisplay */
179 int update_mode_lines;
180
181 /* Smallest number of characters before the gap
182 at any time since last redisplay that finished.
183 Valid for current buffer when try_window_id can be called. */
184 int beg_unchanged;
185
186 /* Smallest number of characters after the gap
187 at any time since last redisplay that finished.
188 Valid for current buffer when try_window_id can be called. */
189 int end_unchanged;
190
191 /* MODIFF as of last redisplay that finished;
192 if it matches MODIFF, beg_unchanged and end_unchanged
193 contain no useful information */
194 int unchanged_modified;
195
196 /* Nonzero if head_clip or tail_clip of current buffer has changed
197 since last redisplay that finished */
198 int clip_changed;
199
200 /* Nonzero if window sizes or contents have changed
201 since last redisplay that finished */
202 int windows_or_buffers_changed;
203
204 /* Nonzero after display_mode_line if %l was used
205 and it displayed a line number. */
206 int line_number_displayed;
207
208 /* Maximum buffer size for which to display line numbers. */
209 int line_number_display_limit;
210
211 /* Number of lines to keep in the message log buffer.
212 t means infinite. nil means don't log at all. */
213 Lisp_Object Vmessage_log_max;
214 \f
215 void
216 message_log_maybe_newline ()
217 {
218 if (message_log_need_newline)
219 message_dolog ("", 0, 1);
220 }
221
222
223 /* Add a string to the message log, optionally terminated with a newline.
224 This function calls low-level routines in order to bypass text property
225 hooks, etc. which might not be safe to run. */
226
227 void
228 message_dolog (m, len, nlflag)
229 char *m;
230 int len, nlflag;
231 {
232 if (!NILP (Vmessage_log_max))
233 {
234 struct buffer *oldbuf;
235 int oldpoint, oldbegv, oldzv;
236
237 oldbuf = current_buffer;
238 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
239 oldpoint = PT;
240 oldbegv = BEGV;
241 oldzv = ZV;
242 BEGV = BEG;
243 ZV = Z;
244 if (oldpoint == Z)
245 oldpoint += len + nlflag;
246 if (oldzv == Z)
247 oldzv += len + nlflag;
248 TEMP_SET_PT (Z);
249 if (len)
250 insert_1 (m, len, 1, 0);
251 if (nlflag)
252 insert_1 ("\n", 1, 1, 0);
253 if (NATNUMP (Vmessage_log_max))
254 {
255 int pos = scan_buffer ('\n', PT, 0,
256 -XFASTINT (Vmessage_log_max) - 1, 0, 1);
257 oldpoint -= min (pos, oldpoint) - BEG;
258 oldbegv -= min (pos, oldbegv) - BEG;
259 oldzv -= min (pos, oldzv) - BEG;
260 del_range_1 (BEG, pos, 0);
261 }
262 BEGV = oldbegv;
263 ZV = oldzv;
264 TEMP_SET_PT (oldpoint);
265 set_buffer_internal (oldbuf);
266 message_log_need_newline = !nlflag;
267 }
268 }
269
270
271 /* Display an echo area message M with a specified length of LEN chars.
272 The string may include null characters. If m is 0, clear out any
273 existing message, and let the minibuffer text show through.
274 Do not pass text that is stored in a Lisp string. */
275
276 void
277 message2 (m, len)
278 char *m;
279 int len;
280 {
281 /* First flush out any partial line written with print. */
282 message_log_maybe_newline ();
283 if (m)
284 message_dolog (m, len, 1);
285 message2_nolog (m, len);
286 }
287
288
289 /* The non-logging part of that function. */
290
291 void
292 message2_nolog (m, len)
293 char *m;
294 int len;
295 {
296 if (noninteractive)
297 {
298 if (noninteractive_need_newline)
299 putc ('\n', stderr);
300 noninteractive_need_newline = 0;
301 fwrite (m, len, 1, stderr);
302 if (cursor_in_echo_area == 0)
303 fprintf (stderr, "\n");
304 fflush (stderr);
305 }
306 /* A null message buffer means that the frame hasn't really been
307 initialized yet. Error messages get reported properly by
308 cmd_error, so this must be just an informative message; toss it. */
309 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
310 {
311 #ifdef MULTI_FRAME
312 Lisp_Object minibuf_frame;
313
314 choose_minibuf_frame ();
315 minibuf_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
316 FRAME_SAMPLE_VISIBILITY (XFRAME (minibuf_frame));
317 if (FRAME_VISIBLE_P (selected_frame)
318 && ! FRAME_VISIBLE_P (XFRAME (minibuf_frame)))
319 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (minibuf_window)));
320 #endif
321
322 if (m)
323 {
324 echo_area_glyphs = m;
325 echo_area_glyphs_length = len;
326 }
327 else
328 echo_area_glyphs = previous_echo_glyphs = 0;
329
330 do_pending_window_change ();
331 echo_area_display ();
332 update_frame (XFRAME (XWINDOW (minibuf_window)->frame), 1, 1);
333 do_pending_window_change ();
334 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
335 (*frame_up_to_date_hook) (XFRAME (XWINDOW (minibuf_window)->frame));
336 }
337 }
338
339 void
340 message1 (m)
341 char *m;
342 {
343 message2 (m, (m ? strlen (m) : 0));
344 }
345
346 void
347 message1_nolog (m)
348 char *m;
349 {
350 message2_nolog (m, (m ? strlen (m) : 0));
351 }
352
353 /* Truncate what will be displayed in the echo area
354 the next time we display it--but don't redisplay it now. */
355
356 void
357 truncate_echo_area (len)
358 int len;
359 {
360 /* A null message buffer means that the frame hasn't really been
361 initialized yet. Error messages get reported properly by
362 cmd_error, so this must be just an informative message; toss it. */
363 if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
364 echo_area_glyphs_length = len;
365 }
366
367 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
368 zero if being used by message. */
369 int message_buf_print;
370
371 /* Dump an informative message to the minibuf. If m is 0, clear out
372 any existing message, and let the minibuffer text show through. */
373 /* VARARGS 1 */
374 void
375 message (m, a1, a2, a3)
376 char *m;
377 EMACS_INT a1, a2, a3;
378 {
379 if (noninteractive)
380 {
381 if (m)
382 {
383 if (noninteractive_need_newline)
384 putc ('\n', stderr);
385 noninteractive_need_newline = 0;
386 fprintf (stderr, m, a1, a2, a3);
387 if (cursor_in_echo_area == 0)
388 fprintf (stderr, "\n");
389 fflush (stderr);
390 }
391 }
392 else if (INTERACTIVE)
393 {
394 /* The frame whose minibuffer we're going to display the message on.
395 It may be larger than the selected frame, so we need
396 to use its buffer, not the selected frame's buffer. */
397 FRAME_PTR echo_frame;
398 #ifdef MULTI_FRAME
399 choose_minibuf_frame ();
400 echo_frame = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
401 #else
402 echo_frame = selected_frame;
403 #endif
404
405 /* A null message buffer means that the frame hasn't really been
406 initialized yet. Error messages get reported properly by
407 cmd_error, so this must be just an informative message; toss it. */
408 if (FRAME_MESSAGE_BUF (echo_frame))
409 {
410 if (m)
411 {
412 int len;
413 #ifdef NO_ARG_ARRAY
414 EMACS_INT a[3];
415 a[0] = a1;
416 a[1] = a2;
417 a[2] = a3;
418
419 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
420 FRAME_WIDTH (echo_frame), m, 0, 3, a);
421 #else
422 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
423 FRAME_WIDTH (echo_frame), m, 0, 3, &a1);
424 #endif /* NO_ARG_ARRAY */
425
426 message2 (FRAME_MESSAGE_BUF (echo_frame), len);
427 }
428 else
429 message1 (0);
430
431 /* Print should start at the beginning of the message
432 buffer next time. */
433 message_buf_print = 0;
434 }
435 }
436 }
437
438 void
439 update_echo_area ()
440 {
441 message2 (echo_area_glyphs, echo_area_glyphs_length);
442 }
443
444 static void
445 echo_area_display ()
446 {
447 register int vpos;
448 FRAME_PTR f;
449
450 #ifdef MULTI_FRAME
451 choose_minibuf_frame ();
452 #endif
453
454 f = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
455
456 if (! FRAME_VISIBLE_P (f))
457 return;
458
459 if (frame_garbaged)
460 {
461 redraw_garbaged_frames ();
462 frame_garbaged = 0;
463 }
464
465 if (echo_area_glyphs || minibuf_level == 0)
466 {
467 vpos = XFASTINT (XWINDOW (minibuf_window)->top);
468 get_display_line (f, vpos, 0);
469 display_string (XWINDOW (minibuf_window), vpos,
470 echo_area_glyphs ? echo_area_glyphs : "",
471 echo_area_glyphs ? echo_area_glyphs_length : -1,
472 0, 0, 0, 0, FRAME_WIDTH (f));
473
474 /* If desired cursor location is on this line, put it at end of text */
475 if (FRAME_CURSOR_Y (f) == vpos)
476 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
477
478 /* Fill the rest of the minibuffer window with blank lines. */
479 {
480 int i;
481
482 for (i = vpos + 1;
483 i < vpos + XFASTINT (XWINDOW (minibuf_window)->height); i++)
484 {
485 get_display_line (f, i, 0);
486 display_string (XWINDOW (minibuf_window), vpos,
487 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f));
488 }
489 }
490 }
491 else if (!EQ (minibuf_window, selected_window))
492 windows_or_buffers_changed++;
493
494 if (EQ (minibuf_window, selected_window))
495 this_line_bufpos = 0;
496
497 previous_echo_glyphs = echo_area_glyphs;
498 }
499
500 #ifdef HAVE_X_WINDOWS
501 static char frame_title_buf[512];
502 static char *frame_title_ptr;
503
504 static int
505 store_frame_title (str, mincol, maxcol)
506 char *str;
507 int mincol, maxcol;
508 {
509 char *limit;
510 if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
511 maxcol = sizeof (frame_title_buf);
512 limit = &frame_title_buf[maxcol];
513 while (*str != '\0' && frame_title_ptr < limit)
514 *frame_title_ptr++ = *str++;
515 while (frame_title_ptr < &frame_title_buf[mincol])
516 *frame_title_ptr++ = ' ';
517 return frame_title_ptr - frame_title_buf;
518 }
519
520 static void
521 x_consider_frame_title (frame)
522 Lisp_Object frame;
523 {
524 Lisp_Object fmt;
525 struct buffer *obuf;
526 int len;
527 FRAME_PTR f = XFRAME (frame);
528
529 if (!FRAME_X_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name)
530 return;
531 multiple_frames = !EQ (Fnext_frame (frame, Qnil), frame);
532 obuf = current_buffer;
533 Fset_buffer (XWINDOW (f->selected_window)->buffer);
534 fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
535 frame_title_ptr = frame_title_buf;
536 len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
537 0, sizeof (frame_title_buf), fmt);
538 frame_title_ptr = 0;
539 set_buffer_internal (obuf);
540 /* Set the name only if it's changed. This avoids consing
541 in the common case where it hasn't. (If it turns out that we've
542 already wasted too much time by walking through the list with
543 display_mode_element, then we might need to optimize at a higher
544 level than this.) */
545 if (! STRINGP (f->name) || XSTRING (f->name)->size != len
546 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
547 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
548 }
549 #else
550 #define frame_title_ptr ((char *)0)
551 #define store_frame_title(str, mincol, maxcol) 0
552 #endif
553 \f
554 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
555 This can't be done in `redisplay' itself because it can call eval. */
556
557 void
558 prepare_menu_bars ()
559 {
560 register struct window *w = XWINDOW (selected_window);
561 int all_windows;
562
563 if (noninteractive)
564 return;
565
566 /* Set the visible flags for all frames.
567 Do this before checking for resized or garbaged frames; they want
568 to know if their frames are visible.
569 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
570 {
571 Lisp_Object tail, frame;
572
573 FOR_EACH_FRAME (tail, frame)
574 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
575 }
576
577 /* Notice any pending interrupt request to change frame size. */
578 do_pending_window_change ();
579
580 if (frame_garbaged)
581 {
582 redraw_garbaged_frames ();
583 frame_garbaged = 0;
584 }
585
586 all_windows = (update_mode_lines || buffer_shared > 1
587 || clip_changed || windows_or_buffers_changed);
588
589 #ifdef HAVE_X_WINDOWS
590 if (windows_or_buffers_changed)
591 {
592 Lisp_Object tail, frame;
593
594 FOR_EACH_FRAME (tail, frame)
595 if (FRAME_VISIBLE_P (XFRAME (frame))
596 || FRAME_ICONIFIED_P (XFRAME (frame)))
597 x_consider_frame_title (frame);
598 }
599 #endif
600
601 /* Update the menu bar item lists, if appropriate.
602 This has to be done before any actual redisplay
603 or generation of display lines. */
604 if (all_windows)
605 {
606 Lisp_Object tail, frame;
607
608 FOR_EACH_FRAME (tail, frame)
609 update_menu_bar (XFRAME (frame));
610 }
611 else
612 update_menu_bar (selected_frame);
613 }
614 \f
615 /* Do a frame update, taking possible shortcuts into account.
616 This is the main external entry point for redisplay.
617
618 If the last redisplay displayed an echo area message and that
619 message is no longer requested, we clear the echo area
620 or bring back the minibuffer if that is in use.
621
622 Do not call eval from within this function.
623 Calls to eval after the call to echo_area_display would confuse
624 the display_line mechanism and would cause a crash.
625 Calls to eval before that point will work most of the time,
626 but can still lose, because this function
627 can be called from signal handlers; with alarms set up;
628 or with synchronous processes running.
629
630 See Fcall_process; if you called it from here, it could be
631 entered recursively. */
632
633 static int do_verify_charstarts;
634
635 /* Counter is used to clear the face cache
636 no more than once ever 1000 redisplays. */
637 static int clear_face_cache_count;
638
639 void
640 redisplay ()
641 {
642 register struct window *w = XWINDOW (selected_window);
643 register int pause;
644 int must_finish = 0;
645 int all_windows;
646 register int tlbufpos, tlendpos;
647 struct position pos;
648 extern int input_pending;
649
650 if (noninteractive)
651 return;
652
653 /* Set the visible flags for all frames.
654 Do this before checking for resized or garbaged frames; they want
655 to know if their frames are visible.
656 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
657 {
658 Lisp_Object tail, frame;
659
660 FOR_EACH_FRAME (tail, frame)
661 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
662 }
663
664 /* Notice any pending interrupt request to change frame size. */
665 do_pending_window_change ();
666
667 if (frame_garbaged)
668 {
669 redraw_garbaged_frames ();
670 frame_garbaged = 0;
671 }
672
673 if (clip_changed || windows_or_buffers_changed
674 || (!NILP (w->column_number_displayed)
675 && XFASTINT (w->column_number_displayed) != current_column ()))
676 update_mode_lines++;
677
678 /* Detect case that we need to write a star in the mode line. */
679 if (XFASTINT (w->last_modified) < MODIFF
680 && XFASTINT (w->last_modified) <= SAVE_MODIFF)
681 {
682 w->update_mode_line = Qt;
683 if (buffer_shared > 1)
684 update_mode_lines++;
685 }
686
687 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
688
689 all_windows = update_mode_lines || buffer_shared > 1;
690
691 /* If specs for an arrow have changed, do thorough redisplay
692 to ensure we remove any arrow that should no longer exist. */
693 if (! EQ (Voverlay_arrow_position, last_arrow_position)
694 || ! EQ (Voverlay_arrow_string, last_arrow_string))
695 all_windows = 1, clip_changed = 1;
696
697 /* Normally the message* functions will have already displayed and
698 updated the echo area, but the frame may have been trashed, or
699 the update may have been preempted, so display the echo area
700 again here. */
701 if (echo_area_glyphs || previous_echo_glyphs)
702 {
703 echo_area_display ();
704 must_finish = 1;
705 }
706
707 /* If showing region, and mark has changed, must redisplay whole window. */
708 if (((!NILP (Vtransient_mark_mode)
709 && !NILP (XBUFFER (w->buffer)->mark_active))
710 != !NILP (w->region_showing))
711 || (!NILP (w->region_showing)
712 && !EQ (w->region_showing,
713 Fmarker_position (XBUFFER (w->buffer)->mark))))
714 this_line_bufpos = -1;
715
716 tlbufpos = this_line_bufpos;
717 tlendpos = this_line_endpos;
718 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
719 && FRAME_VISIBLE_P (XFRAME (w->frame))
720 /* Make sure recorded data applies to current buffer, etc */
721 && this_line_buffer == current_buffer
722 && current_buffer == XBUFFER (w->buffer)
723 && NILP (w->force_start)
724 /* Point must be on the line that we have info recorded about */
725 && PT >= tlbufpos
726 && PT <= Z - tlendpos
727 /* All text outside that line, including its final newline,
728 must be unchanged */
729 && (XFASTINT (w->last_modified) >= MODIFF
730 || (beg_unchanged >= tlbufpos - 1
731 && GPT >= tlbufpos
732 /* If selective display, can't optimize
733 if the changes start at the beginning of the line. */
734 && ((INTEGERP (current_buffer->selective_display)
735 && XINT (current_buffer->selective_display) > 0
736 ? (beg_unchanged >= tlbufpos
737 && GPT > tlbufpos)
738 : 1))
739 && end_unchanged >= tlendpos
740 && Z - GPT >= tlendpos)))
741 {
742 if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n'
743 && (tlbufpos == ZV
744 || FETCH_CHAR (tlbufpos) == '\n'))
745 /* Former continuation line has disappeared by becoming empty */
746 goto cancel;
747 else if (XFASTINT (w->last_modified) < MODIFF
748 || MINI_WINDOW_P (w))
749 {
750 cursor_vpos = -1;
751 overlay_arrow_seen = 0;
752 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
753 pos_tab_offset (w, tlbufpos));
754 /* If line contains point, is not continued,
755 and ends at same distance from eob as before, we win */
756 if (cursor_vpos >= 0 && this_line_bufpos
757 && this_line_endpos == tlendpos)
758 {
759 /* If this is not the window's last line,
760 we must adjust the charstarts of the lines below. */
761 if (this_line_vpos + 1
762 < XFASTINT (w->top) + window_internal_height (w))
763 {
764 int left = XFASTINT (w->left);
765 int *charstart_next_line
766 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
767 int i;
768 int adjust;
769
770 if (Z - tlendpos == ZV)
771 /* This line ends at end of (accessible part of) buffer.
772 There is no newline to count. */
773 adjust = Z - tlendpos - charstart_next_line[left];
774 else
775 /* This line ends in a newline.
776 Must take account of the newline and the rest of the
777 text that follows. */
778 adjust = Z - tlendpos + 1 - charstart_next_line[left];
779
780 adjust_window_charstarts (w, this_line_vpos, adjust);
781 }
782
783 if (XFASTINT (w->width) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
784 preserve_other_columns (w);
785 goto update;
786 }
787 else
788 goto cancel;
789 }
790 else if (PT == XFASTINT (w->last_point))
791 {
792 if (!must_finish)
793 {
794 do_pending_window_change ();
795 return;
796 }
797 goto update;
798 }
799 /* If highlighting the region, we can't just move the cursor. */
800 else if (! (!NILP (Vtransient_mark_mode)
801 && !NILP (current_buffer->mark_active))
802 && NILP (w->region_showing))
803 {
804 pos = *compute_motion (tlbufpos, 0,
805 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
806 PT, 2, - (1 << (SHORTBITS - 1)),
807 window_internal_width (w) - 1,
808 XINT (w->hscroll),
809 pos_tab_offset (w, tlbufpos), w);
810 if (pos.vpos < 1)
811 {
812 FRAME_CURSOR_X (selected_frame)
813 = XFASTINT (w->left) + max (pos.hpos, 0);
814 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
815 goto update;
816 }
817 else
818 goto cancel;
819 }
820 cancel:
821 /* Text changed drastically or point moved off of line */
822 cancel_line (this_line_vpos, selected_frame);
823 }
824
825 this_line_bufpos = 0;
826 all_windows |= buffer_shared > 1;
827
828 clear_face_cache_count++;
829
830 if (all_windows)
831 {
832 Lisp_Object tail, frame;
833
834 #ifdef HAVE_FACES
835 /* Clear the face cache, only when we do a full redisplay
836 and not too often either. */
837 if (clear_face_cache_count > 1000)
838 {
839 clear_face_cache ();
840 clear_face_cache_count = 0;
841 }
842 #endif
843
844 /* Recompute # windows showing selected buffer.
845 This will be incremented each time such a window is displayed. */
846 buffer_shared = 0;
847
848 FOR_EACH_FRAME (tail, frame)
849 {
850 FRAME_PTR f = XFRAME (frame);
851
852 /* Mark all the scroll bars to be removed; we'll redeem the ones
853 we want when we redisplay their windows. */
854 if (condemn_scroll_bars_hook)
855 (*condemn_scroll_bars_hook) (f);
856
857 if (FRAME_VISIBLE_P (f))
858 redisplay_windows (FRAME_ROOT_WINDOW (f));
859
860 /* Any scroll bars which redisplay_windows should have nuked
861 should now go away. */
862 if (judge_scroll_bars_hook)
863 (*judge_scroll_bars_hook) (f);
864 }
865 }
866 else if (FRAME_VISIBLE_P (selected_frame))
867 {
868 redisplay_window (selected_window, 1);
869 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
870 preserve_other_columns (w);
871 }
872
873 update:
874 /* Prevent various kinds of signals during display update.
875 stdio is not robust about handling signals,
876 which can cause an apparent I/O error. */
877 if (interrupt_input)
878 unrequest_sigio ();
879 stop_polling ();
880
881 #ifdef MULTI_FRAME
882 if (all_windows)
883 {
884 Lisp_Object tail;
885
886 pause = 0;
887
888 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
889 {
890 FRAME_PTR f;
891
892 if (!FRAMEP (XCONS (tail)->car))
893 continue;
894
895 f = XFRAME (XCONS (tail)->car);
896 if (FRAME_VISIBLE_P (f))
897 {
898 pause |= update_frame (f, 0, 0);
899 if (!pause)
900 {
901 mark_window_display_accurate (f->root_window, 1);
902 if (frame_up_to_date_hook != 0)
903 (*frame_up_to_date_hook) (f);
904 }
905 }
906 }
907 }
908 else
909 #endif /* MULTI_FRAME */
910 {
911 if (FRAME_VISIBLE_P (selected_frame))
912 pause = update_frame (selected_frame, 0, 0);
913
914 /* We may have called echo_area_display at the top of this
915 function. If the echo area is on another frame, that may
916 have put text on a frame other than the selected one, so the
917 above call to update_frame would not have caught it. Catch
918 it here. */
919 {
920 FRAME_PTR mini_frame
921 = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
922
923 if (mini_frame != selected_frame)
924 pause |= update_frame (mini_frame, 0, 0);
925 }
926 }
927
928 /* If frame does not match, prevent doing single-line-update next time.
929 Also, don't forget to check every line to update the arrow. */
930 if (pause)
931 {
932 this_line_bufpos = 0;
933 if (!NILP (last_arrow_position))
934 {
935 last_arrow_position = Qt;
936 last_arrow_string = Qt;
937 }
938 /* If we pause after scrolling, some lines in current_frame
939 may be null, so preserve_other_columns won't be able to
940 preserve all the vertical-bar separators. So, avoid using it
941 in that case. */
942 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
943 update_mode_lines = 1;
944 }
945
946 /* Now text on frame agrees with windows, so
947 put info into the windows for partial redisplay to follow */
948
949 if (!pause)
950 {
951 register struct buffer *b = XBUFFER (w->buffer);
952
953 blank_end_of_window = 0;
954 clip_changed = 0;
955 unchanged_modified = BUF_MODIFF (b);
956 beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
957 end_unchanged = BUF_Z (b) - BUF_GPT (b);
958
959 XSETFASTINT (w->last_point, BUF_PT (b));
960 XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
961 XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
962
963 if (all_windows)
964 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
965 else
966 {
967 w->update_mode_line = Qnil;
968 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
969 w->window_end_valid = w->buffer;
970 last_arrow_position = Voverlay_arrow_position;
971 last_arrow_string = Voverlay_arrow_string;
972 if (do_verify_charstarts)
973 verify_charstarts (w);
974 if (frame_up_to_date_hook != 0)
975 (*frame_up_to_date_hook) (selected_frame);
976 }
977 update_mode_lines = 0;
978 windows_or_buffers_changed = 0;
979 }
980
981 /* Start SIGIO interrupts coming again.
982 Having them off during the code above
983 makes it less likely one will discard output,
984 but not impossible, since there might be stuff
985 in the system buffer here.
986 But it is much hairier to try to do anything about that. */
987
988 if (interrupt_input)
989 request_sigio ();
990 start_polling ();
991
992 /* Change frame size now if a change is pending. */
993 do_pending_window_change ();
994
995 /* If we just did a pending size change, redisplay again
996 for the new size. */
997 if (windows_or_buffers_changed && !pause)
998 redisplay ();
999 }
1000
1001 /* Redisplay, but leave alone any recent echo area message
1002 unless another message has been requested in its place.
1003
1004 This is useful in situations where you need to redisplay but no
1005 user action has occurred, making it inappropriate for the message
1006 area to be cleared. See tracking_off and
1007 wait_reading_process_input for examples of these situations. */
1008
1009 redisplay_preserve_echo_area ()
1010 {
1011 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
1012 {
1013 echo_area_glyphs = previous_echo_glyphs;
1014 redisplay ();
1015 echo_area_glyphs = 0;
1016 }
1017 else
1018 redisplay ();
1019 }
1020
1021 void
1022 mark_window_display_accurate (window, flag)
1023 Lisp_Object window;
1024 int flag;
1025 {
1026 register struct window *w;
1027
1028 for (;!NILP (window); window = w->next)
1029 {
1030 if (!WINDOWP (window)) abort ();
1031 w = XWINDOW (window);
1032
1033 if (!NILP (w->buffer))
1034 {
1035 XSETFASTINT (w->last_modified,
1036 !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
1037
1038 /* Record if we are showing a region, so can make sure to
1039 update it fully at next redisplay. */
1040 w->region_showing = (!NILP (Vtransient_mark_mode)
1041 && !NILP (XBUFFER (w->buffer)->mark_active)
1042 ? Fmarker_position (XBUFFER (w->buffer)->mark)
1043 : Qnil);
1044 }
1045
1046 w->window_end_valid = w->buffer;
1047 w->update_mode_line = Qnil;
1048
1049 if (!NILP (w->vchild))
1050 mark_window_display_accurate (w->vchild, flag);
1051 if (!NILP (w->hchild))
1052 mark_window_display_accurate (w->hchild, flag);
1053 }
1054
1055 if (flag)
1056 {
1057 last_arrow_position = Voverlay_arrow_position;
1058 last_arrow_string = Voverlay_arrow_string;
1059 }
1060 else
1061 {
1062 /* t is unequal to any useful value of Voverlay_arrow_... */
1063 last_arrow_position = Qt;
1064 last_arrow_string = Qt;
1065 }
1066 }
1067 \f
1068 /* Update the menu bar item list for frame F.
1069 This has to be done before we start to fill in any display lines,
1070 because it can call eval. */
1071
1072 static void
1073 update_menu_bar (f)
1074 FRAME_PTR f;
1075 {
1076 struct buffer *old = current_buffer;
1077 Lisp_Object window;
1078 register struct window *w;
1079 window = FRAME_SELECTED_WINDOW (f);
1080 w = XWINDOW (window);
1081
1082 if (update_mode_lines)
1083 w->update_mode_line = Qt;
1084
1085 if (
1086 #ifdef USE_X_TOOLKIT
1087 FRAME_EXTERNAL_MENU_BAR (f)
1088 #else
1089 FRAME_MENU_BAR_LINES (f) > 0
1090 #endif
1091 )
1092 {
1093 /* If the user has switched buffers or windows, we need to
1094 recompute to reflect the new bindings. But we'll
1095 recompute when update_mode_lines is set too; that means
1096 that people can use force-mode-line-update to request
1097 that the menu bar be recomputed. The adverse effect on
1098 the rest of the redisplay algorithm is about the same as
1099 windows_or_buffers_changed anyway. */
1100 if (windows_or_buffers_changed
1101 || !NILP (w->update_mode_line)
1102 || (XFASTINT (w->last_modified) < MODIFF
1103 && (XFASTINT (w->last_modified)
1104 <= BUF_SAVE_MODIFF (XBUFFER (w->buffer)))))
1105 {
1106 struct buffer *prev = current_buffer;
1107 call1 (Vrun_hooks, Qmenu_bar_update_hook);
1108 current_buffer = XBUFFER (w->buffer);
1109 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1110 current_buffer = prev;
1111 #ifdef USE_X_TOOLKIT
1112 set_frame_menubar (f, 0);
1113 #endif /* USE_X_TOOLKIT */
1114 }
1115 }
1116 }
1117 \f
1118 int do_id = 1;
1119
1120 /* Redisplay WINDOW and its subwindows and siblings. */
1121
1122 static void
1123 redisplay_windows (window)
1124 Lisp_Object window;
1125 {
1126 for (; !NILP (window); window = XWINDOW (window)->next)
1127 redisplay_window (window, 0);
1128 }
1129
1130 /* Redisplay window WINDOW and its subwindows. */
1131
1132 static void
1133 redisplay_window (window, just_this_one)
1134 Lisp_Object window;
1135 int just_this_one;
1136 {
1137 register struct window *w = XWINDOW (window);
1138 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
1139 int height;
1140 register int lpoint = PT;
1141 struct buffer *old = current_buffer;
1142 register int width = window_internal_width (w) - 1;
1143 register int startp;
1144 register int hscroll = XINT (w->hscroll);
1145 struct position pos;
1146 int opoint = PT;
1147 int tem;
1148 int window_needs_modeline;
1149
1150 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1151
1152 /* If this is a combination window, do its children; that's all. */
1153
1154 if (!NILP (w->vchild))
1155 {
1156 redisplay_windows (w->vchild);
1157 return;
1158 }
1159 if (!NILP (w->hchild))
1160 {
1161 redisplay_windows (w->hchild);
1162 return;
1163 }
1164 if (NILP (w->buffer))
1165 abort ();
1166
1167 height = window_internal_height (w);
1168
1169 if (MINI_WINDOW_P (w))
1170 {
1171 if (w == XWINDOW (minibuf_window))
1172 {
1173 if (echo_area_glyphs)
1174 /* We've already displayed the echo area glyphs, if any. */
1175 goto finish_scroll_bars;
1176 }
1177 else
1178 {
1179 /* This is a minibuffer, but it's not the currently active one, so
1180 clear it. */
1181 int vpos = XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1182 int i;
1183
1184 for (i = 0; i < height; i++)
1185 {
1186 get_display_line (f, vpos + i, 0);
1187 display_string (w, vpos + i, "", 0, 0, 0, 1, 0, width);
1188 }
1189
1190 goto finish_scroll_bars;
1191 }
1192 }
1193
1194 if (update_mode_lines)
1195 w->update_mode_line = Qt;
1196
1197 /* Otherwise set up data on this window; select its buffer and point value */
1198
1199 set_buffer_temp (XBUFFER (w->buffer));
1200 opoint = PT;
1201
1202 /* Count number of windows showing the selected buffer.
1203 An indirect buffer counts as its base buffer. */
1204
1205 if (!just_this_one)
1206 {
1207 struct buffer *current_base, *window_base;
1208 current_base = current_buffer;
1209 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
1210 if (current_base->base_buffer)
1211 current_base = current_base->base_buffer;
1212 if (window_base->base_buffer)
1213 window_base = window_base->base_buffer;
1214 if (current_base == window_base)
1215 buffer_shared++;
1216 }
1217
1218 /* POINT refers normally to the selected window.
1219 For any other window, set up appropriate value. */
1220
1221 if (!EQ (window, selected_window))
1222 {
1223 int new_pt = marker_position (w->pointm);
1224 if (new_pt < BEGV)
1225 {
1226 new_pt = BEGV;
1227 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1228 }
1229 else if (new_pt > (ZV - 1))
1230 {
1231 new_pt = ZV;
1232 Fset_marker (w->pointm, make_number (new_pt), Qnil);
1233 }
1234 /* We don't use SET_PT so that the point-motion hooks don't run. */
1235 BUF_PT (current_buffer) = new_pt;
1236 }
1237
1238 /* If any of the character widths specified in the display table
1239 have changed, invalidate the width run cache. It's true that this
1240 may be a bit late to catch such changes, but the rest of
1241 redisplay goes (non-fatally) haywire when the display table is
1242 changed, so why should we worry about doing any better? */
1243 if (current_buffer->width_run_cache)
1244 {
1245 struct Lisp_Vector *disptab = buffer_display_table ();
1246
1247 if (! disptab_matches_widthtab (disptab,
1248 XVECTOR (current_buffer->width_table)))
1249 {
1250 invalidate_region_cache (current_buffer,
1251 current_buffer->width_run_cache,
1252 BEG, Z);
1253 recompute_width_table (current_buffer, disptab);
1254 }
1255 }
1256
1257 /* If window-start is screwed up, choose a new one. */
1258 if (XMARKER (w->start)->buffer != current_buffer)
1259 goto recenter;
1260
1261 startp = marker_position (w->start);
1262
1263 /* Handle case where place to start displaying has been specified,
1264 unless the specified location is outside the accessible range. */
1265 if (!NILP (w->force_start))
1266 {
1267 /* Forget any recorded base line for line number display. */
1268 w->base_line_number = Qnil;
1269 w->update_mode_line = Qt;
1270 w->force_start = Qnil;
1271 XSETFASTINT (w->last_modified, 0);
1272 if (startp < BEGV) startp = BEGV;
1273 if (startp > ZV) startp = ZV;
1274 try_window (window, startp);
1275 if (cursor_vpos < 0)
1276 {
1277 /* If point does not appear, move point so it does appear */
1278 pos = *compute_motion (startp, 0,
1279 ((EQ (window, minibuf_window) && startp == 1)
1280 ? minibuf_prompt_width : 0)
1281 +
1282 (hscroll ? 1 - hscroll : 0),
1283 ZV, height / 2,
1284 - (1 << (SHORTBITS - 1)),
1285 width, hscroll, pos_tab_offset (w, startp), w);
1286 BUF_PT (current_buffer) = pos.bufpos;
1287 if (w != XWINDOW (selected_window))
1288 Fset_marker (w->pointm, make_number (PT), Qnil);
1289 else
1290 {
1291 if (current_buffer == old)
1292 lpoint = PT;
1293 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1294 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1295 }
1296 /* If we are highlighting the region,
1297 then we just changed the region, so redisplay to show it. */
1298 if (!NILP (Vtransient_mark_mode)
1299 && !NILP (current_buffer->mark_active))
1300 {
1301 cancel_my_columns (XWINDOW (window));
1302 try_window (window, startp);
1303 }
1304 }
1305 goto done;
1306 }
1307
1308 /* Handle case where text has not changed, only point,
1309 and it has not moved off the frame */
1310
1311 /* This code is not used for minibuffer for the sake of
1312 the case of redisplaying to replace an echo area message;
1313 since in that case the minibuffer contents per se are usually unchanged.
1314 This code is of no real use in the minibuffer since
1315 the handling of this_line_bufpos, etc.,
1316 in redisplay handles the same cases. */
1317
1318 if (XFASTINT (w->last_modified) >= MODIFF
1319 && PT >= startp && !clip_changed
1320 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
1321 /* Can't use this case if highlighting a region. */
1322 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1323 && NILP (w->region_showing)
1324 /* If end pos is out of date, scroll bar and percentage will be wrong */
1325 && INTEGERP (w->window_end_vpos)
1326 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
1327 && !EQ (window, minibuf_window))
1328 {
1329 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
1330 PT, height + 1, 10000, width, hscroll,
1331 pos_tab_offset (w, startp), w);
1332
1333 if (pos.vpos < height)
1334 {
1335 /* Ok, point is still on frame */
1336 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1337 {
1338 /* These variables are supposed to be origin 1 */
1339 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1340 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1341 }
1342 /* This doesn't do the trick, because if a window to the right of
1343 this one must be redisplayed, this does nothing because there
1344 is nothing in DesiredFrame yet, and then the other window is
1345 redisplayed, making likes that are empty in this window's columns.
1346 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1347 preserve_my_columns (w);
1348 */
1349 goto done;
1350 }
1351 /* Don't bother trying redisplay with same start;
1352 we already know it will lose */
1353 }
1354 /* If current starting point was originally the beginning of a line
1355 but no longer is, find a new starting point. */
1356 else if (!NILP (w->start_at_line_beg)
1357 && !(startp <= BEGV
1358 || FETCH_CHAR (startp - 1) == '\n'))
1359 {
1360 goto recenter;
1361 }
1362 else if (just_this_one && !MINI_WINDOW_P (w)
1363 && PT >= startp
1364 && XFASTINT (w->last_modified)
1365 /* or else vmotion on first line won't work. */
1366 && ! NILP (w->start_at_line_beg)
1367 && ! EQ (w->window_end_valid, Qnil)
1368 && do_id && !clip_changed
1369 && !blank_end_of_window
1370 && XFASTINT (w->width) == FRAME_WIDTH (f)
1371 /* Can't use this case if highlighting a region. */
1372 && !(!NILP (Vtransient_mark_mode)
1373 && !NILP (current_buffer->mark_active))
1374 && NILP (w->region_showing)
1375 && EQ (last_arrow_position, Voverlay_arrow_position)
1376 && EQ (last_arrow_string, Voverlay_arrow_string)
1377 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
1378 && tem != -2)
1379 {
1380 /* tem > 0 means success. tem == -1 means choose new start.
1381 tem == -2 means try again with same start,
1382 and nothing but whitespace follows the changed stuff.
1383 tem == 0 means try again with same start. */
1384 if (tem > 0)
1385 goto done;
1386 }
1387 else if (startp >= BEGV && startp <= ZV
1388 /* Avoid starting display at end of buffer! */
1389 && (startp < ZV || startp == BEGV
1390 || (XFASTINT (w->last_modified) >= MODIFF)))
1391 {
1392 /* Try to redisplay starting at same place as before */
1393 /* If point has not moved off frame, accept the results */
1394 try_window (window, startp);
1395 if (cursor_vpos >= 0)
1396 {
1397 if (!just_this_one || clip_changed || beg_unchanged < startp)
1398 /* Forget any recorded base line for line number display. */
1399 w->base_line_number = Qnil;
1400 goto done;
1401 }
1402 else
1403 cancel_my_columns (w);
1404 }
1405
1406 XSETFASTINT (w->last_modified, 0);
1407 w->update_mode_line = Qt;
1408
1409 /* Try to scroll by specified few lines */
1410
1411 if (scroll_step && !clip_changed)
1412 {
1413 if (PT > startp)
1414 {
1415 pos = *vmotion (Z - XFASTINT (w->window_end_pos),
1416 scroll_step, width, hscroll, window);
1417 if (pos.vpos >= height)
1418 goto scroll_fail;
1419 }
1420
1421 pos = *vmotion (startp, PT < startp ? - scroll_step : scroll_step,
1422 width, hscroll, window);
1423
1424 if (PT >= pos.bufpos)
1425 {
1426 try_window (window, pos.bufpos);
1427 if (cursor_vpos >= 0)
1428 {
1429 if (!just_this_one || clip_changed || beg_unchanged < startp)
1430 /* Forget any recorded base line for line number display. */
1431 w->base_line_number = Qnil;
1432 goto done;
1433 }
1434 else
1435 cancel_my_columns (w);
1436 }
1437 scroll_fail: ;
1438 }
1439
1440 /* Finally, just choose place to start which centers point */
1441
1442 recenter:
1443 /* Forget any previously recorded base line for line number display. */
1444 w->base_line_number = Qnil;
1445
1446 pos = *vmotion (PT, - (height / 2), width, hscroll, window);
1447 try_window (window, pos.bufpos);
1448
1449 startp = marker_position (w->start);
1450 w->start_at_line_beg
1451 = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
1452
1453 done:
1454 if ((!NILP (w->update_mode_line)
1455 /* If window not full width, must redo its mode line
1456 if the window to its side is being redone */
1457 || (!just_this_one && width < FRAME_WIDTH (f) - 1)
1458 || INTEGERP (w->base_line_pos)
1459 || (!NILP (w->column_number_displayed)
1460 && XFASTINT (w->column_number_displayed) != current_column ()))
1461 && height != XFASTINT (w->height))
1462 display_mode_line (w);
1463 if (! line_number_displayed
1464 && ! BUFFERP (w->base_line_pos))
1465 {
1466 w->base_line_pos = Qnil;
1467 w->base_line_number = Qnil;
1468 }
1469
1470 /* When we reach a frame's selected window, redo the frame's menu bar. */
1471 if (!NILP (w->update_mode_line)
1472 #ifdef USE_X_TOOLKIT
1473 && FRAME_EXTERNAL_MENU_BAR (f)
1474 #else
1475 && FRAME_MENU_BAR_LINES (f) > 0
1476 #endif
1477 && EQ (FRAME_SELECTED_WINDOW (f), window))
1478 display_menu_bar (w);
1479
1480 finish_scroll_bars:
1481 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1482 {
1483 int start, end, whole;
1484
1485 /* Calculate the start and end positions for the current window.
1486 At some point, it would be nice to choose between scrollbars
1487 which reflect the whole buffer size, with special markers
1488 indicating narrowing, and scrollbars which reflect only the
1489 visible region.
1490
1491 Note that minibuffers sometimes aren't displaying any text. */
1492 if (! MINI_WINDOW_P (w)
1493 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
1494 {
1495 whole = ZV - BEGV;
1496 start = startp - BEGV;
1497 /* I don't think this is guaranteed to be right. For the
1498 moment, we'll pretend it is. */
1499 end = (Z - XINT (w->window_end_pos)) - BEGV;
1500
1501 if (end < start) end = start;
1502 if (whole < (end - start)) whole = end - start;
1503 }
1504 else
1505 start = end = whole = 0;
1506
1507 /* Indicate what this scroll bar ought to be displaying now. */
1508 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
1509
1510 /* Note that we actually used the scroll bar attached to this window,
1511 so it shouldn't be deleted at the end of redisplay. */
1512 (*redeem_scroll_bar_hook) (w);
1513 }
1514
1515 BUF_PT (current_buffer) = opoint;
1516 set_buffer_temp (old);
1517 BUF_PT (current_buffer) = lpoint;
1518 }
1519 \f
1520 /* Do full redisplay on one window, starting at position `pos'. */
1521
1522 static void
1523 try_window (window, pos)
1524 Lisp_Object window;
1525 register int pos;
1526 {
1527 register struct window *w = XWINDOW (window);
1528 register int height = window_internal_height (w);
1529 register int vpos = XFASTINT (w->top);
1530 register int last_text_vpos = vpos;
1531 int tab_offset = pos_tab_offset (w, pos);
1532 FRAME_PTR f = XFRAME (w->frame);
1533 int width = window_internal_width (w) - 1;
1534 struct position val;
1535
1536 Fset_marker (w->start, make_number (pos), Qnil);
1537 cursor_vpos = -1;
1538 overlay_arrow_seen = 0;
1539 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
1540
1541 while (--height >= 0)
1542 {
1543 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
1544 tab_offset += width;
1545 /* For the first line displayed, display_text_line
1546 subtracts the prompt width from the tab offset.
1547 But it does not affect the value of our variable tab_offset.
1548 So we do the subtraction again,
1549 for the sake of continuation lines of that first line. */
1550 if (MINI_WINDOW_P (w) && vpos == XFASTINT (w->top))
1551 tab_offset -= minibuf_prompt_width;
1552
1553 if (val.vpos) tab_offset = 0;
1554 vpos++;
1555 if (pos != val.bufpos)
1556 last_text_vpos
1557 /* Next line, unless prev line ended in end of buffer with no cr */
1558 = vpos - (val.vpos && (FETCH_CHAR (val.bufpos - 1) != '\n'
1559 #ifdef USE_TEXT_PROPERTIES
1560 || ! NILP (Fget_char_property (val.bufpos-1,
1561 Qinvisible,
1562 window))
1563 #endif
1564 ));
1565 pos = val.bufpos;
1566 }
1567
1568 /* If last line is continued in middle of character,
1569 include the split character in the text considered on the frame */
1570 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
1571 pos++;
1572
1573 /* If bottom just moved off end of frame, change mode line percentage. */
1574 if (XFASTINT (w->window_end_pos) == 0
1575 && Z != pos)
1576 w->update_mode_line = Qt;
1577
1578 /* Say where last char on frame will be, once redisplay is finished. */
1579 XSETFASTINT (w->window_end_pos, Z - pos);
1580 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
1581 /* But that is not valid info until redisplay finishes. */
1582 w->window_end_valid = Qnil;
1583 }
1584 \f
1585 /* Try to redisplay when buffer is modified locally,
1586 computing insert/delete line to preserve text outside
1587 the bounds of the changes.
1588 Return 1 if successful, 0 if if cannot tell what to do,
1589 or -1 to tell caller to find a new window start,
1590 or -2 to tell caller to do normal redisplay with same window start. */
1591
1592 static int
1593 try_window_id (window)
1594 Lisp_Object window;
1595 {
1596 int pos;
1597 register struct window *w = XWINDOW (window);
1598 register int height = window_internal_height (w);
1599 FRAME_PTR f = XFRAME (w->frame);
1600 int top = XFASTINT (w->top);
1601 int start = marker_position (w->start);
1602 int width = window_internal_width (w) - 1;
1603 int hscroll = XINT (w->hscroll);
1604 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1605 register int vpos;
1606 register int i, tem;
1607 int last_text_vpos = 0;
1608 int stop_vpos;
1609 int selective = (INTEGERP (current_buffer->selective_display)
1610 ? XINT (current_buffer->selective_display)
1611 : !NILP (current_buffer->selective_display) ? -1 : 0);
1612
1613 struct position val, bp, ep, xp, pp;
1614 int scroll_amount = 0;
1615 int delta;
1616 int tab_offset, epto;
1617
1618 if (GPT - BEG < beg_unchanged)
1619 beg_unchanged = GPT - BEG;
1620 if (Z - GPT < end_unchanged)
1621 end_unchanged = Z - GPT;
1622
1623 if (beg_unchanged + BEG < start)
1624 return 0; /* Give up if changes go above top of window */
1625
1626 /* Find position before which nothing is changed. */
1627 bp = *compute_motion (start, 0, lmargin,
1628 min (ZV, beg_unchanged + BEG), height + 1, 0,
1629 width, hscroll, pos_tab_offset (w, start), w);
1630 if (bp.vpos >= height)
1631 {
1632 if (PT < bp.bufpos && !bp.contin)
1633 {
1634 /* All changes are below the frame, and point is on the frame.
1635 We don't need to change the frame at all.
1636 But we need to update window_end_pos to account for
1637 any change in buffer size. */
1638 bp = *compute_motion (start, 0, lmargin,
1639 Z, height, 0,
1640 width, hscroll, pos_tab_offset (w, start), w);
1641 XSETFASTINT (w->window_end_vpos, height);
1642 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
1643 return 1;
1644 }
1645 return 0;
1646 }
1647
1648 vpos = bp.vpos;
1649
1650 /* Find beginning of that frame line. Must display from there. */
1651 bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
1652
1653 pos = bp.bufpos;
1654 val.hpos = lmargin;
1655 if (pos < start)
1656 return -1;
1657
1658 /* If about to start displaying at the beginning of a continuation line,
1659 really start with previous frame line, in case it was not
1660 continued when last redisplayed */
1661 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
1662 ||
1663 /* Likewise if we have to worry about selective display. */
1664 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
1665 {
1666 bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
1667 --vpos;
1668 pos = bp.bufpos;
1669 }
1670
1671 if (bp.contin && bp.hpos != lmargin)
1672 {
1673 val.hpos = bp.prevhpos - width + lmargin;
1674 pos--;
1675 }
1676
1677 bp.vpos = vpos;
1678
1679 /* Find first visible newline after which no more is changed. */
1680 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
1681 if (selective > 0)
1682 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
1683 tem = find_next_newline (tem, 1);
1684
1685 /* Compute the cursor position after that newline. */
1686 ep = *compute_motion (pos, vpos, val.hpos, tem,
1687 height, - (1 << (SHORTBITS - 1)),
1688 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
1689
1690 /* If changes reach past the text available on the frame,
1691 just display rest of frame. */
1692 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
1693 stop_vpos = height;
1694 else
1695 stop_vpos = ep.vpos;
1696
1697 /* If no newline before ep, the line ep is on includes some changes
1698 that must be displayed. Make sure we don't stop before it. */
1699 /* Also, if changes reach all the way until ep.bufpos,
1700 it is possible that something was deleted after the
1701 newline before it, so the following line must be redrawn. */
1702 if (stop_vpos == ep.vpos
1703 && (ep.bufpos == BEGV
1704 || FETCH_CHAR (ep.bufpos - 1) != '\n'
1705 || ep.bufpos == Z - end_unchanged))
1706 stop_vpos = ep.vpos + 1;
1707
1708 cursor_vpos = -1;
1709 overlay_arrow_seen = 0;
1710
1711 /* If changes do not reach to bottom of window,
1712 figure out how much to scroll the rest of the window */
1713 if (stop_vpos < height)
1714 {
1715 /* Now determine how far up or down the rest of the window has moved */
1716 epto = pos_tab_offset (w, ep.bufpos);
1717 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
1718 Z - XFASTINT (w->window_end_pos),
1719 10000, 0, width, hscroll, epto, w);
1720 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
1721
1722 /* Is everything on frame below the changes whitespace?
1723 If so, no scrolling is really necessary. */
1724 for (i = ep.bufpos; i < xp.bufpos; i++)
1725 {
1726 tem = FETCH_CHAR (i);
1727 if (tem != ' ' && tem != '\n' && tem != '\t')
1728 break;
1729 }
1730 if (i == xp.bufpos)
1731 return -2;
1732
1733 XSETFASTINT (w->window_end_vpos,
1734 XFASTINT (w->window_end_vpos) + scroll_amount);
1735
1736 /* Before doing any scrolling, verify that point will be on frame. */
1737 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
1738 {
1739 if (PT <= xp.bufpos)
1740 {
1741 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
1742 PT, height, - (1 << (SHORTBITS - 1)),
1743 width, hscroll, epto, w);
1744 }
1745 else
1746 {
1747 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
1748 PT, height, - (1 << (SHORTBITS - 1)),
1749 width, hscroll,
1750 pos_tab_offset (w, xp.bufpos), w);
1751 }
1752 if (pp.bufpos < PT || pp.vpos == height)
1753 return 0;
1754 cursor_vpos = pp.vpos + top;
1755 cursor_hpos = pp.hpos + XFASTINT (w->left);
1756 }
1757
1758 if (stop_vpos - scroll_amount >= height
1759 || ep.bufpos == xp.bufpos)
1760 {
1761 if (scroll_amount < 0)
1762 stop_vpos -= scroll_amount;
1763 scroll_amount = 0;
1764 /* In this path, we have altered window_end_vpos
1765 and not left it negative.
1766 We must make sure that, in case display is preempted
1767 before the frame changes to reflect what we do here,
1768 further updates will not come to try_window_id
1769 and assume the frame and window_end_vpos match. */
1770 blank_end_of_window = 1;
1771 }
1772 else if (!scroll_amount)
1773 {
1774 /* Even if we don't need to scroll, we must adjust the
1775 charstarts of subsequent lines (that we won't redisplay)
1776 according to the amount of text inserted or deleted. */
1777 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1778 int adjust = ep.bufpos - oldpos;
1779 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
1780 }
1781 else if (bp.bufpos == Z - end_unchanged)
1782 {
1783 /* If reprinting everything is nearly as fast as scrolling,
1784 don't bother scrolling. Can happen if lines are short. */
1785 if (scroll_cost (f, bp.vpos + top - scroll_amount,
1786 top + height - max (0, scroll_amount),
1787 scroll_amount)
1788 > xp.bufpos - bp.bufpos - 20)
1789 /* Return "try normal display with same window-start."
1790 Too bad we can't prevent further scroll-thinking. */
1791 return -2;
1792 /* If pure deletion, scroll up as many lines as possible.
1793 In common case of killing a line, this can save the
1794 following line from being overwritten by scrolling
1795 and therefore having to be redrawn. */
1796 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
1797 top + height - max (0, scroll_amount),
1798 scroll_amount, bp.bufpos);
1799 if (!tem)
1800 stop_vpos = height;
1801 else
1802 {
1803 /* scroll_frame_lines did not properly adjust subsequent
1804 lines' charstarts in the case where the text of the
1805 screen line at bp.vpos has changed.
1806 (This can happen in a deletion that ends in mid-line.)
1807 To adjust properly, we need to make things constent at
1808 the position ep.
1809 So do a second adjust to make that happen.
1810 Note that stop_vpos >= ep.vpos, so it is sufficient
1811 to update the charstarts for lines at ep.vpos and below. */
1812 int oldstart
1813 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1814 adjust_window_charstarts (w, ep.vpos + top - 1,
1815 ep.bufpos - oldstart);
1816 }
1817 }
1818 else if (scroll_amount)
1819 {
1820 /* If reprinting everything is nearly as fast as scrolling,
1821 don't bother scrolling. Can happen if lines are short. */
1822 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
1823 overestimate of cost of reprinting, since xp.bufpos
1824 would end up below the bottom of the window. */
1825 if (scroll_cost (f, ep.vpos + top - scroll_amount,
1826 top + height - max (0, scroll_amount),
1827 scroll_amount)
1828 > xp.bufpos - ep.bufpos - 20)
1829 /* Return "try normal display with same window-start."
1830 Too bad we can't prevent further scroll-thinking. */
1831 return -2;
1832 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
1833 top + height - max (0, scroll_amount),
1834 scroll_amount, ep.bufpos);
1835 if (!tem) stop_vpos = height;
1836 }
1837 }
1838
1839 /* In any case, do not display past bottom of window */
1840 if (stop_vpos >= height)
1841 {
1842 stop_vpos = height;
1843 scroll_amount = 0;
1844 }
1845
1846 /* Handle case where pos is before w->start --
1847 can happen if part of line had been clipped and is not clipped now */
1848 if (vpos == 0 && pos < marker_position (w->start))
1849 Fset_marker (w->start, make_number (pos), Qnil);
1850
1851 /* Redisplay the lines where the text was changed */
1852 last_text_vpos = vpos;
1853 tab_offset = pos_tab_offset (w, pos);
1854 /* If we are starting display in mid-character, correct tab_offset
1855 to account for passing the line that that character really starts in. */
1856 if (val.hpos < lmargin)
1857 tab_offset += width;
1858 while (vpos < stop_vpos)
1859 {
1860 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1861 tab_offset += width;
1862 if (val.vpos) tab_offset = 0;
1863 if (pos != val.bufpos)
1864 last_text_vpos
1865 /* Next line, unless prev line ended in end of buffer with no cr */
1866 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
1867 pos = val.bufpos;
1868 }
1869
1870 /* There are two cases:
1871 1) we have displayed down to the bottom of the window
1872 2) we have scrolled lines below stop_vpos by scroll_amount */
1873
1874 if (vpos == height)
1875 {
1876 /* If last line is continued in middle of character,
1877 include the split character in the text considered on the frame */
1878 if (val.hpos < lmargin)
1879 val.bufpos++;
1880 XSETFASTINT (w->window_end_vpos, last_text_vpos);
1881 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
1882 }
1883
1884 /* If scrolling made blank lines at window bottom,
1885 redisplay to fill those lines */
1886 if (scroll_amount < 0)
1887 {
1888 /* Don't consider these lines for general-purpose scrolling.
1889 That will save time in the scrolling computation. */
1890 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
1891 vpos = xp.vpos;
1892 pos = xp.bufpos;
1893 val.hpos = lmargin;
1894 if (pos == ZV)
1895 vpos = height + scroll_amount;
1896 else if (xp.contin && xp.hpos != lmargin)
1897 {
1898 val.hpos = xp.prevhpos - width + lmargin;
1899 pos--;
1900 }
1901
1902 blank_end_of_window = 1;
1903 tab_offset = pos_tab_offset (w, pos);
1904 /* If we are starting display in mid-character, correct tab_offset
1905 to account for passing the line that that character starts in. */
1906 if (val.hpos < lmargin)
1907 tab_offset += width;
1908
1909 while (vpos < height)
1910 {
1911 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1912 tab_offset += width;
1913 if (val.vpos) tab_offset = 0;
1914 pos = val.bufpos;
1915 }
1916
1917 /* Here is a case where display_text_line sets cursor_vpos wrong.
1918 Make it be fixed up, below. */
1919 if (xp.bufpos == ZV
1920 && xp.bufpos == PT)
1921 cursor_vpos = -1;
1922 }
1923
1924 /* If bottom just moved off end of frame, change mode line percentage. */
1925 if (XFASTINT (w->window_end_pos) == 0
1926 && Z != val.bufpos)
1927 w->update_mode_line = Qt;
1928
1929 /* Attempt to adjust end-of-text positions to new bottom line */
1930 if (scroll_amount)
1931 {
1932 delta = height - xp.vpos;
1933 if (delta < 0
1934 || (delta > 0 && xp.bufpos <= ZV)
1935 || (delta == 0 && xp.hpos))
1936 {
1937 val = *vmotion (Z - XFASTINT (w->window_end_pos),
1938 delta, width, hscroll, window);
1939 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
1940 XSETFASTINT (w->window_end_vpos,
1941 XFASTINT (w->window_end_vpos) + val.vpos);
1942 }
1943 }
1944
1945 w->window_end_valid = Qnil;
1946
1947 /* If point was not in a line that was displayed, find it */
1948 if (cursor_vpos < 0)
1949 {
1950 val = *compute_motion (start, 0, lmargin, PT, 10000, 10000,
1951 width, hscroll, pos_tab_offset (w, start), w);
1952 /* Admit failure if point is off frame now */
1953 if (val.vpos >= height)
1954 {
1955 for (vpos = 0; vpos < height; vpos++)
1956 cancel_line (vpos + top, f);
1957 return 0;
1958 }
1959 cursor_vpos = val.vpos + top;
1960 cursor_hpos = val.hpos + XFASTINT (w->left);
1961 }
1962
1963 FRAME_CURSOR_X (f) = max (0, cursor_hpos);
1964 FRAME_CURSOR_Y (f) = cursor_vpos;
1965
1966 if (debug_end_pos)
1967 {
1968 val = *compute_motion (start, 0, lmargin, ZV,
1969 height, - (1 << (SHORTBITS - 1)),
1970 width, hscroll, pos_tab_offset (w, start), w);
1971 if (val.vpos != XFASTINT (w->window_end_vpos))
1972 abort ();
1973 if (XFASTINT (w->window_end_pos)
1974 != Z - val.bufpos)
1975 abort ();
1976 }
1977
1978 return 1;
1979 }
1980 \f
1981 /* Mark a section of BUF as modified, but only for the sake of redisplay.
1982 This is useful for recording changes to overlays.
1983
1984 We increment the buffer's modification timestamp and set the
1985 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
1986 as if the region of text between START and END had been modified;
1987 the redisplay code will check this against the windows' timestamps,
1988 and redraw the appropriate area of the buffer.
1989
1990 However, if the buffer is unmodified, we bump the last-save
1991 timestamp as well, so that incrementing the timestamp doesn't fool
1992 Emacs into thinking that the buffer's text has been modified.
1993
1994 Tweaking the timestamps shouldn't hurt the first-modification
1995 timestamps recorded in the undo records; those values aren't
1996 written until just before a real text modification is made, so they
1997 will never catch the timestamp value just before this function gets
1998 called. */
1999
2000 void
2001 redisplay_region (buf, start, end)
2002 struct buffer *buf;
2003 int start, end;
2004 {
2005 if (start == end)
2006 return;
2007
2008 if (start > end)
2009 {
2010 int temp = start;
2011 start = end; end = temp;
2012 }
2013
2014 /* If this is a buffer not in the selected window,
2015 we must do other windows. */
2016 if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
2017 windows_or_buffers_changed = 1;
2018 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
2019 else if (buf != current_buffer)
2020 windows_or_buffers_changed = 1;
2021 /* If multiple windows show this buffer, we must do other windows. */
2022 else if (buffer_shared > 1)
2023 windows_or_buffers_changed = 1;
2024 else
2025 {
2026 if (unchanged_modified == MODIFF)
2027 {
2028 beg_unchanged = start - BEG;
2029 end_unchanged = Z - end;
2030 }
2031 else
2032 {
2033 if (Z - end < end_unchanged)
2034 end_unchanged = Z - end;
2035 if (start - BEG < beg_unchanged)
2036 beg_unchanged = start - BEG;
2037 }
2038 }
2039
2040 /* Increment the buffer's time stamp, but also increment the save
2041 and autosave timestamps, so as not to screw up that timekeeping. */
2042 if (BUF_MODIFF (buf) == BUF_SAVE_MODIFF (buf))
2043 BUF_SAVE_MODIFF (buf)++;
2044 if (BUF_MODIFF (buf) == buf->auto_save_modified)
2045 buf->auto_save_modified++;
2046
2047 BUF_MODIFF (buf) ++;
2048 }
2049
2050 \f
2051 /* Copy LEN glyphs starting address FROM to the rope TO.
2052 But don't actually copy the parts that would come in before S.
2053 Value is TO, advanced past the copied data.
2054 F is the frame we are displaying in. */
2055
2056 static GLYPH *
2057 copy_part_of_rope (f, to, s, from, len, face)
2058 FRAME_PTR f;
2059 register GLYPH *to; /* Copy to here. */
2060 register GLYPH *s; /* Starting point. */
2061 Lisp_Object *from; /* Data to copy. */
2062 int len;
2063 int face; /* Face to apply to glyphs which don't specify one. */
2064 {
2065 int n = len;
2066 register Lisp_Object *fp = from;
2067 /* These cache the results of the last call to compute_glyph_face. */
2068 int last_code = -1;
2069 int last_merged = 0;
2070
2071 #ifdef HAVE_FACES
2072 if (! FRAME_TERMCAP_P (f))
2073 while (n--)
2074 {
2075 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2076 int facecode;
2077
2078 if (FAST_GLYPH_FACE (glyph) == 0)
2079 /* If GLYPH has no face code, use FACE. */
2080 facecode = face;
2081 else if (FAST_GLYPH_FACE (glyph) == last_code)
2082 /* If it's same as previous glyph, use same result. */
2083 facecode = last_merged;
2084 else
2085 {
2086 /* Merge this glyph's face and remember the result. */
2087 last_code = FAST_GLYPH_FACE (glyph);
2088 last_merged = facecode = compute_glyph_face (f, last_code, face);
2089 }
2090
2091 if (to >= s)
2092 *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
2093 ++to;
2094 ++fp;
2095 }
2096 else
2097 #endif
2098 while (n--)
2099 {
2100 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
2101 ++to;
2102 ++fp;
2103 }
2104 return to;
2105 }
2106
2107 /* Correct a glyph by replacing its specified user-level face code
2108 with a displayable computed face code. */
2109
2110 static GLYPH
2111 fix_glyph (f, glyph, cface)
2112 FRAME_PTR f;
2113 GLYPH glyph;
2114 int cface;
2115 {
2116 #ifdef HAVE_FACES
2117 if (! FRAME_TERMCAP_P (f))
2118 {
2119 if (FAST_GLYPH_FACE (glyph) != 0)
2120 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
2121 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
2122 }
2123 #endif
2124 return glyph;
2125 }
2126 \f
2127 /* Display one line of window W, starting at position START in W's buffer.
2128
2129 Display starting at horizontal position HPOS, expressed relative to
2130 W's left edge. In situations where the text at START shouldn't
2131 start at the left margin (i.e. when the window is hscrolled, or
2132 we're continuing a line which left off in the midst of a
2133 multi-column character), HPOS should be negative; we throw away
2134 characters up 'til hpos = 0. So, HPOS must take hscrolling into
2135 account.
2136
2137 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2138
2139 Display on position VPOS on the frame. It is origin 0, relative to
2140 the top of the frame, not W.
2141
2142 Returns a STRUCT POSITION giving character to start next line with
2143 and where to display it, including a zero or negative hpos.
2144 The vpos field is not really a vpos; it is 1 unless the line is continued */
2145
2146 struct position val_display_text_line;
2147
2148 static struct position *
2149 display_text_line (w, start, vpos, hpos, taboffset)
2150 struct window *w;
2151 int start;
2152 int vpos;
2153 int hpos;
2154 int taboffset;
2155 {
2156 register int pos = start;
2157 register int c;
2158 register GLYPH *p1;
2159 int end;
2160 register int pause;
2161 register unsigned char *p;
2162 GLYPH *endp;
2163 register GLYPH *leftmargin;
2164 register GLYPH *p1prev = 0;
2165 register GLYPH *p1start;
2166 int *charstart;
2167 FRAME_PTR f = XFRAME (w->frame);
2168 int tab_width = XINT (current_buffer->tab_width);
2169 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
2170 int width = window_internal_width (w) - 1;
2171 struct position val;
2172 int lastpos;
2173 int invis;
2174 int hscroll = XINT (w->hscroll);
2175 int truncate = (hscroll
2176 || (truncate_partial_width_windows
2177 && XFASTINT (w->width) < FRAME_WIDTH (f))
2178 || !NILP (current_buffer->truncate_lines));
2179
2180 /* 1 if we should highlight the region. */
2181 int highlight_region
2182 = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
2183 int region_beg, region_end;
2184
2185 int selective = (INTEGERP (current_buffer->selective_display)
2186 ? XINT (current_buffer->selective_display)
2187 : !NILP (current_buffer->selective_display) ? -1 : 0);
2188 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
2189 register struct Lisp_Vector *dp = window_display_table (w);
2190
2191 Lisp_Object default_invis_vector[3];
2192 /* Nonzero means display something where there are invisible lines.
2193 The precise value is the number of glyphs to display. */
2194 int selective_rlen
2195 = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
2196 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
2197 : selective && !NILP (current_buffer->selective_display_ellipses)
2198 ? 3 : 0);
2199 /* This is the sequence of Lisp objects to display
2200 when there are invisible lines. */
2201 Lisp_Object *invis_vector_contents
2202 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
2203 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2204 : default_invis_vector);
2205
2206 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
2207 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
2208 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
2209 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
2210
2211 /* The next buffer location at which the face should change, due
2212 to overlays or text property changes. */
2213 int next_face_change;
2214
2215 #ifdef USE_TEXT_PROPERTIES
2216 /* The next location where the `invisible' property changes */
2217 int next_invisible;
2218 #endif
2219
2220 /* The face we're currently using. */
2221 int current_face = 0;
2222 int i;
2223
2224 XSETFASTINT (default_invis_vector[2], '.');
2225 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2226
2227 hpos += XFASTINT (w->left);
2228 get_display_line (f, vpos, XFASTINT (w->left));
2229 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
2230
2231 /* Show where to highlight the region. */
2232 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
2233 /* Maybe highlight only in selected window. */
2234 && (highlight_nonselected_windows
2235 || w == XWINDOW (selected_window)))
2236 {
2237 region_beg = marker_position (current_buffer->mark);
2238 if (PT < region_beg)
2239 {
2240 region_end = region_beg;
2241 region_beg = PT;
2242 }
2243 else
2244 region_end = PT;
2245 w->region_showing = Qt;
2246 }
2247 else
2248 region_beg = region_end = -1;
2249
2250 if (MINI_WINDOW_P (w)
2251 && start == 1
2252 && vpos == XFASTINT (w->top))
2253 {
2254 if (! NILP (minibuf_prompt))
2255 {
2256 minibuf_prompt_width
2257 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2258 XSTRING (minibuf_prompt)->size, hpos,
2259 /* Display a space if we truncate. */
2260 ' ',
2261 1, -1,
2262 /* Truncate the prompt a little before the
2263 margin, so user input can at least start
2264 on the first line. */
2265 w->width > 10 ? w->width - 4 : -1)
2266 - hpos);
2267 hpos += minibuf_prompt_width;
2268 taboffset -= minibuf_prompt_width;
2269 }
2270 else
2271 minibuf_prompt_width = 0;
2272 }
2273
2274 end = ZV;
2275
2276 /* If we're hscrolled at all, use compute_motion to skip over any
2277 text off the left edge of the window. compute_motion may know
2278 tricks to do this faster than we can. */
2279 if (hpos < 0)
2280 {
2281 struct position *left_edge
2282 = compute_motion (pos, vpos, hpos,
2283 end, vpos, 0,
2284 width, hscroll, taboffset, w);
2285
2286 /* Retrieve the buffer position and column provided by
2287 compute_motion. We can't assume that the column will be
2288 zero, because you may have multi-column characters crossing
2289 the left margin.
2290
2291 compute_motion may have moved us past the screen position we
2292 requested, if we hit a multi-column character, or the end of
2293 the line. If so, back up. */
2294 if (left_edge->vpos > vpos
2295 || left_edge->hpos > 0)
2296 {
2297 pos = left_edge->bufpos - 1;
2298 hpos = left_edge->prevhpos;
2299 }
2300 else
2301 {
2302 pos = left_edge->bufpos;
2303 hpos = left_edge->hpos;
2304 }
2305 }
2306
2307 desired_glyphs->bufp[vpos] = start;
2308 p1 = desired_glyphs->glyphs[vpos] + hpos;
2309 p1start = p1;
2310 charstart = desired_glyphs->charstarts[vpos] + hpos;
2311 /* In case we don't ever write anything into it... */
2312 desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
2313 leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
2314 endp = leftmargin + width;
2315
2316 /* Arrange the overlays nicely for our purposes. Usually, we call
2317 display_text_line on only one line at a time, in which case this
2318 can't really hurt too much, or we call it on lines which appear
2319 one after another in the buffer, in which case all calls to
2320 recenter_overlay_lists but the first will be pretty cheap. */
2321 recenter_overlay_lists (current_buffer, pos);
2322
2323 /* Loop generating characters.
2324 Stop at end of buffer, before newline,
2325 if reach or pass continuation column,
2326 or at face change. */
2327 pause = pos;
2328 next_face_change = pos;
2329 #ifdef USE_TEXT_PROPERTIES
2330 next_invisible = pos;
2331 #endif
2332 while (1)
2333 {
2334 /* Record which glyph starts a character,
2335 and the character position of that character. */
2336 if (p1 >= leftmargin)
2337 charstart[p1 - p1start] = pos;
2338
2339 if (p1 >= endp)
2340 break;
2341
2342 p1prev = p1;
2343 if (pos >= pause)
2344 {
2345 /* Did we hit the end of the visible region of the buffer?
2346 Stop here. */
2347 if (pos >= end)
2348 break;
2349
2350 /* Did we reach point? Record the cursor location. */
2351 if (pos == PT && cursor_vpos < 0)
2352 {
2353 cursor_vpos = vpos;
2354 cursor_hpos = p1 - leftmargin;
2355 }
2356
2357 #ifdef USE_TEXT_PROPERTIES
2358 /* if the `invisible' property is set to t, we can skip to
2359 the next property change */
2360 while (pos == next_invisible && pos < end)
2361 {
2362 Lisp_Object position, limit, endpos, prop, ww;
2363 XSETFASTINT (position, pos);
2364 XSETWINDOW (ww, w);
2365 prop = Fget_char_property (position, Qinvisible, ww);
2366 /* This is just an estimate to give reasonable
2367 performance; nothing should go wrong if it is too small. */
2368 limit = Fnext_overlay_change (position);
2369 if (XFASTINT (limit) > pos + 50)
2370 XSETFASTINT (limit, pos + 50);
2371 endpos = Fnext_single_property_change (position, Qinvisible,
2372 Fcurrent_buffer (), limit);
2373 if (INTEGERP (endpos))
2374 next_invisible = XINT (endpos);
2375 else
2376 next_invisible = end;
2377 if (! NILP (prop))
2378 {
2379 if (pos < PT && next_invisible >= PT)
2380 {
2381 cursor_vpos = vpos;
2382 cursor_hpos = p1 - leftmargin;
2383 }
2384 pos = next_invisible;
2385 }
2386 }
2387 if (pos >= end)
2388 break;
2389 #endif
2390
2391 #ifdef HAVE_FACES
2392 /* Did we hit a face change? Figure out what face we should
2393 use now. We also hit this the first time through the
2394 loop, to see what face we should start with. */
2395 if (pos >= next_face_change && FRAME_X_P (f))
2396 current_face = compute_char_face (f, w, pos,
2397 region_beg, region_end,
2398 &next_face_change, pos + 50, 0);
2399 #endif
2400
2401 pause = end;
2402
2403 #ifdef USE_TEXT_PROPERTIES
2404 if (pos < next_invisible && next_invisible < pause)
2405 pause = next_invisible;
2406 #endif
2407 if (pos < next_face_change && next_face_change < pause)
2408 pause = next_face_change;
2409
2410 /* Wouldn't you hate to read the next line to someone over
2411 the phone? */
2412 if (pos < PT && PT < pause)
2413 pause = PT;
2414 if (pos < GPT && GPT < pause)
2415 pause = GPT;
2416
2417 p = &FETCH_CHAR (pos);
2418 }
2419 c = *p++;
2420 if (c >= 040 && c < 0177
2421 && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
2422 {
2423 if (p1 >= leftmargin)
2424 *p1 = MAKE_GLYPH (f, c, current_face);
2425 p1++;
2426 }
2427 else if (c == '\n')
2428 {
2429 invis = 0;
2430 while (pos + 1 < end
2431 && selective > 0
2432 && indented_beyond_p (pos + 1, selective))
2433 {
2434 invis = 1;
2435 pos = find_next_newline (pos + 1, 1);
2436 if (FETCH_CHAR (pos - 1) == '\n')
2437 pos--;
2438 }
2439 if (invis && selective_rlen > 0 && p1 >= leftmargin)
2440 {
2441 p1 += selective_rlen;
2442 if (p1 - leftmargin > width)
2443 p1 = endp;
2444 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2445 (p1 - p1prev), current_face);
2446 }
2447 #ifdef HAVE_FACES
2448 /* Draw the face of the newline character as extending all the
2449 way to the end of the frame line. */
2450 if (current_face)
2451 {
2452 if (p1 < leftmargin)
2453 p1 = leftmargin;
2454 while (p1 < endp)
2455 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2456 }
2457 #endif
2458 break;
2459 }
2460 else if (c == '\t')
2461 {
2462 do
2463 {
2464 if (p1 >= leftmargin && p1 < endp)
2465 *p1 = MAKE_GLYPH (f, ' ', current_face);
2466 p1++;
2467 }
2468 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
2469 % tab_width);
2470 }
2471 else if (c == Ctl ('M') && selective == -1)
2472 {
2473 pos = find_next_newline (pos, 1);
2474 if (FETCH_CHAR (pos - 1) == '\n')
2475 pos--;
2476 if (selective_rlen > 0)
2477 {
2478 p1 += selective_rlen;
2479 if (p1 - leftmargin > width)
2480 p1 = endp;
2481 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2482 (p1 - p1prev), current_face);
2483 }
2484 #ifdef HAVE_FACES
2485 /* Draw the face of the newline character as extending all the
2486 way to the end of the frame line. */
2487 if (current_face)
2488 {
2489 if (p1 < leftmargin)
2490 p1 = leftmargin;
2491 while (p1 < endp)
2492 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2493 }
2494 #endif
2495 break;
2496 }
2497 else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
2498 {
2499 p1 = copy_part_of_rope (f, p1, leftmargin,
2500 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
2501 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
2502 current_face);
2503 }
2504 else if (c < 0200 && ctl_arrow)
2505 {
2506 if (p1 >= leftmargin)
2507 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
2508 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
2509 current_face);
2510 p1++;
2511 if (p1 >= leftmargin && p1 < endp)
2512 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
2513 p1++;
2514 }
2515 else
2516 {
2517 if (p1 >= leftmargin)
2518 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
2519 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
2520 current_face);
2521 p1++;
2522 if (p1 >= leftmargin && p1 < endp)
2523 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
2524 p1++;
2525 if (p1 >= leftmargin && p1 < endp)
2526 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
2527 p1++;
2528 if (p1 >= leftmargin && p1 < endp)
2529 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
2530 p1++;
2531 }
2532
2533 /* Do nothing here for a char that's entirely off the left edge. */
2534 if (p1 >= leftmargin)
2535 {
2536 /* For all the glyphs occupied by this character, except for the
2537 first, store -1 in charstarts. */
2538 if (p1 != p1prev)
2539 {
2540 int *p2x = &charstart[p1prev - p1start];
2541 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
2542
2543 /* The window's left column should always
2544 contain a character position.
2545 And don't clobber anything to the left of that. */
2546 if (p1prev < leftmargin)
2547 {
2548 p2x = charstart + (leftmargin - p1start);
2549 *p2x = pos;
2550 }
2551
2552 /* This loop skips over the char p2x initially points to. */
2553 while (++p2x < p2)
2554 *p2x = -1;
2555 }
2556 }
2557
2558 pos++;
2559 }
2560
2561 val.hpos = - XINT (w->hscroll);
2562 if (val.hpos)
2563 val.hpos++;
2564
2565 val.vpos = 1;
2566
2567 lastpos = pos;
2568
2569 /* Store 0 in this charstart line for the positions where
2570 there is no character. But do leave what was recorded
2571 for the character that ended the line. */
2572 /* Add 1 in the endtest to compensate for the fact that ENDP was
2573 made from WIDTH, which is 1 less than the window's actual
2574 internal width. */
2575 i = p1 - p1start + 1;
2576 if (p1 < leftmargin)
2577 i += leftmargin - p1;
2578 for (; i < endp - p1start + 1; i++)
2579 charstart[i] = 0;
2580
2581 /* Handle continuation in middle of a character */
2582 /* by backing up over it */
2583 if (p1 > endp)
2584 {
2585 /* Don't back up if we never actually displayed any text.
2586 This occurs when the minibuffer prompt takes up the whole line. */
2587 if (p1prev)
2588 {
2589 /* Start the next line with that same character */
2590 pos--;
2591 /* but at negative hpos, to skip the columns output on this line. */
2592 val.hpos += p1prev - endp;
2593 }
2594
2595 /* Keep in this line everything up to the continuation column. */
2596 p1 = endp;
2597 }
2598
2599 /* Finish deciding which character to start the next line on,
2600 and what hpos to start it at.
2601 Also set `lastpos' to the last position which counts as "on this line"
2602 for cursor-positioning. */
2603
2604 if (pos < ZV)
2605 {
2606 if (FETCH_CHAR (pos) == '\n')
2607 {
2608 /* If stopped due to a newline, start next line after it */
2609 pos++;
2610 /* Check again for hidden lines, in case the newline occurred exactly
2611 at the right margin. */
2612 while (pos < ZV && selective > 0
2613 && indented_beyond_p (pos, selective))
2614 pos = find_next_newline (pos, 1);
2615 }
2616 else
2617 /* Stopped due to right margin of window */
2618 {
2619 if (truncate)
2620 {
2621 *p1++ = fix_glyph (f, truncator, 0);
2622 /* Truncating => start next line after next newline,
2623 and point is on this line if it is before the newline,
2624 and skip none of first char of next line */
2625 do
2626 pos = find_next_newline (pos, 1);
2627 while (pos < ZV && selective > 0
2628 && indented_beyond_p (pos, selective));
2629 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
2630
2631 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
2632 }
2633 else
2634 {
2635 *p1++ = fix_glyph (f, continuer, 0);
2636 val.vpos = 0;
2637 lastpos--;
2638 }
2639 }
2640 }
2641
2642 /* If point is at eol or in invisible text at eol,
2643 record its frame location now. */
2644
2645 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
2646 {
2647 cursor_vpos = vpos;
2648 cursor_hpos = p1 - leftmargin;
2649 }
2650
2651 if (cursor_vpos == vpos)
2652 {
2653 if (cursor_hpos < 0) cursor_hpos = 0;
2654 if (cursor_hpos > width) cursor_hpos = width;
2655 cursor_hpos += XFASTINT (w->left);
2656 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
2657 {
2658 FRAME_CURSOR_Y (f) = cursor_vpos;
2659 FRAME_CURSOR_X (f) = cursor_hpos;
2660
2661 if (w == XWINDOW (selected_window))
2662 {
2663 /* Line is not continued and did not start
2664 in middle of character */
2665 if ((hpos - XFASTINT (w->left)
2666 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
2667 && val.vpos)
2668 {
2669 this_line_bufpos = start;
2670 this_line_buffer = current_buffer;
2671 this_line_vpos = cursor_vpos;
2672 this_line_start_hpos = hpos;
2673 this_line_endpos = Z - lastpos;
2674 }
2675 else
2676 this_line_bufpos = 0;
2677 }
2678 }
2679 }
2680
2681 /* If hscroll and line not empty, insert truncation-at-left marker */
2682 if (hscroll && lastpos != start)
2683 {
2684 *leftmargin = fix_glyph (f, truncator, 0);
2685 if (p1 <= leftmargin)
2686 p1 = leftmargin + 1;
2687 }
2688
2689 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f))
2690 {
2691 endp++;
2692 if (p1 < leftmargin) p1 = leftmargin;
2693 while (p1 < endp) *p1++ = SPACEGLYPH;
2694
2695 /* Don't draw vertical bars if we're using scroll bars. They're
2696 covered up by the scroll bars, and it's distracting to see
2697 them when the scroll bar windows are flickering around to be
2698 reconfigured. */
2699 *p1++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2700 ? ' '
2701 : (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
2702 ? DISP_BORDER_GLYPH (dp)
2703 : '|'));
2704 }
2705 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
2706 p1 - desired_glyphs->glyphs[vpos]);
2707 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
2708
2709 /* If the start of this line is the overlay arrow-position,
2710 then put the arrow string into the display-line. */
2711
2712 if (MARKERP (Voverlay_arrow_position)
2713 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
2714 && start == marker_position (Voverlay_arrow_position)
2715 && STRINGP (Voverlay_arrow_string)
2716 && ! overlay_arrow_seen)
2717 {
2718 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
2719 int i;
2720 int len = XSTRING (Voverlay_arrow_string)->size;
2721 int arrow_end;
2722
2723 if (len > width)
2724 len = width;
2725 #ifdef HAVE_FACES
2726 if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
2727 {
2728 /* If the arrow string has text props, obey them when displaying. */
2729 for (i = 0; i < len; i++)
2730 {
2731 int c = p[i];
2732 Lisp_Object face, ilisp;
2733 int newface;
2734
2735 XSETFASTINT (ilisp, i);
2736 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
2737 newface = compute_glyph_face_1 (f, face, 0);
2738 leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
2739 }
2740 }
2741 else
2742 #endif /* HAVE_FACES */
2743 {
2744 for (i = 0; i < len; i++)
2745 leftmargin[i] = p[i];
2746 }
2747
2748 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
2749 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
2750 if (desired_glyphs->used[vpos] < arrow_end)
2751 desired_glyphs->used[vpos] = arrow_end;
2752
2753 overlay_arrow_seen = 1;
2754 }
2755
2756 val.bufpos = pos;
2757 val_display_text_line = val;
2758 return &val_display_text_line;
2759 }
2760 \f
2761 /* Redisplay the menu bar in the frame for window W. */
2762
2763 static void
2764 display_menu_bar (w)
2765 struct window *w;
2766 {
2767 Lisp_Object items, tail;
2768 register int vpos = 0;
2769 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2770 int maxendcol = FRAME_WIDTH (f);
2771 int hpos = 0;
2772 int i;
2773
2774 #ifndef USE_X_TOOLKIT
2775 if (FRAME_MENU_BAR_LINES (f) <= 0)
2776 return;
2777
2778 get_display_line (f, vpos, 0);
2779
2780 items = FRAME_MENU_BAR_ITEMS (f);
2781 for (i = 0; i < XVECTOR (items)->size; i += 3)
2782 {
2783 Lisp_Object pos, string;
2784 string = XVECTOR (items)->contents[i + 1];
2785 if (NILP (string))
2786 break;
2787
2788 XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos);
2789
2790 if (hpos < maxendcol)
2791 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
2792 XSTRING (string)->data,
2793 XSTRING (string)->size,
2794 hpos, 0, 0, hpos, maxendcol);
2795 /* Put a gap of 3 spaces between items. */
2796 if (hpos < maxendcol)
2797 {
2798 int hpos1 = hpos + 3;
2799 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
2800 min (hpos1, maxendcol), maxendcol);
2801 }
2802 }
2803
2804 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
2805 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2806
2807 /* Fill out the line with spaces. */
2808 if (maxendcol > hpos)
2809 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
2810
2811 /* Clear the rest of the lines allocated to the menu bar. */
2812 vpos++;
2813 while (vpos < FRAME_MENU_BAR_LINES (f))
2814 get_display_line (f, vpos++, 0);
2815 #endif /* not USE_X_TOOLKIT */
2816 }
2817 \f
2818 /* Display the mode line for window w */
2819
2820 static void
2821 display_mode_line (w)
2822 struct window *w;
2823 {
2824 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
2825 register int left = XFASTINT (w->left);
2826 register int right = XFASTINT (w->width) + left;
2827 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2828
2829 line_number_displayed = 0;
2830 w->column_number_displayed = Qnil;
2831
2832 get_display_line (f, vpos, left);
2833 display_mode_element (w, vpos, left, 0, right, right,
2834 current_buffer->mode_line_format);
2835 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
2836
2837 /* Make the mode line inverse video if the entire line
2838 is made of mode lines.
2839 I.e. if this window is full width,
2840 or if it is the child of a full width window
2841 (which implies that that window is split side-by-side
2842 and the rest of this line is mode lines of the sibling windows). */
2843 if (XFASTINT (w->width) == FRAME_WIDTH (f)
2844 || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
2845 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2846 #ifdef HAVE_FACES
2847 else if (! FRAME_TERMCAP_P (f))
2848 {
2849 /* For a partial width window, explicitly set face of each glyph. */
2850 int i;
2851 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
2852 for (i = left; i < right; ++i)
2853 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
2854 }
2855 #endif
2856 }
2857
2858 /* Contribute ELT to the mode line for window W.
2859 How it translates into text depends on its data type.
2860
2861 VPOS is the position of the mode line being displayed.
2862
2863 HPOS is the position (absolute on frame) where this element's text
2864 should start. The output is truncated automatically at the right
2865 edge of window W.
2866
2867 DEPTH is the depth in recursion. It is used to prevent
2868 infinite recursion here.
2869
2870 MINENDCOL is the hpos before which the element may not end.
2871 The element is padded at the right with spaces if nec
2872 to reach this column.
2873
2874 MAXENDCOL is the hpos past which this element may not extend.
2875 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
2876 (This is necessary to make nested padding and truncation work.)
2877
2878 Returns the hpos of the end of the text generated by ELT.
2879 The next element will receive that value as its HPOS arg,
2880 so as to concatenate the elements. */
2881
2882 static int
2883 display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2884 struct window *w;
2885 register int vpos, hpos;
2886 int depth;
2887 int minendcol;
2888 register int maxendcol;
2889 register Lisp_Object elt;
2890 {
2891 tail_recurse:
2892 if (depth > 10)
2893 goto invalid;
2894
2895 depth++;
2896
2897 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
2898 {
2899 case Lisp_String:
2900 {
2901 /* A string: output it and check for %-constructs within it. */
2902 register unsigned char c;
2903 register unsigned char *this = XSTRING (elt)->data;
2904
2905 while (hpos < maxendcol && *this)
2906 {
2907 unsigned char *last = this;
2908 while ((c = *this++) != '\0' && c != '%')
2909 ;
2910 if (this - 1 != last)
2911 {
2912 register int lim = --this - last + hpos;
2913 if (frame_title_ptr)
2914 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
2915 else
2916 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
2917 hpos, min (lim, maxendcol));
2918 }
2919 else /* c == '%' */
2920 {
2921 register int spec_width = 0;
2922
2923 /* We can't allow -ve args due to the "%-" construct */
2924 /* Argument specifies minwidth but not maxwidth
2925 (maxwidth can be specified by
2926 (<negative-number> . <stuff>) mode-line elements) */
2927
2928 while ((c = *this++) >= '0' && c <= '9')
2929 {
2930 spec_width = spec_width * 10 + (c - '0');
2931 }
2932
2933 spec_width += hpos;
2934 if (spec_width > maxendcol)
2935 spec_width = maxendcol;
2936
2937 if (c == 'M')
2938 hpos = display_mode_element (w, vpos, hpos, depth,
2939 spec_width, maxendcol,
2940 Vglobal_mode_string);
2941 else if (c != 0)
2942 {
2943 char *spec = decode_mode_spec (w, c, maxendcol - hpos);
2944 if (frame_title_ptr)
2945 hpos = store_frame_title (spec, spec_width, maxendcol);
2946 else
2947 hpos = display_string (w, vpos, spec, -1,
2948 hpos, 0, 1,
2949 spec_width, maxendcol);
2950 }
2951 }
2952 }
2953 }
2954 break;
2955
2956 case Lisp_Symbol:
2957 /* A symbol: process the value of the symbol recursively
2958 as if it appeared here directly. Avoid error if symbol void.
2959 Special case: if value of symbol is a string, output the string
2960 literally. */
2961 {
2962 register Lisp_Object tem;
2963 tem = Fboundp (elt);
2964 if (!NILP (tem))
2965 {
2966 tem = Fsymbol_value (elt);
2967 /* If value is a string, output that string literally:
2968 don't check for % within it. */
2969 if (STRINGP (tem))
2970 {
2971 if (frame_title_ptr)
2972 hpos = store_frame_title (XSTRING (tem)->data,
2973 minendcol, maxendcol);
2974 else
2975 hpos = display_string (w, vpos, XSTRING (tem)->data,
2976 XSTRING (tem)->size,
2977 hpos, 0, 1, minendcol, maxendcol);
2978 }
2979 /* Give up right away for nil or t. */
2980 else if (!EQ (tem, elt))
2981 { elt = tem; goto tail_recurse; }
2982 }
2983 }
2984 break;
2985
2986 case Lisp_Cons:
2987 {
2988 register Lisp_Object car, tem;
2989
2990 /* A cons cell: three distinct cases.
2991 If first element is a string or a cons, process all the elements
2992 and effectively concatenate them.
2993 If first element is a negative number, truncate displaying cdr to
2994 at most that many characters. If positive, pad (with spaces)
2995 to at least that many characters.
2996 If first element is a symbol, process the cadr or caddr recursively
2997 according to whether the symbol's value is non-nil or nil. */
2998 car = XCONS (elt)->car;
2999 if (SYMBOLP (car))
3000 {
3001 tem = Fboundp (car);
3002 elt = XCONS (elt)->cdr;
3003 if (!CONSP (elt))
3004 goto invalid;
3005 /* elt is now the cdr, and we know it is a cons cell.
3006 Use its car if CAR has a non-nil value. */
3007 if (!NILP (tem))
3008 {
3009 tem = Fsymbol_value (car);
3010 if (!NILP (tem))
3011 { elt = XCONS (elt)->car; goto tail_recurse; }
3012 }
3013 /* Symbol's value is nil (or symbol is unbound)
3014 Get the cddr of the original list
3015 and if possible find the caddr and use that. */
3016 elt = XCONS (elt)->cdr;
3017 if (NILP (elt))
3018 break;
3019 else if (!CONSP (elt))
3020 goto invalid;
3021 elt = XCONS (elt)->car;
3022 goto tail_recurse;
3023 }
3024 else if (INTEGERP (car))
3025 {
3026 register int lim = XINT (car);
3027 elt = XCONS (elt)->cdr;
3028 if (lim < 0)
3029 /* Negative int means reduce maximum width.
3030 DO NOT change MINENDCOL here!
3031 (20 -10 . foo) should truncate foo to 10 col
3032 and then pad to 20. */
3033 maxendcol = min (maxendcol, hpos - lim);
3034 else if (lim > 0)
3035 {
3036 /* Padding specified. Don't let it be more than
3037 current maximum. */
3038 lim += hpos;
3039 if (lim > maxendcol)
3040 lim = maxendcol;
3041 /* If that's more padding than already wanted, queue it.
3042 But don't reduce padding already specified even if
3043 that is beyond the current truncation point. */
3044 if (lim > minendcol)
3045 minendcol = lim;
3046 }
3047 goto tail_recurse;
3048 }
3049 else if (STRINGP (car) || CONSP (car))
3050 {
3051 register int limit = 50;
3052 /* LIMIT is to protect against circular lists. */
3053 while (CONSP (elt) && --limit > 0
3054 && hpos < maxendcol)
3055 {
3056 hpos = display_mode_element (w, vpos, hpos, depth,
3057 hpos, maxendcol,
3058 XCONS (elt)->car);
3059 elt = XCONS (elt)->cdr;
3060 }
3061 }
3062 }
3063 break;
3064
3065 default:
3066 invalid:
3067 if (frame_title_ptr)
3068 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
3069 else
3070 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
3071 minendcol, maxendcol);
3072 return hpos;
3073 }
3074
3075 if (minendcol > hpos)
3076 if (frame_title_ptr)
3077 hpos = store_frame_title ("", minendcol, maxendcol);
3078 else
3079 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
3080 return hpos;
3081 }
3082 \f
3083 /* Return a string for the output of a mode line %-spec for window W,
3084 generated by character C and width MAXWIDTH. */
3085
3086 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3087
3088 static char *
3089 decode_mode_spec (w, c, maxwidth)
3090 struct window *w;
3091 register char c;
3092 register int maxwidth;
3093 {
3094 Lisp_Object obj;
3095 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3096 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
3097 struct buffer *b = XBUFFER (w->buffer);
3098
3099 obj = Qnil;
3100 if (maxwidth > FRAME_WIDTH (f))
3101 maxwidth = FRAME_WIDTH (f);
3102
3103 switch (c)
3104 {
3105 case 'b':
3106 obj = b->name;
3107 #if 0
3108 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
3109 {
3110 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
3111 decode_mode_spec_buf[maxwidth - 1] = '\\';
3112 decode_mode_spec_buf[maxwidth] = '\0';
3113 return decode_mode_spec_buf;
3114 }
3115 #endif
3116 break;
3117
3118 case 'f':
3119 obj = b->filename;
3120 #if 0
3121 if (NILP (obj))
3122 return "[none]";
3123 else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
3124 {
3125 bcopy ("...", decode_mode_spec_buf, 3);
3126 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
3127 decode_mode_spec_buf + 3, maxwidth - 3);
3128 return decode_mode_spec_buf;
3129 }
3130 #endif
3131 break;
3132
3133 case 'c':
3134 {
3135 int col = current_column ();
3136 XSETFASTINT (w->column_number_displayed, col);
3137 sprintf (decode_mode_spec_buf, "%d", col);
3138 return decode_mode_spec_buf;
3139 }
3140
3141 case 'l':
3142 {
3143 int startpos = marker_position (w->start);
3144 int line, linepos, topline;
3145 int nlines, junk;
3146 Lisp_Object tem;
3147 int height = XFASTINT (w->height);
3148
3149 /* If we decided that this buffer isn't suitable for line numbers,
3150 don't forget that too fast. */
3151 if (EQ (w->base_line_pos, w->buffer))
3152 return "??";
3153
3154 /* If the buffer is very big, don't waste time. */
3155 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
3156 {
3157 w->base_line_pos = Qnil;
3158 w->base_line_number = Qnil;
3159 return "??";
3160 }
3161
3162 if (!NILP (w->base_line_number)
3163 && !NILP (w->base_line_pos)
3164 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
3165 {
3166 line = XFASTINT (w->base_line_number);
3167 linepos = XFASTINT (w->base_line_pos);
3168 }
3169 else
3170 {
3171 line = 1;
3172 linepos = BUF_BEGV (b);
3173 }
3174
3175 /* Count lines from base line to window start position. */
3176 nlines = display_count_lines (linepos, startpos, startpos, &junk);
3177
3178 topline = nlines + line;
3179
3180 /* Determine a new base line, if the old one is too close
3181 or too far away, or if we did not have one.
3182 "Too close" means it's plausible a scroll-down would
3183 go back past it. */
3184 if (startpos == BUF_BEGV (b))
3185 {
3186 XSETFASTINT (w->base_line_number, topline);
3187 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
3188 }
3189 else if (nlines < height + 25 || nlines > height * 3 + 50
3190 || linepos == BUF_BEGV (b))
3191 {
3192 int limit = BUF_BEGV (b);
3193 int position;
3194 int distance = (height * 2 + 30) * 200;
3195
3196 if (startpos - distance > limit)
3197 limit = startpos - distance;
3198
3199 nlines = display_count_lines (startpos, limit,
3200 -(height * 2 + 30),
3201 &position);
3202 /* If we couldn't find the lines we wanted within
3203 200 chars per line,
3204 give up on line numbers for this window. */
3205 if (position == startpos - distance)
3206 {
3207 w->base_line_pos = w->buffer;
3208 w->base_line_number = Qnil;
3209 return "??";
3210 }
3211
3212 XSETFASTINT (w->base_line_number, topline - nlines);
3213 XSETFASTINT (w->base_line_pos, position);
3214 }
3215
3216 /* Now count lines from the start pos to point. */
3217 nlines = display_count_lines (startpos, PT, PT, &junk);
3218
3219 /* Record that we did display the line number. */
3220 line_number_displayed = 1;
3221
3222 /* Make the string to show. */
3223 sprintf (decode_mode_spec_buf, "%d", topline + nlines);
3224 return decode_mode_spec_buf;
3225 }
3226 break;
3227
3228 case 'm':
3229 obj = b->mode_name;
3230 break;
3231
3232 case 'n':
3233 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
3234 return " Narrow";
3235 break;
3236
3237 case '*':
3238 if (!NILP (b->read_only))
3239 return "%";
3240 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3241 return "*";
3242 return "-";
3243
3244 case '+':
3245 /* This differs from %* only for a modified read-only buffer. */
3246 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3247 return "*";
3248 if (!NILP (b->read_only))
3249 return "%";
3250 return "-";
3251
3252 case '&':
3253 /* This differs from %* in ignoring read-only-ness. */
3254 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
3255 return "*";
3256 return "-";
3257
3258 case 's':
3259 /* status of process */
3260 obj = Fget_buffer_process (w->buffer);
3261 if (NILP (obj))
3262 return "no process";
3263 #ifdef subprocesses
3264 obj = Fsymbol_name (Fprocess_status (obj));
3265 #endif
3266 break;
3267
3268 case 't': /* indicate TEXT or BINARY */
3269 #ifdef MODE_LINE_BINARY_TEXT
3270 return MODE_LINE_BINARY_TEXT (b);
3271 #else
3272 return "T";
3273 #endif
3274
3275 case 'p':
3276 {
3277 int pos = marker_position (w->start);
3278 int total = BUF_ZV (b) - BUF_BEGV (b);
3279
3280 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
3281 {
3282 if (pos <= BUF_BEGV (b))
3283 return "All";
3284 else
3285 return "Bottom";
3286 }
3287 else if (pos <= BUF_BEGV (b))
3288 return "Top";
3289 else
3290 {
3291 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
3292 /* We can't normally display a 3-digit number,
3293 so get us a 2-digit number that is close. */
3294 if (total == 100)
3295 total = 99;
3296 sprintf (decode_mode_spec_buf, "%2d%%", total);
3297 return decode_mode_spec_buf;
3298 }
3299 }
3300
3301 /* Display percentage of size above the bottom of the screen. */
3302 case 'P':
3303 {
3304 int toppos = marker_position (w->start);
3305 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
3306 int total = BUF_ZV (b) - BUF_BEGV (b);
3307
3308 if (botpos >= BUF_ZV (b))
3309 {
3310 if (toppos <= BUF_BEGV (b))
3311 return "All";
3312 else
3313 return "Bottom";
3314 }
3315 else
3316 {
3317 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
3318 /* We can't normally display a 3-digit number,
3319 so get us a 2-digit number that is close. */
3320 if (total == 100)
3321 total = 99;
3322 if (toppos <= BUF_BEGV (b))
3323 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
3324 else
3325 sprintf (decode_mode_spec_buf, "%2d%%", total);
3326 return decode_mode_spec_buf;
3327 }
3328 }
3329
3330 case '%':
3331 return "%";
3332
3333 case '[':
3334 {
3335 int i;
3336 char *p;
3337
3338 if (command_loop_level > 5)
3339 return "[[[... ";
3340 p = decode_mode_spec_buf;
3341 for (i = 0; i < command_loop_level; i++)
3342 *p++ = '[';
3343 *p = 0;
3344 return decode_mode_spec_buf;
3345 }
3346
3347 case ']':
3348 {
3349 int i;
3350 char *p;
3351
3352 if (command_loop_level > 5)
3353 return " ...]]]";
3354 p = decode_mode_spec_buf;
3355 for (i = 0; i < command_loop_level; i++)
3356 *p++ = ']';
3357 *p = 0;
3358 return decode_mode_spec_buf;
3359 }
3360
3361 case '-':
3362 {
3363 register char *p;
3364 register int i;
3365
3366 if (maxwidth < sizeof (lots_of_dashes))
3367 return lots_of_dashes;
3368 else
3369 {
3370 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
3371 *p++ = '-';
3372 *p = '\0';
3373 }
3374 return decode_mode_spec_buf;
3375 }
3376 }
3377
3378 if (STRINGP (obj))
3379 return (char *) XSTRING (obj)->data;
3380 else
3381 return "";
3382 }
3383 \f
3384 /* Search for COUNT instances of a line boundary, which means either a
3385 newline or (if selective display enabled) a carriage return.
3386 Start at START. If COUNT is negative, search backwards.
3387
3388 If we find COUNT instances, set *SHORTAGE to zero, and return the
3389 position after the COUNTth match. Note that for reverse motion
3390 this is not the same as the usual convention for Emacs motion commands.
3391
3392 If we don't find COUNT instances before reaching the end of the
3393 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3394 the number of line boundaries left unfound, and return the end of the
3395 buffer we bumped up against. */
3396
3397 static int
3398 display_scan_buffer (start, count, shortage)
3399 int *shortage, start;
3400 register int count;
3401 {
3402 int limit = ((count > 0) ? ZV - 1 : BEGV);
3403 int direction = ((count > 0) ? 1 : -1);
3404
3405 register unsigned char *cursor;
3406 unsigned char *base;
3407
3408 register int ceiling;
3409 register unsigned char *ceiling_addr;
3410
3411 /* If we are not in selective display mode,
3412 check only for newlines. */
3413 if (! (!NILP (current_buffer->selective_display)
3414 && !INTEGERP (current_buffer->selective_display)))
3415 return scan_buffer ('\n', start, 0, count, shortage, 0);
3416
3417 /* The code that follows is like scan_buffer
3418 but checks for either newline or carriage return. */
3419
3420 if (shortage != 0)
3421 *shortage = 0;
3422
3423 if (count > 0)
3424 while (start != limit + 1)
3425 {
3426 ceiling = BUFFER_CEILING_OF (start);
3427 ceiling = min (limit, ceiling);
3428 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
3429 base = (cursor = &FETCH_CHAR (start));
3430 while (1)
3431 {
3432 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
3433 ;
3434 if (cursor != ceiling_addr)
3435 {
3436 if (--count == 0)
3437 {
3438 immediate_quit = 0;
3439 return (start + cursor - base + 1);
3440 }
3441 else
3442 if (++cursor == ceiling_addr)
3443 break;
3444 }
3445 else
3446 break;
3447 }
3448 start += cursor - base;
3449 }
3450 else
3451 {
3452 start--; /* first character we scan */
3453 while (start > limit - 1)
3454 { /* we WILL scan under start */
3455 ceiling = BUFFER_FLOOR_OF (start);
3456 ceiling = max (limit, ceiling);
3457 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
3458 base = (cursor = &FETCH_CHAR (start));
3459 cursor++;
3460 while (1)
3461 {
3462 while (--cursor != ceiling_addr
3463 && *cursor != '\n' && *cursor != 015)
3464 ;
3465 if (cursor != ceiling_addr)
3466 {
3467 if (++count == 0)
3468 {
3469 immediate_quit = 0;
3470 return (start + cursor - base + 1);
3471 }
3472 }
3473 else
3474 break;
3475 }
3476 start += cursor - base;
3477 }
3478 }
3479
3480 if (shortage != 0)
3481 *shortage = count * direction;
3482 return (start + ((direction == 1 ? 0 : 1)));
3483 }
3484
3485 /* Count up to N lines starting from FROM.
3486 But don't go beyond LIMIT.
3487 Return the number of lines thus found (always positive).
3488 Store the position after what was found into *POS_PTR. */
3489
3490 static int
3491 display_count_lines (from, limit, n, pos_ptr)
3492 int from, limit, n;
3493 int *pos_ptr;
3494 {
3495 int oldbegv = BEGV;
3496 int oldzv = ZV;
3497 int shortage = 0;
3498
3499 if (limit < from)
3500 BEGV = limit;
3501 else
3502 ZV = limit;
3503
3504 *pos_ptr = display_scan_buffer (from, n, &shortage);
3505
3506 ZV = oldzv;
3507 BEGV = oldbegv;
3508
3509 if (n < 0)
3510 /* When scanning backwards, scan_buffer stops *after* the last newline
3511 it finds, but does count it. Compensate for that. */
3512 return - n - shortage - (*pos_ptr != limit);
3513 return n - shortage;
3514 }
3515 \f
3516 /* Display STRING on one line of window W, starting at HPOS.
3517 Display at position VPOS. Caller should have done get_display_line.
3518 If VPOS == -1, display it as the current frame's title.
3519 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3520
3521 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3522
3523 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3524 MAXCOL is the last column ok to end at. Truncate here.
3525 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3526 Both count from the left edge of the frame, as does HPOS.
3527 The right edge of W is an implicit maximum.
3528 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3529
3530 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3531 at the place where the current window ends in this line
3532 and not display anything beyond there. Otherwise, only MAXCOL
3533 controls where to stop output.
3534
3535 Returns ending hpos. */
3536
3537 static int
3538 display_string (w, vpos, string, length, hpos, truncate,
3539 obey_window_width, mincol, maxcol)
3540 struct window *w;
3541 unsigned char *string;
3542 int length;
3543 int vpos, hpos;
3544 GLYPH truncate;
3545 int obey_window_width;
3546 int mincol, maxcol;
3547 {
3548 register int c;
3549 register GLYPH *p1;
3550 int hscroll = XINT (w->hscroll);
3551 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
3552 register GLYPH *start;
3553 register GLYPH *end;
3554 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3555 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
3556 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
3557 int window_width = XFASTINT (w->width);
3558
3559 /* Use the standard display table, not the window's display table.
3560 We don't want the mode line in rot13. */
3561 register struct Lisp_Vector *dp = 0;
3562 int i;
3563
3564 if (VECTORP (Vstandard_display_table)
3565 && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
3566 dp = XVECTOR (Vstandard_display_table);
3567
3568 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
3569
3570 p1 = p1start;
3571 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
3572
3573 if (obey_window_width)
3574 {
3575 end = start + window_width - (truncate != 0);
3576
3577 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f))
3578 {
3579 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3580 {
3581 int i;
3582
3583 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
3584 *end-- = ' ';
3585 }
3586 else
3587 *end-- = '|';
3588 }
3589 }
3590
3591 if (! obey_window_width
3592 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
3593 end = desired_glyphs->glyphs[vpos] + maxcol;
3594
3595 /* Store 0 in charstart for these columns. */
3596 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
3597 desired_glyphs->charstarts[vpos][i] = 0;
3598
3599 if (maxcol >= 0 && mincol > maxcol)
3600 mincol = maxcol;
3601
3602 while (p1 < end)
3603 {
3604 if (length == 0)
3605 break;
3606 c = *string++;
3607 /* Specified length. */
3608 if (length >= 0)
3609 length--;
3610 /* Unspecified length (null-terminated string). */
3611 else if (c == 0)
3612 break;
3613
3614 if (c >= 040 && c < 0177
3615 && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
3616 {
3617 if (p1 >= start)
3618 *p1 = c;
3619 p1++;
3620 }
3621 else if (c == '\t')
3622 {
3623 do
3624 {
3625 if (p1 >= start && p1 < end)
3626 *p1 = SPACEGLYPH;
3627 p1++;
3628 }
3629 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
3630 }
3631 else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
3632 {
3633 p1 = copy_part_of_rope (f, p1, start,
3634 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
3635 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
3636 0);
3637 }
3638 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
3639 {
3640 if (p1 >= start)
3641 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
3642 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
3643 0);
3644 p1++;
3645 if (p1 >= start && p1 < end)
3646 *p1 = c ^ 0100;
3647 p1++;
3648 }
3649 else
3650 {
3651 if (p1 >= start)
3652 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
3653 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
3654 0);
3655 p1++;
3656 if (p1 >= start && p1 < end)
3657 *p1 = (c >> 6) + '0';
3658 p1++;
3659 if (p1 >= start && p1 < end)
3660 *p1 = (7 & (c >> 3)) + '0';
3661 p1++;
3662 if (p1 >= start && p1 < end)
3663 *p1 = (7 & c) + '0';
3664 p1++;
3665 }
3666 }
3667
3668 if (c && length > 0)
3669 {
3670 p1 = end;
3671 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
3672 }
3673 else if (mincol >= 0)
3674 {
3675 end = desired_glyphs->glyphs[vpos] + mincol;
3676 while (p1 < end)
3677 *p1++ = SPACEGLYPH;
3678 }
3679
3680 {
3681 register int len = p1 - desired_glyphs->glyphs[vpos];
3682
3683 if (len > desired_glyphs->used[vpos])
3684 desired_glyphs->used[vpos] = len;
3685 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3686
3687 return len;
3688 }
3689 }
3690 \f
3691 void
3692 syms_of_xdisp ()
3693 {
3694 staticpro (&Qmenu_bar_update_hook);
3695 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
3696
3697 staticpro (&last_arrow_position);
3698 staticpro (&last_arrow_string);
3699 last_arrow_position = Qnil;
3700 last_arrow_string = Qnil;
3701
3702 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
3703 "String (or mode line construct) included (normally) in `mode-line-format'.");
3704 Vglobal_mode_string = Qnil;
3705
3706 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
3707 "Marker for where to display an arrow on top of the buffer text.\n\
3708 This must be the beginning of a line in order to work.\n\
3709 See also `overlay-arrow-string'.");
3710 Voverlay_arrow_position = Qnil;
3711
3712 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
3713 "String to display as an arrow. See also `overlay-arrow-position'.");
3714 Voverlay_arrow_string = Qnil;
3715
3716 DEFVAR_INT ("scroll-step", &scroll_step,
3717 "*The number of lines to try scrolling a window by when point moves out.\n\
3718 If that fails to bring point back on frame, point is centered instead.\n\
3719 If this is zero, point is always centered after it moves off frame.");
3720
3721 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
3722
3723 DEFVAR_BOOL ("truncate-partial-width-windows",
3724 &truncate_partial_width_windows,
3725 "*Non-nil means truncate lines in all windows less than full frame wide.");
3726 truncate_partial_width_windows = 1;
3727
3728 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
3729 "*Non-nil means use inverse video for the mode line.");
3730 mode_line_inverse_video = 1;
3731
3732 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
3733 "*Maximum buffer size for which line number should be displayed.");
3734 line_number_display_limit = 1000000;
3735
3736 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
3737 "*Non-nil means highlight region even in nonselected windows.");
3738 highlight_nonselected_windows = 1;
3739
3740 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3741 "Non-nil means more than one frame is in use, not counting minibuffer frames.\n\
3742 Not guaranteed to be accurate except while parsing frame-title-format.");
3743
3744 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
3745 "Template for displaying the titlebar of visible frames.\n\
3746 \(Assuming the window manager supports this feature.)\n\
3747 This variable has the same structure as `mode-line-format' (which see),\n\
3748 and is used only on frames for which no explicit name has been set\n\
3749 \(see `modify-frame-parameters').");
3750 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
3751 "Template for displaying the titlebar of an iconified frame.\n\
3752 \(Assuming the window manager supports this feature.)\n\
3753 This variable has the same structure as `mode-line-format' (which see),\n\
3754 and is used only on frames for which no explicit name has been set\n\
3755 \(see `modify-frame-parameters').");
3756 Vicon_title_format
3757 = Vframe_title_format
3758 = Fcons (intern ("multiple-frames"),
3759 Fcons (build_string ("%b"),
3760 Fcons (Fcons (build_string (""),
3761 Fcons (intern ("invocation-name"),
3762 Fcons (build_string ("@"),
3763 Fcons (intern ("system-name"),
3764 Qnil)))),
3765 Qnil)));
3766
3767 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
3768 "Maximum number of lines to keep in the message log buffer.\n\
3769 If nil, disable message logging. If t, log messages but don't truncate\n\
3770 the buffer when it becomes large.");
3771 XSETFASTINT (Vmessage_log_max, 50);
3772 }
3773
3774 /* initialize the window system */
3775 init_xdisp ()
3776 {
3777 Lisp_Object root_window;
3778 #ifndef COMPILER_REGISTER_BUG
3779 register
3780 #endif /* COMPILER_REGISTER_BUG */
3781 struct window *mini_w;
3782
3783 this_line_bufpos = 0;
3784
3785 mini_w = XWINDOW (minibuf_window);
3786 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
3787
3788 echo_area_glyphs = 0;
3789 previous_echo_glyphs = 0;
3790
3791 if (!noninteractive)
3792 {
3793 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
3794 XSETFASTINT (XWINDOW (root_window)->top, 0);
3795 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
3796 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
3797 set_window_height (minibuf_window, 1, 0);
3798
3799 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
3800 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
3801 }
3802 }