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