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