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