(edmacro-original-buffer, edmacro-finish-hook)
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
5992c4f7 2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
a2889657
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
b1d1124b 8the Free Software Foundation; either version 2, or (at your option)
a2889657
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
a2889657
JB
20
21
18160b98 22#include <config.h>
a2889657
JB
23#include <stdio.h>
24/*#include <ctype.h>*/
25#undef NULL
26#include "lisp.h"
44fa5b1e 27#include "frame.h"
a2889657
JB
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"
30c566e4 36#include "termhooks.h"
b0a0fbda 37#include "intervals.h"
fe8b0cf8 38#include "keyboard.h"
a2889657 39
8f3343d0 40#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
76412d64
RS
41extern void set_frame_menubar ();
42#endif
43
a2889657
JB
44extern int interrupt_input;
45extern int command_loop_level;
46
c4628384
RS
47extern Lisp_Object Qface;
48
399164b4
KH
49extern Lisp_Object Voverriding_local_map;
50extern Lisp_Object Voverriding_local_map_menu_flag;
51
d46fb96a 52Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 53Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 54Lisp_Object Qredisplay_end_trigger_functions;
399164b4 55
f88eb0b6 56/* Nonzero means print newline to stdout before next minibuffer message. */
a2889657
JB
57
58int noninteractive_need_newline;
59
f88eb0b6
KH
60/* Nonzero means print newline to message log before next message. */
61
3c6595e0 62static int message_log_need_newline;
f88eb0b6 63
a2889657
JB
64#define min(a, b) ((a) < (b) ? (a) : (b))
65#define max(a, b) ((a) > (b) ? (a) : (b))
210e752f
KH
66#define minmax(floor, val, ceil) \
67 ((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
a2889657
JB
68
69/* The buffer position of the first character appearing
44fa5b1e
JB
70 entirely or partially on the current frame line.
71 Or zero, which disables the optimization for the current frame line. */
a2889657
JB
72static int this_line_bufpos;
73
74/* Number of characters past the end of this line,
75 including the terminating newline */
76static int this_line_endpos;
77
44fa5b1e 78/* The vertical position of this frame line. */
a2889657
JB
79static int this_line_vpos;
80
44fa5b1e 81/* Hpos value for start of display on this frame line.
a2889657
JB
82 Usually zero, but negative if first character really began
83 on previous line */
84static int this_line_start_hpos;
85
86/* Buffer that this_line variables are describing. */
87static struct buffer *this_line_buffer;
88
a2889657 89/* Value of echo_area_glyphs when it was last acted on.
44fa5b1e 90 If this is nonzero, there is a message on the frame
a2889657
JB
91 in the minibuffer and it should be erased as soon
92 as it is no longer requested to appear. */
93char *previous_echo_glyphs;
94
44fa5b1e 95/* Nonzero means truncate lines in all windows less wide than the frame */
a2889657
JB
96int truncate_partial_width_windows;
97
d39b6696
KH
98/* Nonzero means we have more than one non-minibuffer-only frame.
99 Not guaranteed to be accurate except while parsing frame-title-format. */
100int multiple_frames;
101
a2889657
JB
102Lisp_Object Vglobal_mode_string;
103
104/* Marker for where to display an arrow on top of the buffer text. */
105Lisp_Object Voverlay_arrow_position;
106
107/* String to display for the arrow. */
108Lisp_Object Voverlay_arrow_string;
109
d39b6696
KH
110/* Like mode-line-format, but for the titlebar on a visible frame. */
111Lisp_Object Vframe_title_format;
112
113/* Like mode-line-format, but for the titlebar on an iconified frame. */
114Lisp_Object Vicon_title_format;
115
08b610e4
RS
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. */
119static Lisp_Object Vwindow_size_change_functions;
120
a2889657 121/* Values of those variables at last redisplay. */
ded34426 122static Lisp_Object last_arrow_position, last_arrow_string;
a2889657 123
cf074754
RS
124Lisp_Object Qmenu_bar_update_hook;
125
a2889657
JB
126/* Nonzero if overlay arrow has been displayed once in this window. */
127static int overlay_arrow_seen;
128
ca26e1c8
KH
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.) */
132static int zv_strings_seen;
133
fba9ce76
RS
134/* Nonzero means highlight the region even in nonselected windows. */
135static int highlight_nonselected_windows;
136
44fa5b1e 137/* If cursor motion alone moves point off frame,
a2889657 138 Try scrolling this many lines up or down if that will bring it back. */
14510fee 139static int scroll_step;
a2889657
JB
140
141/* Nonzero if try_window_id has made blank lines at window bottom
142 since the last redisplay that paused */
143static int blank_end_of_window;
144
42640f83
RS
145/* Number of windows showing the buffer of the selected window
146 (or another buffer with the same base buffer).
a2889657
JB
147 keyboard.c refers to this. */
148int buffer_shared;
149
44fa5b1e 150/* display_text_line sets these to the frame position (origin 0) of point,
a2889657
JB
151 whether the window is selected or not.
152 Set one to -1 first to determine whether point was found afterwards. */
153
154static int cursor_vpos;
155static int cursor_hpos;
156
14510fee 157static int debug_end_pos;
a2889657
JB
158
159/* Nonzero means display mode line highlighted */
160int mode_line_inverse_video;
161
ff6c30e5 162static int message_log_check_duplicate ();
a2889657
JB
163static void echo_area_display ();
164void mark_window_display_accurate ();
165static void redisplay_windows ();
166static void redisplay_window ();
90adcf20 167static void update_menu_bar ();
a2889657
JB
168static void try_window ();
169static int try_window_id ();
170static struct position *display_text_line ();
171static void display_mode_line ();
172static int display_mode_element ();
a2889657
JB
173static char *decode_mode_spec ();
174static int display_string ();
7ce2c095 175static void display_menu_bar ();
aa6d10fa 176static int display_count_lines ();
a2889657
JB
177
178/* Prompt to display in front of the minibuffer contents */
8c5b6a0a 179Lisp_Object minibuf_prompt;
a2889657
JB
180
181/* Width in columns of current minibuffer prompt. */
182int 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. */
188char *echo_area_glyphs;
189
90adcf20
RS
190/* This is the length of the message in echo_area_glyphs. */
191int echo_area_glyphs_length;
192
73af359d
RS
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. */
196Lisp_Object echo_area_window;
197
a2889657
JB
198/* true iff we should redraw the mode lines on the next redisplay */
199int 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. */
204int 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. */
209int 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 */
214int unchanged_modified;
215
a2889657
JB
216/* Nonzero if window sizes or contents have changed
217 since last redisplay that finished */
218int windows_or_buffers_changed;
219
aa6d10fa
RS
220/* Nonzero after display_mode_line if %l was used
221 and it displayed a line number. */
222int line_number_displayed;
223
224/* Maximum buffer size for which to display line numbers. */
14510fee 225static int line_number_display_limit;
5992c4f7
KH
226
227/* Number of lines to keep in the message log buffer.
228 t means infinite. nil means don't log at all. */
229Lisp_Object Vmessage_log_max;
a2889657 230\f
3c6595e0
KH
231void
232message_log_maybe_newline ()
233{
234 if (message_log_need_newline)
235 message_dolog ("", 0, 1);
236}
237
238
d917be71
KH
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. */
90adcf20
RS
242
243void
f88eb0b6 244message_dolog (m, len, nlflag)
90adcf20 245 char *m;
f88eb0b6 246 int len, nlflag;
5992c4f7 247{
f88eb0b6 248 if (!NILP (Vmessage_log_max))
5992c4f7
KH
249 {
250 struct buffer *oldbuf;
251 int oldpoint, oldbegv, oldzv;
69f033ab 252 int old_windows_or_buffers_changed = windows_or_buffers_changed;
5992c4f7
KH
253
254 oldbuf = current_buffer;
3c6595e0 255 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
16c300fb 256 current_buffer->undo_list = Qt;
5992c4f7
KH
257 oldpoint = PT;
258 oldbegv = BEGV;
259 oldzv = ZV;
d917be71
KH
260 BEGV = BEG;
261 ZV = Z;
5992c4f7 262 if (oldpoint == Z)
f88eb0b6 263 oldpoint += len + nlflag;
5992c4f7 264 if (oldzv == Z)
f88eb0b6 265 oldzv += len + nlflag;
5992c4f7 266 TEMP_SET_PT (Z);
f88eb0b6
KH
267 if (len)
268 insert_1 (m, len, 1, 0);
269 if (nlflag)
5992c4f7 270 {
ff6c30e5
KH
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 }
5992c4f7
KH
316 }
317 BEGV = oldbegv;
318 ZV = oldzv;
319 TEMP_SET_PT (oldpoint);
320 set_buffer_internal (oldbuf);
69f033ab 321 windows_or_buffers_changed = old_windows_or_buffers_changed;
3c6595e0 322 message_log_need_newline = !nlflag;
5992c4f7 323 }
f88eb0b6
KH
324}
325
326
ff6c30e5
KH
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]". */
f82aff7c 332
ff6c30e5
KH
333static int
334message_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;
f82aff7c
RS
340 unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
341 unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
ff6c30e5
KH
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
f88eb0b6
KH
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
370void
371message2 (m, len)
372 char *m;
373 int len;
374{
375 /* First flush out any partial line written with print. */
3c6595e0 376 message_log_maybe_newline ();
f88eb0b6
KH
377 if (m)
378 message_dolog (m, len, 1);
5992c4f7
KH
379 message2_nolog (m, len);
380}
381
382
383/* The non-logging part of that function. */
384
385void
386message2_nolog (m, len)
387 char *m;
388 int len;
90adcf20
RS
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 {
73af359d
RS
405 Lisp_Object mini_window;
406 FRAME_PTR f;
90adcf20 407
73af359d
RS
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);
90adcf20 415 if (FRAME_VISIBLE_P (selected_frame)
73af359d
RS
416 && ! FRAME_VISIBLE_P (f))
417 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
90adcf20
RS
418#endif
419
420 if (m)
421 {
422 echo_area_glyphs = m;
423 echo_area_glyphs_length = len;
424 }
ded34426
JB
425 else
426 echo_area_glyphs = previous_echo_glyphs = 0;
427
428 do_pending_window_change ();
429 echo_area_display ();
73af359d 430 update_frame (f, 1, 1);
ded34426 431 do_pending_window_change ();
853cf346 432 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
73af359d 433 (*frame_up_to_date_hook) (f);
ded34426
JB
434 }
435}
436
48ae5f0a
KH
437void
438message1 (m)
439 char *m;
440{
441 message2 (m, (m ? strlen (m) : 0));
442}
443
0b1005ef
KH
444void
445message1_nolog (m)
446 char *m;
447{
448 message2_nolog (m, (m ? strlen (m) : 0));
449}
450
76412d64
RS
451/* Truncate what will be displayed in the echo area
452 the next time we display it--but don't redisplay it now. */
453
454void
455truncate_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
44fa5b1e 465/* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
9c74a0dd
JB
466 zero if being used by message. */
467int message_buf_print;
468
81d478f3
JB
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. */
a2889657 471/* VARARGS 1 */
a2889657
JB
472void
473message (m, a1, a2, a3)
474 char *m;
5d5ed907 475 EMACS_INT a1, a2, a3;
a2889657
JB
476{
477 if (noninteractive)
478 {
81d478f3
JB
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);
c4f14ccb
RS
485 if (cursor_in_echo_area == 0)
486 fprintf (stderr, "\n");
81d478f3
JB
487 fflush (stderr);
488 }
a2889657 489 }
1f40cad2 490 else if (INTERACTIVE)
a2889657 491 {
1f40cad2
JB
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. */
73af359d
RS
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)));
1f40cad2
JB
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. */
73af359d 506 if (FRAME_MESSAGE_BUF (f))
81d478f3 507 {
1f40cad2
JB
508 if (m)
509 {
90adcf20 510 int len;
a2889657 511#ifdef NO_ARG_ARRAY
5d5ed907 512 EMACS_INT a[3];
90adcf20
RS
513 a[0] = a1;
514 a[1] = a2;
515 a[2] = a3;
a2889657 516
73af359d
RS
517 len = doprnt (FRAME_MESSAGE_BUF (f),
518 FRAME_WIDTH (f), m, (char *)0, 3, a);
a2889657 519#else
73af359d
RS
520 len = doprnt (FRAME_MESSAGE_BUF (f),
521 FRAME_WIDTH (f), m, (char *)0, 3, &a1);
1f40cad2 522#endif /* NO_ARG_ARRAY */
1f40cad2 523
73af359d 524 message2 (FRAME_MESSAGE_BUF (f), len);
1f40cad2
JB
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;
81d478f3 532 }
a2889657
JB
533 }
534}
535
6c4429a5
KH
536/* The non-logging version of that function. */
537void
538message_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
131f2133
RS
549void
550update_echo_area ()
551{
552 message2 (echo_area_glyphs, echo_area_glyphs_length);
553}
554
a2889657
JB
555static void
556echo_area_display ()
557{
558 register int vpos;
44fa5b1e 559 FRAME_PTR f;
73af359d 560 Lisp_Object mini_window;
a2889657 561
73af359d
RS
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)));
a2889657 567
44fa5b1e 568 if (! FRAME_VISIBLE_P (f))
a2889657 569 return;
a2889657 570
44fa5b1e 571 if (frame_garbaged)
a2889657 572 {
02a9b6e4 573 redraw_garbaged_frames ();
44fa5b1e 574 frame_garbaged = 0;
a2889657
JB
575 }
576
577 if (echo_area_glyphs || minibuf_level == 0)
578 {
73af359d
RS
579 echo_area_window = mini_window;
580
581 vpos = XFASTINT (XWINDOW (mini_window)->top);
44fa5b1e 582 get_display_line (f, vpos, 0);
73af359d 583 display_string (XWINDOW (mini_window), vpos,
a2889657 584 echo_area_glyphs ? echo_area_glyphs : "",
90adcf20 585 echo_area_glyphs ? echo_area_glyphs_length : -1,
278feba9 586 0, 0, 0, 0, FRAME_WIDTH (f));
a2889657 587
b6f0fe04 588#if 0 /* This just gets in the way. update_frame does the job. */
a2889657 589 /* If desired cursor location is on this line, put it at end of text */
b5bbc9a5
KH
590 if (cursor_in_echo_area)
591 FRAME_CURSOR_Y (f) = vpos;
44fa5b1e
JB
592 if (FRAME_CURSOR_Y (f) == vpos)
593 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
b6f0fe04 594#endif
daa37602
JB
595
596 /* Fill the rest of the minibuffer window with blank lines. */
597 {
598 int i;
599
b2a76982 600 for (i = vpos + 1;
73af359d 601 i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
daa37602 602 {
44fa5b1e 603 get_display_line (f, i, 0);
73af359d 604 display_string (XWINDOW (mini_window), vpos,
278feba9 605 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f));
daa37602
JB
606 }
607 }
a2889657 608 }
73af359d 609 else if (!EQ (mini_window, selected_window))
a2889657
JB
610 windows_or_buffers_changed++;
611
73af359d 612 if (EQ (mini_window, selected_window))
a2889657
JB
613 this_line_bufpos = 0;
614
615 previous_echo_glyphs = echo_area_glyphs;
616}
96a410bc 617
8f3343d0 618#ifdef HAVE_WINDOW_SYSTEM
d39b6696
KH
619static char frame_title_buf[512];
620static char *frame_title_ptr;
96a410bc 621
d39b6696
KH
622static int
623store_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}
96a410bc 637
96a410bc
KH
638static void
639x_consider_frame_title (frame)
640 Lisp_Object frame;
641{
d39b6696
KH
642 Lisp_Object fmt;
643 struct buffer *obuf;
644 int len;
96a410bc
KH
645 FRAME_PTR f = XFRAME (frame);
646
8f3343d0 647 if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
d39b6696 648 return;
3450d04c
KH
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
c9492f08
KH
658 if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
659 && !FRAME_MINIBUF_ONLY_P (tf)
3450d04c
KH
660 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
661 break;
662 }
663
664 multiple_frames = CONSP (tail);
665 }
666
d39b6696
KH
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);
96a410bc 683}
c7c9ca97
KH
684#else
685#define frame_title_ptr ((char *)0)
e39322d9 686#define store_frame_title(str, mincol, maxcol) 0
96a410bc 687#endif
a2889657 688\f
90adcf20 689/* Prepare for redisplay by updating menu-bar item lists when appropriate.
87382820 690 This can call eval. */
90adcf20
RS
691
692void
693prepare_menu_bars ()
694{
695 register struct window *w = XWINDOW (selected_window);
696 int all_windows;
08b610e4 697 struct gcpro gcpro1, gcpro2;
90adcf20 698
ecf7de9b 699 all_windows = (update_mode_lines || buffer_shared > 1
28995e67 700 || windows_or_buffers_changed);
90adcf20 701
feb0c42f
KH
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. */
8f3343d0 712#ifdef HAVE_WINDOW_SYSTEM
d3f46cff 713 if (windows_or_buffers_changed || update_mode_lines)
feb0c42f
KH
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
90adcf20
RS
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;
a2725ab2
RS
730 int count = specpdl_ptr - specpdl;
731
732 record_unwind_protect (Fstore_match_data, Fmatch_data ());
90adcf20
RS
733
734 FOR_EACH_FRAME (tail, frame)
08b610e4
RS
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;
14510fee
RS
741 /* Clear flag first in case we get error below. */
742 FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
08b610e4
RS
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;
08b610e4
RS
751 }
752 GCPRO1 (tail);
a2725ab2 753 update_menu_bar (XFRAME (frame), 0);
08b610e4
RS
754 UNGCPRO;
755 }
a2725ab2
RS
756
757 unbind_to (count, Qnil);
90adcf20 758 }
ecf7de9b 759 else
a2725ab2 760 update_menu_bar (selected_frame, 1);
90adcf20
RS
761}
762\f
44fa5b1e 763/* Do a frame update, taking possible shortcuts into account.
a2889657
JB
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
90adcf20
RS
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;
a2889657 776 or with synchronous processes running.
90adcf20 777
a2889657
JB
778 See Fcall_process; if you called it from here, it could be
779 entered recursively. */
780
0d231165
RS
781static int do_verify_charstarts;
782
463f6b91
RS
783/* Counter is used to clear the face cache
784 no more than once ever 1000 redisplays. */
785static int clear_face_cache_count;
786
20de20dc
RS
787/* Record the previous terminal frame we displayed. */
788static FRAME_PTR previous_terminal_frame;
789
a2889657
JB
790void
791redisplay ()
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;
a2889657
JB
799
800 if (noninteractive)
801 return;
802
20de20dc
RS
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
d724d989
JB
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 {
35f56f96 821 Lisp_Object tail, frame;
d724d989 822
35f56f96 823 FOR_EACH_FRAME (tail, frame)
f82aff7c
RS
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 }
d724d989
JB
831 }
832
44fa5b1e 833 /* Notice any pending interrupt request to change frame size. */
a2889657
JB
834 do_pending_window_change ();
835
44fa5b1e 836 if (frame_garbaged)
a2889657 837 {
02a9b6e4 838 redraw_garbaged_frames ();
44fa5b1e 839 frame_garbaged = 0;
a2889657
JB
840 }
841
f82aff7c
RS
842 prepare_menu_bars ();
843
28995e67 844 if (windows_or_buffers_changed)
a2889657
JB
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
42640f83 849 && XFASTINT (w->last_modified) <= SAVE_MODIFF)
a2889657
JB
850 {
851 w->update_mode_line = Qt;
852 if (buffer_shared > 1)
853 update_mode_lines++;
854 }
855
28995e67
RS
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
44fa5b1e 865 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657
JB
866
867 all_windows = update_mode_lines || buffer_shared > 1;
a2889657
JB
868
869 /* If specs for an arrow have changed, do thorough redisplay
870 to ensure we remove any arrow that should no longer exist. */
ded34426
JB
871 if (! EQ (Voverlay_arrow_position, last_arrow_position)
872 || ! EQ (Voverlay_arrow_string, last_arrow_string))
28995e67 873 all_windows = 1;
a2889657 874
90adcf20
RS
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
bd66d1ba
RS
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))
82d04750
JB
889 || (!NILP (w->region_showing)
890 && !EQ (w->region_showing,
891 Fmarker_position (XBUFFER (w->buffer)->mark))))
bd66d1ba
RS
892 this_line_bufpos = -1;
893
a2889657
JB
894 tlbufpos = this_line_bufpos;
895 tlendpos = this_line_endpos;
265a9e55 896 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
73af359d 897 && !current_buffer->clip_changed
44fa5b1e 898 && FRAME_VISIBLE_P (XFRAME (w->frame))
a2889657
JB
899 /* Make sure recorded data applies to current buffer, etc */
900 && this_line_buffer == current_buffer
901 && current_buffer == XBUFFER (w->buffer)
265a9e55 902 && NILP (w->force_start)
a2889657 903 /* Point must be on the line that we have info recorded about */
ae3b1442
KH
904 && PT >= tlbufpos
905 && PT <= Z - tlendpos
a2889657
JB
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
05ba02eb
JB
911 /* If selective display, can't optimize
912 if the changes start at the beginning of the line. */
e24c997d 913 && ((INTEGERP (current_buffer->selective_display)
05ba02eb
JB
914 && XINT (current_buffer->selective_display) > 0
915 ? (beg_unchanged >= tlbufpos
916 && GPT > tlbufpos)
917 : 1))
a2889657
JB
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;
ca26e1c8 931 zv_strings_seen = 0;
a2889657
JB
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 {
0d231165
RS
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))
85bcef6c
RS
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];
85bcef6c
RS
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 }
46db8486 961
44fa5b1e 962 if (XFASTINT (w->width) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
a2889657
JB
963 preserve_other_columns (w);
964 goto update;
965 }
966 else
967 goto cancel;
968 }
b6f0fe04
RS
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)))
a2889657
JB
975 {
976 if (!must_finish)
977 {
978 do_pending_window_change ();
979 return;
980 }
981 goto update;
982 }
8b51f1e3
KH
983 /* If highlighting the region, or if the cursor is in the echo area,
984 then we can't just move the cursor. */
bd66d1ba
RS
985 else if (! (!NILP (Vtransient_mark_mode)
986 && !NILP (current_buffer->mark_active))
8b51f1e3
KH
987 && NILP (w->region_showing)
988 && !cursor_in_echo_area)
a2889657
JB
989 {
990 pos = *compute_motion (tlbufpos, 0,
991 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
ca26e1c8 992 0,
68be917d 993 PT, 2, - (1 << (BITS_PER_SHORT - 1)),
b1d1124b 994 window_internal_width (w) - 1,
de3e8b15 995 XINT (w->hscroll),
e37f06d7 996 pos_tab_offset (w, tlbufpos), w);
a2889657
JB
997 if (pos.vpos < 1)
998 {
210e752f 999 int width = window_internal_width (w) - 1;
44fa5b1e 1000 FRAME_CURSOR_X (selected_frame)
210e752f 1001 = XFASTINT (w->left) + minmax (0, pos.hpos, width);
44fa5b1e 1002 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
a2889657
JB
1003 goto update;
1004 }
1005 else
1006 goto cancel;
1007 }
1008 cancel:
1009 /* Text changed drastically or point moved off of line */
44fa5b1e 1010 cancel_line (this_line_vpos, selected_frame);
a2889657
JB
1011 }
1012
1013 this_line_bufpos = 0;
1014 all_windows |= buffer_shared > 1;
1015
463f6b91
RS
1016 clear_face_cache_count++;
1017
a2889657
JB
1018 if (all_windows)
1019 {
35f56f96 1020 Lisp_Object tail, frame;
a2889657 1021
87485d6f 1022#ifdef HAVE_FACES
463f6b91
RS
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 }
31b24551
JB
1030#endif
1031
a2889657 1032 /* Recompute # windows showing selected buffer.
8de2d90b 1033 This will be incremented each time such a window is displayed. */
a2889657
JB
1034 buffer_shared = 0;
1035
35f56f96 1036 FOR_EACH_FRAME (tail, frame)
30c566e4 1037 {
35f56f96 1038 FRAME_PTR f = XFRAME (frame);
9769686d
RS
1039 if (! FRAME_TERMCAP_P (f) || f == selected_frame)
1040 {
35f56f96 1041
9769686d
RS
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);
30c566e4 1046
9769686d
RS
1047 if (FRAME_VISIBLE_P (f))
1048 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 1049
9769686d
RS
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 }
30c566e4 1055 }
a2889657 1056 }
44fa5b1e 1057 else if (FRAME_VISIBLE_P (selected_frame))
a2889657
JB
1058 {
1059 redisplay_window (selected_window, 1);
44fa5b1e 1060 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
a2889657
JB
1061 preserve_other_columns (w);
1062 }
1063
1064update:
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
44fa5b1e 1072#ifdef MULTI_FRAME
a2889657
JB
1073 if (all_windows)
1074 {
1075 Lisp_Object tail;
1076
1077 pause = 0;
1078
44fa5b1e 1079 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
a2889657 1080 {
44fa5b1e 1081 FRAME_PTR f;
a2889657 1082
e24c997d 1083 if (!FRAMEP (XCONS (tail)->car))
a2889657
JB
1084 continue;
1085
44fa5b1e 1086 f = XFRAME (XCONS (tail)->car);
1af9f229
RS
1087
1088 if ((! FRAME_TERMCAP_P (f) || f == selected_frame)
1089 && FRAME_VISIBLE_P (f))
a2889657 1090 {
44fa5b1e 1091 pause |= update_frame (f, 0, 0);
a2889657 1092 if (!pause)
efc63ef0
RS
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 }
a2889657
JB
1098 }
1099 }
1100 }
1101 else
44fa5b1e 1102#endif /* MULTI_FRAME */
6e8290aa 1103 {
44fa5b1e
JB
1104 if (FRAME_VISIBLE_P (selected_frame))
1105 pause = update_frame (selected_frame, 0, 0);
4d641a15
KH
1106 else
1107 pause = 0;
d724d989 1108
8de2d90b 1109 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
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
8de2d90b
JB
1113 it here. */
1114 {
84faf44c
RS
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)));
8de2d90b 1120
20de20dc
RS
1121 if (mini_frame != selected_frame
1122 && ! FRAME_TERMCAP_P (mini_frame))
44fa5b1e 1123 pause |= update_frame (mini_frame, 0, 0);
8de2d90b 1124 }
6e8290aa 1125 }
a2889657 1126
44fa5b1e 1127 /* If frame does not match, prevent doing single-line-update next time.
a2889657
JB
1128 Also, don't forget to check every line to update the arrow. */
1129 if (pause)
1130 {
1131 this_line_bufpos = 0;
265a9e55 1132 if (!NILP (last_arrow_position))
a2889657
JB
1133 {
1134 last_arrow_position = Qt;
1135 last_arrow_string = Qt;
1136 }
44fa5b1e 1137 /* If we pause after scrolling, some lines in current_frame
a2889657
JB
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. */
44fa5b1e 1141 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
a2889657
JB
1142 update_mode_lines = 1;
1143 }
1144
44fa5b1e 1145 /* Now text on frame agrees with windows, so
a2889657
JB
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;
a2889657
JB
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
c2213350
KH
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));
a2889657
JB
1160
1161 if (all_windows)
11e82b76 1162 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
a2889657
JB
1163 else
1164 {
28995e67 1165 b->clip_changed = 0;
a2889657 1166 w->update_mode_line = Qnil;
c2213350 1167 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
d2f84654 1168 w->window_end_valid = w->buffer;
a2889657
JB
1169 last_arrow_position = Voverlay_arrow_position;
1170 last_arrow_string = Voverlay_arrow_string;
0d231165
RS
1171 if (do_verify_charstarts)
1172 verify_charstarts (w);
efc63ef0
RS
1173 if (frame_up_to_date_hook != 0)
1174 (*frame_up_to_date_hook) (selected_frame);
a2889657
JB
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
44fa5b1e 1191 /* Change frame size now if a change is pending. */
a2889657 1192 do_pending_window_change ();
d8e242fd
RS
1193
1194 /* If we just did a pending size change, redisplay again
1195 for the new size. */
3c8c72e0 1196 if (windows_or_buffers_changed && !pause)
d8e242fd 1197 redisplay ();
a2889657
JB
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
1208redisplay_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
1220void
1221mark_window_display_accurate (window, flag)
1222 Lisp_Object window;
1223 int flag;
1224{
1225 register struct window *w;
1226
265a9e55 1227 for (;!NILP (window); window = w->next)
a2889657 1228 {
e24c997d 1229 if (!WINDOWP (window)) abort ();
a2889657
JB
1230 w = XWINDOW (window);
1231
265a9e55 1232 if (!NILP (w->buffer))
bd66d1ba 1233 {
c2213350
KH
1234 XSETFASTINT (w->last_modified,
1235 !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
bd66d1ba
RS
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
d2f84654 1245 w->window_end_valid = w->buffer;
a2889657 1246 w->update_mode_line = Qnil;
051e7076 1247 if (!NILP (w->buffer) && flag)
28995e67 1248 XBUFFER (w->buffer)->clip_changed = 0;
a2889657 1249
265a9e55 1250 if (!NILP (w->vchild))
a2889657 1251 mark_window_display_accurate (w->vchild, flag);
265a9e55 1252 if (!NILP (w->hchild))
a2889657
JB
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
ecf7de9b 1269/* Update the menu bar item list for frame F.
90adcf20 1270 This has to be done before we start to fill in any display lines,
a2725ab2
RS
1271 because it can call eval.
1272
1273 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
90adcf20
RS
1274
1275static void
a2725ab2 1276update_menu_bar (f, save_match_data)
ecf7de9b 1277 FRAME_PTR f;
a2725ab2 1278 int save_match_data;
90adcf20 1279{
90adcf20 1280 struct buffer *old = current_buffer;
ecf7de9b
RS
1281 Lisp_Object window;
1282 register struct window *w;
a2725ab2 1283
ecf7de9b
RS
1284 window = FRAME_SELECTED_WINDOW (f);
1285 w = XWINDOW (window);
90adcf20
RS
1286
1287 if (update_mode_lines)
1288 w->update_mode_line = Qt;
1289
d1e74921 1290 if (FRAME_WINDOW_P (f)
d3413a53 1291 ?
dc937613 1292#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
cf074754 1293 FRAME_EXTERNAL_MENU_BAR (f)
78614721 1294#else
cf074754 1295 FRAME_MENU_BAR_LINES (f) > 0
78614721 1296#endif
d3413a53 1297 : FRAME_MENU_BAR_LINES (f) > 0)
90adcf20
RS
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
cf074754 1307 || !NILP (w->update_mode_line)
90adcf20
RS
1308 || (XFASTINT (w->last_modified) < MODIFF
1309 && (XFASTINT (w->last_modified)
94bb7f9b
KH
1310 <= BUF_SAVE_MODIFF (XBUFFER (w->buffer))))
1311 || ((!NILP (Vtransient_mark_mode)
1312 && !NILP (XBUFFER (w->buffer)->mark_active))
1313 != !NILP (w->region_showing)))
90adcf20
RS
1314 {
1315 struct buffer *prev = current_buffer;
a2725ab2
RS
1316 int count = specpdl_ptr - specpdl;
1317
399164b4 1318 set_buffer_internal_1 (XBUFFER (w->buffer));
eac4251c 1319 if (save_match_data)
a2725ab2 1320 record_unwind_protect (Fstore_match_data, Fmatch_data ());
399164b4 1321 if (NILP (Voverriding_local_map_menu_flag))
d46fb96a
KH
1322 {
1323 specbind (Qoverriding_terminal_local_map, Qnil);
1324 specbind (Qoverriding_local_map, Qnil);
1325 }
a2725ab2 1326
34acc8e6
KH
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);
e02500d4 1333 safe_run_hooks (Qmenu_bar_update_hook);
8351baf2 1334 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
8f3343d0 1335#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
d1e74921 1336 if (FRAME_WINDOW_P (f))
d3413a53 1337 set_frame_menubar (f, 0, 0);
8f3343d0 1338#endif /* USE_X_TOOLKIT || HAVE_NTGUI */
a2725ab2
RS
1339
1340 unbind_to (count, Qnil);
399164b4 1341 set_buffer_internal_1 (prev);
90adcf20
RS
1342 }
1343 }
1344}
1345\f
a2889657
JB
1346int do_id = 1;
1347
90adcf20
RS
1348/* Redisplay WINDOW and its subwindows and siblings. */
1349
a2889657
JB
1350static void
1351redisplay_windows (window)
1352 Lisp_Object window;
1353{
265a9e55 1354 for (; !NILP (window); window = XWINDOW (window)->next)
a2889657
JB
1355 redisplay_window (window, 0);
1356}
1357
90adcf20
RS
1358/* Redisplay window WINDOW and its subwindows. */
1359
a2889657
JB
1360static void
1361redisplay_window (window, just_this_one)
1362 Lisp_Object window;
1363 int just_this_one;
1364{
1365 register struct window *w = XWINDOW (window);
30c566e4 1366 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
a2889657 1367 int height;
ae3b1442 1368 register int lpoint = PT;
a2889657 1369 struct buffer *old = current_buffer;
b1d1124b 1370 register int width = window_internal_width (w) - 1;
a2889657
JB
1371 register int startp;
1372 register int hscroll = XINT (w->hscroll);
1373 struct position pos;
ae3b1442 1374 int opoint = PT;
a2889657 1375 int tem;
e481f960 1376 int update_mode_line;
f908610f 1377 struct Lisp_Char_Table *dp = window_display_table (w);
a2889657 1378
44fa5b1e 1379 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
a2889657
JB
1380
1381 /* If this is a combination window, do its children; that's all. */
1382
265a9e55 1383 if (!NILP (w->vchild))
a2889657
JB
1384 {
1385 redisplay_windows (w->vchild);
1386 return;
1387 }
265a9e55 1388 if (!NILP (w->hchild))
a2889657
JB
1389 {
1390 redisplay_windows (w->hchild);
1391 return;
1392 }
265a9e55 1393 if (NILP (w->buffer))
a2889657 1394 abort ();
8de2d90b
JB
1395
1396 height = window_internal_height (w);
4d641a15 1397 update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
73af359d
RS
1398 if (XBUFFER (w->buffer)->clip_changed)
1399 update_mode_line = 1;
8de2d90b
JB
1400
1401 if (MINI_WINDOW_P (w))
1402 {
73af359d
RS
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))
8de2d90b 1407 {
73af359d
RS
1408 /* This is a minibuffer, but it's not the currently active one,
1409 so clear it. */
1410 int vpos = XFASTINT (w->top);
8de2d90b
JB
1411 int i;
1412
1413 for (i = 0; i < height; i++)
1414 {
44fa5b1e 1415 get_display_line (f, vpos + i, 0);
278feba9 1416 display_string (w, vpos + i, "", 0, 0, 0, 1, 0, width);
8de2d90b
JB
1417 }
1418
88f22aff 1419 goto finish_scroll_bars;
8de2d90b
JB
1420 }
1421 }
a2889657 1422
a2889657
JB
1423 /* Otherwise set up data on this window; select its buffer and point value */
1424
e481f960 1425 if (update_mode_line)
f72df6ac 1426 set_buffer_internal_1 (XBUFFER (w->buffer));
e481f960
RS
1427 else
1428 set_buffer_temp (XBUFFER (w->buffer));
1429
ae3b1442 1430 opoint = PT;
a2889657 1431
28995e67
RS
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
42640f83
RS
1441 /* Count number of windows showing the selected buffer.
1442 An indirect buffer counts as its base buffer. */
a2889657 1443
42640f83
RS
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 }
a2889657
JB
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 {
f67a0f51
RS
1462 int new_pt = marker_position (w->pointm);
1463 if (new_pt < BEGV)
a2889657 1464 {
f67a0f51
RS
1465 new_pt = BEGV;
1466 Fset_marker (w->pointm, make_number (new_pt), Qnil);
a2889657 1467 }
f67a0f51 1468 else if (new_pt > (ZV - 1))
a2889657 1469 {
f67a0f51
RS
1470 new_pt = ZV;
1471 Fset_marker (w->pointm, make_number (new_pt), Qnil);
a2889657 1472 }
f67a0f51
RS
1473 /* We don't use SET_PT so that the point-motion hooks don't run. */
1474 BUF_PT (current_buffer) = new_pt;
a2889657
JB
1475 }
1476
f4faa47c
JB
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 {
f908610f 1484 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
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
a2889657 1496 /* If window-start is screwed up, choose a new one. */
a2889657
JB
1497 if (XMARKER (w->start)->buffer != current_buffer)
1498 goto recenter;
1499
1500 startp = marker_position (w->start);
1501
8de2d90b 1502 /* Handle case where place to start displaying has been specified,
aa6d10fa 1503 unless the specified location is outside the accessible range. */
265a9e55 1504 if (!NILP (w->force_start))
a2889657 1505 {
e63574d7 1506 w->force_start = Qnil;
aa6d10fa
RS
1507 /* Forget any recorded base line for line number display. */
1508 w->base_line_number = Qnil;
75c43375
RS
1509 /* Redisplay the mode line. Select the buffer properly for that.
1510 Also, run the hook window-scroll-functions
1511 because we have scrolled. */
e63574d7
RS
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. */
75c43375
RS
1516 if (!update_mode_line
1517 || ! NILP (Vwindow_scroll_functions))
e481f960 1518 {
75c43375
RS
1519 Lisp_Object temp[3];
1520
e481f960 1521 set_buffer_temp (old);
f72df6ac 1522 set_buffer_internal_1 (XBUFFER (w->buffer));
e481f960
RS
1523 update_mode_line = 1;
1524 w->update_mode_line = Qt;
75c43375
RS
1525 if (! NILP (Vwindow_scroll_functions))
1526 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1527 make_number (startp));
e481f960 1528 }
c2213350 1529 XSETFASTINT (w->last_modified, 0);
8de2d90b
JB
1530 if (startp < BEGV) startp = BEGV;
1531 if (startp > ZV) startp = ZV;
a2889657
JB
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,
ca26e1c8
KH
1537 (((EQ (window, minibuf_window)
1538 && startp == BEG)
1539 ? minibuf_prompt_width : 0)
1540 + (hscroll ? 1 - hscroll : 0)),
1541 0,
1542 ZV, height / 2,
68be917d 1543 - (1 << (BITS_PER_SHORT - 1)),
ca26e1c8 1544 width, hscroll, pos_tab_offset (w, startp), w);
f67a0f51 1545 BUF_PT (current_buffer) = pos.bufpos;
90adcf20 1546 if (w != XWINDOW (selected_window))
ae3b1442 1547 Fset_marker (w->pointm, make_number (PT), Qnil);
a2889657
JB
1548 else
1549 {
9d6a6bb9 1550 if (current_buffer == old)
ae3b1442 1551 lpoint = PT;
210e752f
KH
1552 FRAME_CURSOR_X (f) = (XFASTINT (w->left)
1553 + minmax (0, pos.hpos, width));
44fa5b1e 1554 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
a2889657 1555 }
df0b5ea1
RS
1556 /* If we are highlighting the region,
1557 then we just changed the region, so redisplay to show it. */
df0b5ea1
RS
1558 if (!NILP (Vtransient_mark_mode)
1559 && !NILP (current_buffer->mark_active))
6f27fa9b
RS
1560 {
1561 cancel_my_columns (XWINDOW (window));
1562 try_window (window, startp);
1563 }
a2889657
JB
1564 }
1565 goto done;
1566 }
1567
1568 /* Handle case where text has not changed, only point,
208aee63 1569 and it has not moved off the frame. */
a2889657
JB
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
86bee31c 1579 && PT >= startp && !current_buffer->clip_changed
44fa5b1e 1580 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
b1aa6cb3
RS
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. */
632ab665 1584 && NILP (w->update_mode_line)
bd66d1ba
RS
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)
15495c73
KH
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)
a2889657
JB
1591 && !EQ (window, minibuf_window))
1592 {
ca26e1c8 1593 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
632ab665 1594 PT, height, 0, width, hscroll,
e37f06d7 1595 pos_tab_offset (w, startp), w);
a2889657
JB
1596
1597 if (pos.vpos < height)
1598 {
44fa5b1e
JB
1599 /* Ok, point is still on frame */
1600 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
a2889657
JB
1601 {
1602 /* These variables are supposed to be origin 1 */
210e752f
KH
1603 FRAME_CURSOR_X (f) = (XFASTINT (w->left)
1604 + minmax (0, pos.hpos, width));
44fa5b1e 1605 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
a2889657
JB
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
44fa5b1e 1609 is nothing in DesiredFrame yet, and then the other window is
a2889657 1610 redisplayed, making likes that are empty in this window's columns.
44fa5b1e 1611 if (XFASTINT (w->width) != FRAME_WIDTH (f))
a2889657
JB
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. */
265a9e55 1621 else if (!NILP (w->start_at_line_beg)
b16234d8 1622 && !(startp <= BEGV
a2889657
JB
1623 || FETCH_CHAR (startp - 1) == '\n'))
1624 {
1625 goto recenter;
1626 }
1627 else if (just_this_one && !MINI_WINDOW_P (w)
ae3b1442 1628 && PT >= startp
a2889657 1629 && XFASTINT (w->last_modified)
14709f21
JB
1630 /* or else vmotion on first line won't work. */
1631 && ! NILP (w->start_at_line_beg)
a2889657 1632 && ! EQ (w->window_end_valid, Qnil)
86bee31c 1633 && do_id && !current_buffer->clip_changed
a2889657 1634 && !blank_end_of_window
44fa5b1e 1635 && XFASTINT (w->width) == FRAME_WIDTH (f)
bd66d1ba
RS
1636 /* Can't use this case if highlighting a region. */
1637 && !(!NILP (Vtransient_mark_mode)
1638 && !NILP (current_buffer->mark_active))
23c852cb
KH
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')))
bd66d1ba 1642 && NILP (w->region_showing)
a2889657
JB
1643 && EQ (last_arrow_position, Voverlay_arrow_position)
1644 && EQ (last_arrow_string, Voverlay_arrow_string)
44fa5b1e 1645 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
a2889657
JB
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! */
8de2d90b 1657 && (startp < ZV || startp == BEGV
a2889657
JB
1658 || (XFASTINT (w->last_modified) >= MODIFF)))
1659 {
1660 /* Try to redisplay starting at same place as before */
44fa5b1e 1661 /* If point has not moved off frame, accept the results */
a2889657
JB
1662 try_window (window, startp);
1663 if (cursor_vpos >= 0)
aa6d10fa 1664 {
28995e67
RS
1665 if (!just_this_one || current_buffer->clip_changed
1666 || beg_unchanged < startp)
aa6d10fa
RS
1667 /* Forget any recorded base line for line number display. */
1668 w->base_line_number = Qnil;
1669 goto done;
1670 }
a2889657
JB
1671 else
1672 cancel_my_columns (w);
1673 }
1674
c2213350 1675 XSETFASTINT (w->last_modified, 0);
e481f960
RS
1676 /* Redisplay the mode line. Select the buffer properly for that. */
1677 if (!update_mode_line)
1678 {
1679 set_buffer_temp (old);
f72df6ac 1680 set_buffer_internal_1 (XBUFFER (w->buffer));
e481f960
RS
1681 update_mode_line = 1;
1682 w->update_mode_line = Qt;
1683 }
a2889657
JB
1684
1685 /* Try to scroll by specified few lines */
1686
2c081c2d
KH
1687 if (scroll_step && !current_buffer->clip_changed
1688 && startp >= BEGV && startp <= ZV)
a2889657 1689 {
ae3b1442 1690 if (PT > startp)
a2889657 1691 {
210e752f 1692 pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
a2889657
JB
1693 if (pos.vpos >= height)
1694 goto scroll_fail;
1695 }
1696
210e752f 1697 pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
a2889657 1698
ae3b1442 1699 if (PT >= pos.bufpos)
a2889657 1700 {
75c43375
RS
1701 if (! NILP (Vwindow_scroll_functions))
1702 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1703 make_number (pos.bufpos));
a2889657
JB
1704 try_window (window, pos.bufpos);
1705 if (cursor_vpos >= 0)
aa6d10fa 1706 {
28995e67
RS
1707 if (!just_this_one || current_buffer->clip_changed
1708 || beg_unchanged < startp)
aa6d10fa
RS
1709 /* Forget any recorded base line for line number display. */
1710 w->base_line_number = Qnil;
1711 goto done;
1712 }
a2889657
JB
1713 else
1714 cancel_my_columns (w);
1715 }
1716 scroll_fail: ;
1717 }
1718
1719 /* Finally, just choose place to start which centers point */
1720
1721recenter:
aa6d10fa
RS
1722 /* Forget any previously recorded base line for line number display. */
1723 w->base_line_number = Qnil;
1724
210e752f 1725 pos = *vmotion (PT, - (height / 2), w);
e63574d7
RS
1726 /* Set startp here explicitly in case that helps avoid an infinite loop
1727 in case the window-scroll-functions functions get errors. */
208aee63 1728 Fset_marker (w->start, make_number (pos.bufpos), Qnil);
75c43375
RS
1729 if (! NILP (Vwindow_scroll_functions))
1730 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1731 make_number (pos.bufpos));
a2889657
JB
1732 try_window (window, pos.bufpos);
1733
1734 startp = marker_position (w->start);
ca26e1c8 1735 w->start_at_line_beg
b16234d8 1736 = (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
a2889657
JB
1737
1738done:
e481f960 1739 if ((update_mode_line
aa6d10fa
RS
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)
155ef550
KH
1743 || INTEGERP (w->base_line_pos)
1744 || (!NILP (w->column_number_displayed)
1745 && XFASTINT (w->column_number_displayed) != current_column ()))
a2889657
JB
1746 && height != XFASTINT (w->height))
1747 display_mode_line (w);
aa6d10fa
RS
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 }
a2889657 1754
7ce2c095 1755 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 1756 if (update_mode_line
d1e74921 1757 && (FRAME_WINDOW_P (f)
d3413a53 1758 ?
dc937613 1759#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
d3413a53 1760 FRAME_EXTERNAL_MENU_BAR (f)
76412d64 1761#else
d3413a53 1762 FRAME_MENU_BAR_LINES (f) > 0
76412d64 1763#endif
d3413a53 1764 : FRAME_MENU_BAR_LINES (f) > 0)
7ce2c095
RS
1765 && EQ (FRAME_SELECTED_WINDOW (f), window))
1766 display_menu_bar (w);
1767
88f22aff
JB
1768 finish_scroll_bars:
1769 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 1770 {
b1d1124b 1771 int start, end, whole;
30c566e4 1772
b1d1124b 1773 /* Calculate the start and end positions for the current window.
3505ea70
JB
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
b1d1124b
JB
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 {
8a9311d7 1783 whole = ZV - BEGV;
4d641a15 1784 start = marker_position (w->start) - BEGV;
b1d1124b
JB
1785 /* I don't think this is guaranteed to be right. For the
1786 moment, we'll pretend it is. */
85f26be9 1787 end = (Z - XINT (w->window_end_pos)) - BEGV;
3505ea70
JB
1788
1789 if (end < start) end = start;
8a9311d7 1790 if (whole < (end - start)) whole = end - start;
b1d1124b
JB
1791 }
1792 else
1793 start = end = whole = 0;
30c566e4 1794
88f22aff 1795 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 1796 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 1797
88f22aff 1798 /* Note that we actually used the scroll bar attached to this window,
30c566e4 1799 so it shouldn't be deleted at the end of redisplay. */
88f22aff 1800 (*redeem_scroll_bar_hook) (w);
30c566e4 1801 }
b1d1124b 1802
f67a0f51 1803 BUF_PT (current_buffer) = opoint;
e481f960 1804 if (update_mode_line)
f72df6ac 1805 set_buffer_internal_1 (old);
e481f960
RS
1806 else
1807 set_buffer_temp (old);
f67a0f51 1808 BUF_PT (current_buffer) = lpoint;
a2889657
JB
1809}
1810\f
1811/* Do full redisplay on one window, starting at position `pos'. */
1812
1813static void
1814try_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);
44fa5b1e 1823 FRAME_PTR f = XFRAME (w->frame);
b1d1124b 1824 int width = window_internal_width (w) - 1;
a2889657
JB
1825 struct position val;
1826
1827 Fset_marker (w->start, make_number (pos), Qnil);
1828 cursor_vpos = -1;
1829 overlay_arrow_seen = 0;
ca26e1c8 1830 zv_strings_seen = 0;
a2889657
JB
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;
2b050fec
RS
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
a2889657
JB
1845 if (val.vpos) tab_offset = 0;
1846 vpos++;
1847 if (pos != val.bufpos)
642eefc6
RS
1848 {
1849 int invis = 0;
e885523c 1850#ifdef USE_TEXT_PROPERTIES
642eefc6
RS
1851 Lisp_Object invis_prop;
1852 invis_prop = Fget_char_property (val.bufpos-1, Qinvisible, window);
1853 invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
e885523c 1854#endif
642eefc6
RS
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 }
a2889657
JB
1861 pos = val.bufpos;
1862 }
1863
1864 /* If last line is continued in middle of character,
44fa5b1e 1865 include the split character in the text considered on the frame */
a2889657
JB
1866 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
1867 pos++;
1868
44fa5b1e 1869 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
1870 if (XFASTINT (w->window_end_pos) == 0
1871 && Z != pos)
1872 w->update_mode_line = Qt;
1873
44fa5b1e 1874 /* Say where last char on frame will be, once redisplay is finished. */
c2213350
KH
1875 XSETFASTINT (w->window_end_pos, Z - pos);
1876 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
a2889657
JB
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
1888static int
1889try_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);
44fa5b1e 1895 FRAME_PTR f = XFRAME (w->frame);
a2889657
JB
1896 int top = XFASTINT (w->top);
1897 int start = marker_position (w->start);
b1d1124b 1898 int width = window_internal_width (w) - 1;
a2889657
JB
1899 int hscroll = XINT (w->hscroll);
1900 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
ca26e1c8 1901 int did_motion;
a2889657
JB
1902 register int vpos;
1903 register int i, tem;
1904 int last_text_vpos = 0;
1905 int stop_vpos;
e24c997d
KH
1906 int selective = (INTEGERP (current_buffer->selective_display)
1907 ? XINT (current_buffer->selective_display)
1908 : !NILP (current_buffer->selective_display) ? -1 : 0);
a2889657
JB
1909
1910 struct position val, bp, ep, xp, pp;
1911 int scroll_amount = 0;
1912 int delta;
d3413a53 1913 int tab_offset, epto, old_tick;
a2889657
JB
1914
1915 if (GPT - BEG < beg_unchanged)
1916 beg_unchanged = GPT - BEG;
1917 if (Z - GPT < end_unchanged)
1918 end_unchanged = Z - GPT;
1919
6a1dc7ac 1920 if (beg_unchanged + BEG < start)
a2889657
JB
1921 return 0; /* Give up if changes go above top of window */
1922
1923 /* Find position before which nothing is changed. */
ca26e1c8 1924 bp = *compute_motion (start, 0, lmargin, 0,
632ab665 1925 min (ZV, beg_unchanged + BEG), height, 0,
e37f06d7 1926 width, hscroll, pos_tab_offset (w, start), w);
a2889657 1927 if (bp.vpos >= height)
6e8290aa 1928 {
632ab665 1929 if (PT < bp.bufpos)
6e8290aa 1930 {
67481ae5
RS
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.
6e8290aa
JB
1933 But we need to update window_end_pos to account for
1934 any change in buffer size. */
ca26e1c8 1935 bp = *compute_motion (start, 0, lmargin, 0,
67481ae5 1936 ZV, height, 0,
e37f06d7 1937 width, hscroll, pos_tab_offset (w, start), w);
c2213350
KH
1938 XSETFASTINT (w->window_end_vpos, height);
1939 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
4d641a15 1940 goto findpoint;
6e8290aa
JB
1941 }
1942 return 0;
1943 }
a2889657
JB
1944
1945 vpos = bp.vpos;
1946
44fa5b1e 1947 /* Find beginning of that frame line. Must display from there. */
210e752f 1948 bp = *vmotion (bp.bufpos, 0, w);
a2889657
JB
1949
1950 pos = bp.bufpos;
1951 val.hpos = lmargin;
1952 if (pos < start)
1953 return -1;
1954
ca26e1c8 1955 did_motion = 0;
a2889657 1956 /* If about to start displaying at the beginning of a continuation line,
44fa5b1e 1957 really start with previous frame line, in case it was not
a2889657 1958 continued when last redisplayed */
05ba02eb
JB
1959 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
1960 ||
1961 /* Likewise if we have to worry about selective display. */
9f412332 1962 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
a2889657 1963 {
210e752f 1964 bp = *vmotion (bp.bufpos, -1, w);
a2889657
JB
1965 --vpos;
1966 pos = bp.bufpos;
1967 }
1968
1969 if (bp.contin && bp.hpos != lmargin)
1970 {
1971 val.hpos = bp.prevhpos - width + lmargin;
ca26e1c8 1972 did_motion = 1;
a2889657
JB
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);
9f412332
KH
1980 if (selective > 0)
1981 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
a2889657
JB
1982 tem = find_next_newline (tem, 1);
1983
1984 /* Compute the cursor position after that newline. */
ca26e1c8 1985 ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
68be917d 1986 height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7 1987 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
a2889657 1988
44fa5b1e
JB
1989 /* If changes reach past the text available on the frame,
1990 just display rest of frame. */
a2889657
JB
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;
ca26e1c8 2009 zv_strings_seen = 0;
a2889657
JB
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);
ca26e1c8 2017 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
a2889657 2018 Z - XFASTINT (w->window_end_pos),
e37f06d7 2019 10000, 0, width, hscroll, epto, w);
a2889657
JB
2020 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
2021
44fa5b1e 2022 /* Is everything on frame below the changes whitespace?
a2889657
JB
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
e8e536a9
KH
2033 XSETFASTINT (w->window_end_vpos,
2034 XFASTINT (w->window_end_vpos) + scroll_amount);
a2889657 2035
44fa5b1e 2036 /* Before doing any scrolling, verify that point will be on frame. */
ae3b1442 2037 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
a2889657 2038 {
ae3b1442 2039 if (PT <= xp.bufpos)
a2889657 2040 {
ca26e1c8 2041 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
68be917d 2042 PT, height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7 2043 width, hscroll, epto, w);
a2889657
JB
2044 }
2045 else
2046 {
ca26e1c8 2047 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
68be917d 2048 PT, height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7
KH
2049 width, hscroll,
2050 pos_tab_offset (w, xp.bufpos), w);
a2889657 2051 }
ae3b1442 2052 if (pp.bufpos < PT || pp.vpos == height)
a2889657
JB
2053 return 0;
2054 cursor_vpos = pp.vpos + top;
210e752f 2055 cursor_hpos = XFASTINT (w->left) + minmax (0, pp.hpos, width);
a2889657
JB
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
44fa5b1e 2067 before the frame changes to reflect what we do here,
a2889657 2068 further updates will not come to try_window_id
44fa5b1e 2069 and assume the frame and window_end_vpos match. */
a2889657
JB
2070 blank_end_of_window = 1;
2071 }
2072 else if (!scroll_amount)
0d231165
RS
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 }
a2889657
JB
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. */
44fa5b1e 2085 if (scroll_cost (f, bp.vpos + top - scroll_amount,
a2889657
JB
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. */
44fa5b1e 2096 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
d1cb44a4
RS
2097 top + height - max (0, scroll_amount),
2098 scroll_amount, bp.bufpos);
d2f84654
RS
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.)
8e6208c5
KH
2107 To adjust properly, we need to make things consistent
2108 at the position ep.
d2f84654
RS
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 }
a2889657
JB
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. */
44fa5b1e 2125 if (scroll_cost (f, ep.vpos + top - scroll_amount,
a2889657
JB
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;
44fa5b1e 2132 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
a2889657 2133 top + height - max (0, scroll_amount),
d1cb44a4 2134 scroll_amount, ep.bufpos);
a2889657
JB
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;
d3413a53 2158 old_tick = MODIFF;
a2889657
JB
2159 while (vpos < stop_vpos)
2160 {
2161 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
d3413a53
RS
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;
a2889657
JB
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,
44fa5b1e 2183 include the split character in the text considered on the frame */
a2889657
JB
2184 if (val.hpos < lmargin)
2185 val.bufpos++;
c2213350
KH
2186 XSETFASTINT (w->window_end_vpos, last_text_vpos);
2187 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
a2889657
JB
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. */
44fa5b1e 2196 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
a2889657
JB
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
ae3b1442 2226 && xp.bufpos == PT)
a2889657
JB
2227 cursor_vpos = -1;
2228 }
2229
44fa5b1e 2230 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
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 {
210e752f 2243 val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
c2213350 2244 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
e8e536a9
KH
2245 XSETFASTINT (w->window_end_vpos,
2246 XFASTINT (w->window_end_vpos) + val.vpos);
a2889657
JB
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 {
4d641a15 2255 findpoint:
ca26e1c8 2256 val = *compute_motion (start, 0, lmargin, 0, PT, 10000, 10000,
e37f06d7 2257 width, hscroll, pos_tab_offset (w, start), w);
44fa5b1e 2258 /* Admit failure if point is off frame now */
a2889657
JB
2259 if (val.vpos >= height)
2260 {
2261 for (vpos = 0; vpos < height; vpos++)
44fa5b1e 2262 cancel_line (vpos + top, f);
a2889657
JB
2263 return 0;
2264 }
2265 cursor_vpos = val.vpos + top;
210e752f 2266 cursor_hpos = XFASTINT (w->left) + minmax (0, val.hpos, width);
a2889657
JB
2267 }
2268
210e752f 2269 FRAME_CURSOR_X (f) = cursor_hpos;
44fa5b1e 2270 FRAME_CURSOR_Y (f) = cursor_vpos;
a2889657
JB
2271
2272 if (debug_end_pos)
2273 {
ca26e1c8 2274 val = *compute_motion (start, 0, lmargin, 0, ZV,
68be917d 2275 height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7 2276 width, hscroll, pos_tab_offset (w, start), w);
a2889657
JB
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
31b24551
JB
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
2306void
2307redisplay_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
70bcb498
RS
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;
99b9e975
RS
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;
70bcb498
RS
2327 /* If multiple windows show this buffer, we must do other windows. */
2328 else if (buffer_shared > 1)
31b24551
JB
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
42640f83
RS
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)++;
31b24551
JB
2350 if (BUF_MODIFF (buf) == buf->auto_save_modified)
2351 buf->auto_save_modified++;
2352
2353 BUF_MODIFF (buf) ++;
2354}
2355
2356\f
278feba9 2357/* Copy LEN glyphs starting address FROM to the rope TO.
f7430cb6 2358 But don't actually copy the parts that would come in before S.
278feba9
RS
2359 Value is TO, advanced past the copied data.
2360 F is the frame we are displaying in. */
a2889657 2361
278feba9
RS
2362static GLYPH *
2363copy_part_of_rope (f, to, s, from, len, face)
2364 FRAME_PTR f;
2365 register GLYPH *to; /* Copy to here. */
a2889657 2366 register GLYPH *s; /* Starting point. */
278feba9
RS
2367 Lisp_Object *from; /* Data to copy. */
2368 int len;
1c2250c2 2369 int face; /* Face to apply to glyphs which don't specify one. */
a2889657 2370{
278feba9
RS
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;
c581d710 2376
87485d6f 2377#ifdef HAVE_FACES
4cdc65eb
KH
2378 if (! FRAME_TERMCAP_P (f))
2379 while (n--)
2380 {
dedd1182 2381 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb
KH
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 }
b2a76982 2396
4cdc65eb
KH
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 {
dedd1182 2406 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb
KH
2407 ++to;
2408 ++fp;
2409 }
278feba9 2410 return to;
c581d710
RS
2411}
2412
278feba9
RS
2413/* Correct a glyph by replacing its specified user-level face code
2414 with a displayable computed face code. */
c581d710 2415
278feba9 2416static GLYPH
659a218f 2417fix_glyph (f, glyph, cface)
278feba9
RS
2418 FRAME_PTR f;
2419 GLYPH glyph;
659a218f 2420 int cface;
c581d710 2421{
87485d6f 2422#ifdef HAVE_FACES
659a218f
KH
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 }
4cdc65eb
KH
2429#endif
2430 return glyph;
a2889657
JB
2431}
2432\f
f4faa47c
JB
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.
a2889657
JB
2442
2443 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
2444
f4faa47c
JB
2445 Display on position VPOS on the frame. It is origin 0, relative to
2446 the top of the frame, not W.
a2889657
JB
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
2452struct position val_display_text_line;
2453
2454static struct position *
2455display_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;
a2889657
JB
2465 register int pause;
2466 register unsigned char *p;
2467 GLYPH *endp;
d2f84654 2468 register GLYPH *leftmargin;
ca26e1c8 2469 register GLYPH *p1prev;
efc63ef0 2470 register GLYPH *p1start;
ca26e1c8 2471 int prevpos;
efc63ef0 2472 int *charstart;
44fa5b1e 2473 FRAME_PTR f = XFRAME (w->frame);
a2889657 2474 int tab_width = XINT (current_buffer->tab_width);
265a9e55 2475 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
b1d1124b 2476 int width = window_internal_width (w) - 1;
a2889657
JB
2477 struct position val;
2478 int lastpos;
2479 int invis;
642eefc6
RS
2480 int last_invis_skip = 0;
2481 Lisp_Object last_invis_prop;
a2889657 2482 int hscroll = XINT (w->hscroll);
d2f84654
RS
2483 int truncate = (hscroll
2484 || (truncate_partial_width_windows
2485 && XFASTINT (w->width) < FRAME_WIDTH (f))
2486 || !NILP (current_buffer->truncate_lines));
bd66d1ba
RS
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
e24c997d
KH
2493 int selective = (INTEGERP (current_buffer->selective_display)
2494 ? XINT (current_buffer->selective_display)
2495 : !NILP (current_buffer->selective_display) ? -1 : 0);
44fa5b1e 2496 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
f908610f 2497 register struct Lisp_Char_Table *dp = window_display_table (w);
68a37fa8
RS
2498
2499 Lisp_Object default_invis_vector[3];
642eefc6
RS
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. */
a2889657 2504 int selective_rlen
642eefc6 2505 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
68a37fa8 2506 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
642eefc6 2507 : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
68a37fa8
RS
2508 /* This is the sequence of Lisp objects to display
2509 when there are invisible lines. */
2510 Lisp_Object *invis_vector_contents
e24c997d 2511 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
68a37fa8
RS
2512 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2513 : default_invis_vector);
2514
e24c997d 2515 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
278feba9 2516 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
e24c997d 2517 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
278feba9 2518 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
a2889657 2519
31b24551
JB
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
ca26e1c8
KH
2524 /* The next location where the `invisible' property changes, or an
2525 overlay starts or ends. */
2526 int next_boundary;
2527
31b24551 2528 /* The face we're currently using. */
1c2250c2 2529 int current_face = 0;
efc63ef0 2530 int i;
31b24551 2531
c2213350 2532 XSETFASTINT (default_invis_vector[2], '.');
68a37fa8
RS
2533 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2534
a2889657 2535 hpos += XFASTINT (w->left);
44fa5b1e 2536 get_display_line (f, vpos, XFASTINT (w->left));
54ff581a 2537 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657 2538
bd66d1ba 2539 /* Show where to highlight the region. */
1613b757 2540 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
fba9ce76
RS
2541 /* Maybe highlight only in selected window. */
2542 && (highlight_nonselected_windows
6f139a45 2543 || w == XWINDOW (selected_window)))
bd66d1ba
RS
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
f4faa47c 2558 if (MINI_WINDOW_P (w)
ca26e1c8 2559 && start == BEG
a2889657
JB
2560 && vpos == XFASTINT (w->top))
2561 {
8c5b6a0a 2562 if (! NILP (minibuf_prompt))
f7b4b63a
KH
2563 {
2564 minibuf_prompt_width
8c5b6a0a
KH
2565 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2566 XSTRING (minibuf_prompt)->size, hpos,
ce006f69
RS
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)
f7b4b63a
KH
2574 - hpos);
2575 hpos += minibuf_prompt_width;
2b050fec 2576 taboffset -= minibuf_prompt_width;
f7b4b63a
KH
2577 }
2578 else
2579 minibuf_prompt_width = 0;
a2889657
JB
2580 }
2581
f4faa47c
JB
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
ca26e1c8
KH
2588 = compute_motion (pos, vpos, hpos, 0,
2589 ZV, vpos, 0,
f4faa47c
JB
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;
a2889657 2614 p1 = desired_glyphs->glyphs[vpos] + hpos;
efc63ef0
RS
2615 p1start = p1;
2616 charstart = desired_glyphs->charstarts[vpos] + hpos;
2617 /* In case we don't ever write anything into it... */
a007eef6 2618 desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
d2f84654
RS
2619 leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
2620 endp = leftmargin + width;
a2889657 2621
1c2250c2
JB
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
a2889657
JB
2629 /* Loop generating characters.
2630 Stop at end of buffer, before newline,
31b24551
JB
2631 if reach or pass continuation column,
2632 or at face change. */
a2889657 2633 pause = pos;
31b24551 2634 next_face_change = pos;
ca26e1c8
KH
2635 next_boundary = pos;
2636 p1prev = p1;
2637 prevpos = pos;
85bcef6c 2638 while (1)
a2889657 2639 {
31b24551 2640 if (pos >= pause)
a2889657 2641 {
67481ae5
RS
2642 int e_t_h;
2643
ca26e1c8 2644 while (pos == next_boundary)
a2889657 2645 {
ca26e1c8
KH
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;
a2889657 2673
c2213350 2674 XSETFASTINT (position, pos);
ca26e1c8
KH
2675 limit = Fnext_overlay_change (position);
2676#ifdef USE_TEXT_PROPERTIES
dfabd9a0
RS
2677 /* This is just an estimate to give reasonable
2678 performance; nothing should go wrong if it is too small. */
fe3d6921 2679 if (XFASTINT (limit) > pos + 50)
c2213350 2680 XSETFASTINT (limit, pos + 50);
ca26e1c8
KH
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);
642eefc6 2689 if (TEXT_PROP_MEANS_INVISIBLE (prop))
dfabd9a0 2690 {
ca26e1c8 2691 if (pos < PT && next_boundary >= PT)
dfabd9a0
RS
2692 {
2693 cursor_vpos = vpos;
d2f84654 2694 cursor_hpos = p1 - leftmargin;
dfabd9a0 2695 }
ca26e1c8 2696 pos = next_boundary;
642eefc6
RS
2697 last_invis_skip = pos;
2698 last_invis_prop = prop;
dfabd9a0 2699 }
b0a0fbda 2700 }
ca26e1c8
KH
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)
eff87c2c
RS
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 }
b0a0fbda 2724
67481ae5
RS
2725 /* Figure out where (if at all) the
2726 redisplay_end_trigger-hook should run. */
f6fd109b
RS
2727 if (MARKERP (w->redisplay_end_trigger)
2728 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
d3413a53
RS
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);
67481ae5
RS
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 {
e0bfbde6
RS
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);
e0bfbde6 2744
9c49d3d7
KH
2745 /* Since we are *trying* to run these functions,
2746 don't try to run them again, even if they get an error. */
d3413a53 2747 w->redisplay_end_trigger = Qnil;
9c49d3d7
KH
2748 Frun_hook_with_args (3, args);
2749
67481ae5 2750 e_t_h = ZV;
f6fd109b
RS
2751 /* Notice if it changed the face of this character. */
2752 next_face_change = pos;
67481ae5
RS
2753 }
2754
f6fd109b
RS
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
67481ae5
RS
2765 /* Compute the next place we need to stop
2766 and do something special; set PAUSE. */
2767
ca26e1c8 2768 pause = ZV;
1c2250c2 2769
ca26e1c8
KH
2770 if (pos < next_boundary && next_boundary < pause)
2771 pause = next_boundary;
1c2250c2
JB
2772 if (pos < next_face_change && next_face_change < pause)
2773 pause = next_face_change;
2774
67481ae5
RS
2775 if (e_t_h < pause)
2776 pause = e_t_h;
2777
31b24551
JB
2778 /* Wouldn't you hate to read the next line to someone over
2779 the phone? */
ae3b1442
KH
2780 if (pos < PT && PT < pause)
2781 pause = PT;
a2889657
JB
2782 if (pos < GPT && GPT < pause)
2783 pause = GPT;
2784
2785 p = &FETCH_CHAR (pos);
2786 }
ca26e1c8 2787
ca26e1c8
KH
2788 if (p1 >= endp)
2789 break;
2790
2791 p1prev = p1;
2792
a2889657 2793 c = *p++;
376b0e59
RS
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)
a2889657 2803 {
d2f84654 2804 if (p1 >= leftmargin)
4cdc65eb 2805 *p1 = MAKE_GLYPH (f, c, current_face);
a2889657
JB
2806 p1++;
2807 }
2808 else if (c == '\n')
2809 {
2810 invis = 0;
642eefc6
RS
2811 if (last_invis_skip == pos
2812 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
2813 invis = 1;
ca26e1c8 2814 while (pos + 1 < ZV
a2889657 2815 && selective > 0
9f412332 2816 && indented_beyond_p (pos + 1, selective))
a2889657
JB
2817 {
2818 invis = 1;
2819 pos = find_next_newline (pos + 1, 1);
2820 if (FETCH_CHAR (pos - 1) == '\n')
2821 pos--;
2822 }
d2f84654 2823 if (invis && selective_rlen > 0 && p1 >= leftmargin)
a2889657
JB
2824 {
2825 p1 += selective_rlen;
d2f84654 2826 if (p1 - leftmargin > width)
a2889657 2827 p1 = endp;
278feba9 2828 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c2250c2 2829 (p1 - p1prev), current_face);
a2889657 2830 }
87485d6f 2831#ifdef HAVE_FACES
3c5c35c5
JB
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)
1105ff20
KH
2835 {
2836 if (p1 < leftmargin)
2837 p1 = leftmargin;
2838 while (p1 < endp)
2839 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2840 }
3c5c35c5 2841#endif
545e04f6
KH
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
68a37fa8 2861 break;
a2889657
JB
2862 }
2863 else if (c == '\t')
2864 {
2865 do
2866 {
d2f84654 2867 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2868 *p1 = MAKE_GLYPH (f, ' ', current_face);
a2889657
JB
2869 p1++;
2870 }
d2f84654 2871 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
a2889657
JB
2872 % tab_width);
2873 }
6e8290aa 2874 else if (c == Ctl ('M') && selective == -1)
a2889657
JB
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;
d2f84654 2882 if (p1 - leftmargin > width)
a2889657 2883 p1 = endp;
278feba9 2884 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c2250c2 2885 (p1 - p1prev), current_face);
a2889657 2886 }
87485d6f 2887#ifdef HAVE_FACES
3c5c35c5
JB
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)
1105ff20
KH
2891 {
2892 if (p1 < leftmargin)
2893 p1 = leftmargin;
2894 while (p1 < endp)
2895 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2896 }
3c5c35c5 2897#endif
545e04f6
KH
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 }
68a37fa8 2916 break;
a2889657 2917 }
a2889657
JB
2918 else if (c < 0200 && ctl_arrow)
2919 {
d2f84654 2920 if (p1 >= leftmargin)
e24c997d 2921 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
278feba9
RS
2922 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
2923 current_face);
a2889657 2924 p1++;
d2f84654 2925 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2926 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
a2889657
JB
2927 p1++;
2928 }
2929 else
2930 {
d2f84654 2931 if (p1 >= leftmargin)
e24c997d 2932 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
278feba9
RS
2933 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
2934 current_face);
a2889657 2935 p1++;
d2f84654 2936 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2937 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
a2889657 2938 p1++;
d2f84654 2939 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2940 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
a2889657 2941 p1++;
d2f84654 2942 if (p1 >= leftmargin && p1 < endp)
4cdc65eb 2943 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
a2889657
JB
2944 p1++;
2945 }
31b24551 2946
ca26e1c8 2947 prevpos = pos;
a2889657 2948 pos++;
545e04f6
KH
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 }
a2889657
JB
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
efc63ef0
RS
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. */
85bcef6c
RS
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. */
a007eef6
RS
2987 i = p1 - p1start + 1;
2988 if (p1 < leftmargin)
2989 i += leftmargin - p1;
2990 for (; i < endp - p1start + 1; i++)
efc63ef0
RS
2991 charstart[i] = 0;
2992
a2889657
JB
2993 /* Handle continuation in middle of a character */
2994 /* by backing up over it */
2995 if (p1 > endp)
2996 {
5fcbb24d
JB
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
a2889657
JB
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')
dd5f6267
KH
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 }
a2889657
JB
3028 else
3029 /* Stopped due to right margin of window */
3030 {
3031 if (truncate)
3032 {
278feba9 3033 *p1++ = fix_glyph (f, truncator, 0);
a2889657
JB
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 */
dd5f6267
KH
3037 do
3038 pos = find_next_newline (pos, 1);
3039 while (pos < ZV && selective > 0
3040 && indented_beyond_p (pos, selective));
a2889657
JB
3041 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
3042
3043 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
3044 }
3045 else
3046 {
278feba9 3047 *p1++ = fix_glyph (f, continuer, 0);
a2889657
JB
3048 val.vpos = 0;
3049 lastpos--;
3050 }
3051 }
3052 }
3053
3054 /* If point is at eol or in invisible text at eol,
44fa5b1e 3055 record its frame location now. */
a2889657 3056
ae3b1442 3057 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
a2889657
JB
3058 {
3059 cursor_vpos = vpos;
d2f84654 3060 cursor_hpos = p1 - leftmargin;
a2889657
JB
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);
44fa5b1e 3068 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
a2889657 3069 {
b5bbc9a5
KH
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 }
a2889657
JB
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 {
d2f84654
RS
3100 *leftmargin = fix_glyph (f, truncator, 0);
3101 if (p1 <= leftmargin)
3102 p1 = leftmargin + 1;
a2889657
JB
3103 }
3104
44fa5b1e 3105 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f))
a2889657
JB
3106 {
3107 endp++;
d2f84654 3108 if (p1 < leftmargin) p1 = leftmargin;
a2889657 3109 while (p1 < endp) *p1++ = SPACEGLYPH;
b1d1124b 3110
88f22aff
JB
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
b1d1124b 3114 reconfigured. */
75d13c64
KH
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 : '|');
a2889657
JB
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
e24c997d 3133 if (MARKERP (Voverlay_arrow_position)
a2889657
JB
3134 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
3135 && start == marker_position (Voverlay_arrow_position)
e24c997d 3136 && STRINGP (Voverlay_arrow_string)
a2889657
JB
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;
142be3dd 3142 int arrow_end;
a2889657 3143
b1d1124b
JB
3144 if (len > width)
3145 len = width;
87485d6f 3146#ifdef HAVE_FACES
c4628384
RS
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
c2213350 3156 XSETFASTINT (ilisp, i);
c4628384
RS
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
87485d6f 3163#endif /* HAVE_FACES */
c4628384
RS
3164 {
3165 for (i = 0; i < len; i++)
3166 leftmargin[i] = p[i];
3167 }
142be3dd
JB
3168
3169 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
d2f84654 3170 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
142be3dd
JB
3171 if (desired_glyphs->used[vpos] < arrow_end)
3172 desired_glyphs->used[vpos] = arrow_end;
a2889657
JB
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
7ce2c095
RS
3182/* Redisplay the menu bar in the frame for window W. */
3183
3184static void
3185display_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;
8351baf2 3193 int i;
7ce2c095 3194
dc937613
RS
3195#ifdef HAVE_NTGUI
3196 return;
3197#endif
3198
3199#ifdef USE_X_TOOLKIT
d3413a53 3200 if (FRAME_X_P (f))
7ce2c095 3201 return;
dc937613 3202#endif /* USE_X_TOOLKIT */
7ce2c095
RS
3203
3204 get_display_line (f, vpos, 0);
3205
8351baf2
RS
3206 items = FRAME_MENU_BAR_ITEMS (f);
3207 for (i = 0; i < XVECTOR (items)->size; i += 3)
7ce2c095 3208 {
8351baf2
RS
3209 Lisp_Object pos, string;
3210 string = XVECTOR (items)->contents[i + 1];
3211 if (NILP (string))
3212 break;
2d66ad19 3213
c2213350 3214 XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos);
7ce2c095
RS
3215
3216 if (hpos < maxendcol)
3217 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
3218 XSTRING (string)->data,
90adcf20 3219 XSTRING (string)->size,
278feba9 3220 hpos, 0, 0, hpos, maxendcol);
6b1bbc46 3221 /* Put a space between items. */
2d66ad19
RS
3222 if (hpos < maxendcol)
3223 {
6b1bbc46 3224 int hpos1 = hpos + 1;
278feba9 3225 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
2d66ad19
RS
3226 min (hpos1, maxendcol), maxendcol);
3227 }
7ce2c095
RS
3228 }
3229
3230 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
3231 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2d66ad19
RS
3232
3233 /* Fill out the line with spaces. */
3234 if (maxendcol > hpos)
278feba9 3235 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
db6f348c
JB
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);
7ce2c095
RS
3241}
3242\f
a2889657
JB
3243/* Display the mode line for window w */
3244
3245static void
3246display_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;
44fa5b1e 3252 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
a2889657 3253
aa6d10fa 3254 line_number_displayed = 0;
155ef550 3255 w->column_number_displayed = Qnil;
aa6d10fa 3256
44fa5b1e 3257 get_display_line (f, vpos, left);
03b294dc
RS
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
44fa5b1e 3269 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
a2889657
JB
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). */
44fa5b1e
JB
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;
87485d6f 3280#ifdef HAVE_FACES
03b294dc 3281 else if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
d7eb09a0
RS
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)
4cdc65eb 3287 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
d7eb09a0 3288 }
4cdc65eb 3289#endif
a2889657
JB
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
44fa5b1e 3297 HPOS is the position (absolute on frame) where this element's text
a2889657
JB
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
3316static int
3317display_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
0220c518 3331 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
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;
d39b6696
KH
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));
a2889657
JB
3352 }
3353 else /* c == '%' */
3354 {
766525bc 3355 register int minendcol;
a2889657
JB
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
766525bc
RS
3368 minendcol = hpos + spec_width;
3369 if (minendcol > maxendcol)
3370 {
3371 spec_width = maxendcol - hpos;
3372 minendcol = maxendcol;
3373 }
a2889657
JB
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)
d39b6696 3380 {
766525bc
RS
3381 char *spec = decode_mode_spec (w, c, spec_width,
3382 maxendcol - hpos);
d39b6696 3383 if (frame_title_ptr)
766525bc 3384 hpos = store_frame_title (spec, minendcol, maxendcol);
d39b6696
KH
3385 else
3386 hpos = display_string (w, vpos, spec, -1,
3387 hpos, 0, 1,
766525bc 3388 minendcol, maxendcol);
d39b6696 3389 }
a2889657
JB
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);
265a9e55 3403 if (!NILP (tem))
a2889657
JB
3404 {
3405 tem = Fsymbol_value (elt);
3406 /* If value is a string, output that string literally:
3407 don't check for % within it. */
e24c997d 3408 if (STRINGP (tem))
d39b6696
KH
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 }
a2889657
JB
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;
e24c997d 3438 if (SYMBOLP (car))
a2889657
JB
3439 {
3440 tem = Fboundp (car);
3441 elt = XCONS (elt)->cdr;
e24c997d 3442 if (!CONSP (elt))
a2889657
JB
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. */
265a9e55 3446 if (!NILP (tem))
a2889657
JB
3447 {
3448 tem = Fsymbol_value (car);
265a9e55 3449 if (!NILP (tem))
a2889657
JB
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;
265a9e55 3456 if (NILP (elt))
a2889657 3457 break;
e24c997d 3458 else if (!CONSP (elt))
a2889657
JB
3459 goto invalid;
3460 elt = XCONS (elt)->car;
3461 goto tail_recurse;
3462 }
e24c997d 3463 else if (INTEGERP (car))
a2889657
JB
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 }
e24c997d 3488 else if (STRINGP (car) || CONSP (car))
a2889657
JB
3489 {
3490 register int limit = 50;
3491 /* LIMIT is to protect against circular lists. */
e24c997d 3492 while (CONSP (elt) && --limit > 0
a2889657
JB
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:
d39b6696
KH
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;
a2889657
JB
3512 }
3513
a2889657 3514 if (minendcol > hpos)
d39b6696
KH
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);
a2889657
JB
3519 return hpos;
3520}
3521\f
766525bc
RS
3522/* Write a null-terminated, right justified decimal representation of
3523 the positive integer D to BUF using a minimal field width WIDTH. */
3524
3525static void
3526pint2str (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
a2889657 3551/* Return a string for the output of a mode line %-spec for window W,
766525bc
RS
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. */
a2889657 3555
11e82b76
JB
3556static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
3557
a2889657 3558static char *
766525bc 3559decode_mode_spec (w, c, spec_width, maxwidth)
a2889657
JB
3560 struct window *w;
3561 register char c;
766525bc 3562 register int spec_width;
a2889657
JB
3563 register int maxwidth;
3564{
0b67772d 3565 Lisp_Object obj;
44fa5b1e
JB
3566 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3567 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
d39b6696 3568 struct buffer *b = XBUFFER (w->buffer);
a2889657 3569
0b67772d 3570 obj = Qnil;
44fa5b1e
JB
3571 if (maxwidth > FRAME_WIDTH (f))
3572 maxwidth = FRAME_WIDTH (f);
a2889657
JB
3573
3574 switch (c)
3575 {
1af9f229
RS
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
a2889657 3644 case 'b':
d39b6696 3645 obj = b->name;
a2889657
JB
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
1af9f229
RS
3657 case 'c':
3658 {
3659 int col = current_column ();
3660 XSETFASTINT (w->column_number_displayed, col);
766525bc 3661 pint2str (decode_mode_spec_buf, spec_width, col);
1af9f229
RS
3662 return decode_mode_spec_buf;
3663 }
3664
3665 case 'F':
3666 /* %F displays the frame name. */
9cb61f8d 3667#ifdef MULTI_FRAME
22dabbb2
RS
3668 if (!NILP (selected_frame->title))
3669 return (char *) XSTRING (selected_frame->title)->data;
1af9f229 3670 return (char *) XSTRING (selected_frame->name)->data;
9cb61f8d
RS
3671#else
3672 return "Emacs";
3673#endif
1af9f229 3674
a2889657 3675 case 'f':
d39b6696 3676 obj = b->filename;
a2889657 3677#if 0
265a9e55 3678 if (NILP (obj))
a2889657 3679 return "[none]";
e24c997d 3680 else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
a2889657
JB
3681 {
3682 bcopy ("...", decode_mode_spec_buf, 3);
3683 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
3684 decode_mode_spec_buf + 3, maxwidth - 3);
3685 return decode_mode_spec_buf;
3686 }
3687#endif
3688 break;
3689
aa6d10fa
RS
3690 case 'l':
3691 {
3692 int startpos = marker_position (w->start);
3693 int line, linepos, topline;
3694 int nlines, junk;
3695 Lisp_Object tem;
3696 int height = XFASTINT (w->height);
3697
3698 /* If we decided that this buffer isn't suitable for line numbers,
3699 don't forget that too fast. */
3700 if (EQ (w->base_line_pos, w->buffer))
766525bc 3701 goto no_value;
aa6d10fa
RS
3702
3703 /* If the buffer is very big, don't waste time. */
d39b6696 3704 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
aa6d10fa
RS
3705 {
3706 w->base_line_pos = Qnil;
3707 w->base_line_number = Qnil;
766525bc 3708 goto no_value;
aa6d10fa
RS
3709 }
3710
3711 if (!NILP (w->base_line_number)
3712 && !NILP (w->base_line_pos)
3713 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
3714 {
3715 line = XFASTINT (w->base_line_number);
3716 linepos = XFASTINT (w->base_line_pos);
3717 }
3718 else
3719 {
3720 line = 1;
d39b6696 3721 linepos = BUF_BEGV (b);
aa6d10fa
RS
3722 }
3723
3724 /* Count lines from base line to window start position. */
3725 nlines = display_count_lines (linepos, startpos, startpos, &junk);
3726
3727 topline = nlines + line;
3728
3729 /* Determine a new base line, if the old one is too close
3730 or too far away, or if we did not have one.
3731 "Too close" means it's plausible a scroll-down would
3732 go back past it. */
d39b6696 3733 if (startpos == BUF_BEGV (b))
aa6d10fa 3734 {
c2213350
KH
3735 XSETFASTINT (w->base_line_number, topline);
3736 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
3737 }
3738 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 3739 || linepos == BUF_BEGV (b))
aa6d10fa 3740 {
d39b6696 3741 int limit = BUF_BEGV (b);
aa6d10fa
RS
3742 int position;
3743 int distance = (height * 2 + 30) * 200;
3744
3745 if (startpos - distance > limit)
3746 limit = startpos - distance;
3747
3748 nlines = display_count_lines (startpos, limit,
3749 -(height * 2 + 30),
3750 &position);
3751 /* If we couldn't find the lines we wanted within
3752 200 chars per line,
3753 give up on line numbers for this window. */
3754 if (position == startpos - distance)
3755 {
3756 w->base_line_pos = w->buffer;
3757 w->base_line_number = Qnil;
766525bc 3758 goto no_value;
aa6d10fa
RS
3759 }
3760
c2213350
KH
3761 XSETFASTINT (w->base_line_number, topline - nlines);
3762 XSETFASTINT (w->base_line_pos, position);
aa6d10fa
RS
3763 }
3764
3765 /* Now count lines from the start pos to point. */
3766 nlines = display_count_lines (startpos, PT, PT, &junk);
3767
3768 /* Record that we did display the line number. */
3769 line_number_displayed = 1;
3770
3771 /* Make the string to show. */
766525bc 3772 pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
aa6d10fa 3773 return decode_mode_spec_buf;
766525bc
RS
3774 no_value:
3775 {
3776 char* p = decode_mode_spec_buf;
3777 for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
3778 strcpy (p, "??");
3779 return decode_mode_spec_buf;
3780 }
aa6d10fa
RS
3781 }
3782 break;
3783
a2889657 3784 case 'm':
d39b6696 3785 obj = b->mode_name;
a2889657
JB
3786 break;
3787
3788 case 'n':
d39b6696 3789 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
3790 return " Narrow";
3791 break;
3792
a2889657
JB
3793 case 'p':
3794 {
3795 int pos = marker_position (w->start);
d39b6696 3796 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 3797
d39b6696 3798 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 3799 {
d39b6696 3800 if (pos <= BUF_BEGV (b))
a2889657
JB
3801 return "All";
3802 else
3803 return "Bottom";
3804 }
d39b6696 3805 else if (pos <= BUF_BEGV (b))
a2889657
JB
3806 return "Top";
3807 else
3808 {
3c7d31b9
RS
3809 if (total > 1000000)
3810 /* Do it differently for a large value, to avoid overflow. */
3811 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
3812 else
3813 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
3814 /* We can't normally display a 3-digit number,
3815 so get us a 2-digit number that is close. */
3816 if (total == 100)
3817 total = 99;
3818 sprintf (decode_mode_spec_buf, "%2d%%", total);
3819 return decode_mode_spec_buf;
3820 }
3821 }
3822
8ffcb79f
RS
3823 /* Display percentage of size above the bottom of the screen. */
3824 case 'P':
3825 {
3826 int toppos = marker_position (w->start);
d39b6696
KH
3827 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
3828 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 3829
d39b6696 3830 if (botpos >= BUF_ZV (b))
8ffcb79f 3831 {
d39b6696 3832 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
3833 return "All";
3834 else
3835 return "Bottom";
3836 }
3837 else
3838 {
3c7d31b9
RS
3839 if (total > 1000000)
3840 /* Do it differently for a large value, to avoid overflow. */
3841 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
3842 else
3843 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
3844 /* We can't normally display a 3-digit number,
3845 so get us a 2-digit number that is close. */
3846 if (total == 100)
3847 total = 99;
d39b6696 3848 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
3849 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
3850 else
3851 sprintf (decode_mode_spec_buf, "%2d%%", total);
3852 return decode_mode_spec_buf;
3853 }
3854 }
3855
1af9f229
RS
3856 case 's':
3857 /* status of process */
3858 obj = Fget_buffer_process (w->buffer);
3859 if (NILP (obj))
3860 return "no process";
3861#ifdef subprocesses
3862 obj = Fsymbol_name (Fprocess_status (obj));
3863#endif
3864 break;
d39b6696 3865
1af9f229
RS
3866 case 't': /* indicate TEXT or BINARY */
3867#ifdef MODE_LINE_BINARY_TEXT
3868 return MODE_LINE_BINARY_TEXT (b);
3869#else
3870 return "T";
3871#endif
a2889657 3872 }
d39b6696 3873
e24c997d 3874 if (STRINGP (obj))
a2889657
JB
3875 return (char *) XSTRING (obj)->data;
3876 else
3877 return "";
3878}
59b49f63
RS
3879\f
3880/* Search for COUNT instances of a line boundary, which means either a
3881 newline or (if selective display enabled) a carriage return.
3882 Start at START. If COUNT is negative, search backwards.
3883
3884 If we find COUNT instances, set *SHORTAGE to zero, and return the
3885 position after the COUNTth match. Note that for reverse motion
3886 this is not the same as the usual convention for Emacs motion commands.
3887
3888 If we don't find COUNT instances before reaching the end of the
3889 buffer (or the beginning, if scanning backwards), set *SHORTAGE to
3890 the number of line boundaries left unfound, and return the end of the
3891 buffer we bumped up against. */
3892
3893static int
3894display_scan_buffer (start, count, shortage)
3895 int *shortage, start;
3896 register int count;
3897{
3898 int limit = ((count > 0) ? ZV - 1 : BEGV);
3899 int direction = ((count > 0) ? 1 : -1);
3900
3901 register unsigned char *cursor;
3902 unsigned char *base;
3903
3904 register int ceiling;
3905 register unsigned char *ceiling_addr;
3906
3907 /* If we are not in selective display mode,
3908 check only for newlines. */
3909 if (! (!NILP (current_buffer->selective_display)
3910 && !INTEGERP (current_buffer->selective_display)))
ae474ea9 3911 return scan_buffer ('\n', start, 0, count, shortage, 0);
59b49f63
RS
3912
3913 /* The code that follows is like scan_buffer
3914 but checks for either newline or carriage return. */
3915
3916 if (shortage != 0)
3917 *shortage = 0;
3918
3919 if (count > 0)
3920 while (start != limit + 1)
3921 {
3922 ceiling = BUFFER_CEILING_OF (start);
3923 ceiling = min (limit, ceiling);
3924 ceiling_addr = &FETCH_CHAR (ceiling) + 1;
3925 base = (cursor = &FETCH_CHAR (start));
3926 while (1)
3927 {
3928 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
3929 ;
3930 if (cursor != ceiling_addr)
3931 {
3932 if (--count == 0)
3933 {
3934 immediate_quit = 0;
3935 return (start + cursor - base + 1);
3936 }
3937 else
3938 if (++cursor == ceiling_addr)
3939 break;
3940 }
3941 else
3942 break;
3943 }
3944 start += cursor - base;
3945 }
3946 else
3947 {
3948 start--; /* first character we scan */
3949 while (start > limit - 1)
3950 { /* we WILL scan under start */
3951 ceiling = BUFFER_FLOOR_OF (start);
3952 ceiling = max (limit, ceiling);
3953 ceiling_addr = &FETCH_CHAR (ceiling) - 1;
3954 base = (cursor = &FETCH_CHAR (start));
3955 cursor++;
3956 while (1)
3957 {
3958 while (--cursor != ceiling_addr
3959 && *cursor != '\n' && *cursor != 015)
3960 ;
3961 if (cursor != ceiling_addr)
3962 {
3963 if (++count == 0)
3964 {
3965 immediate_quit = 0;
3966 return (start + cursor - base + 1);
3967 }
3968 }
3969 else
3970 break;
3971 }
3972 start += cursor - base;
3973 }
3974 }
3975
3976 if (shortage != 0)
3977 *shortage = count * direction;
3978 return (start + ((direction == 1 ? 0 : 1)));
3979}
aa6d10fa
RS
3980
3981/* Count up to N lines starting from FROM.
3982 But don't go beyond LIMIT.
3983 Return the number of lines thus found (always positive).
3984 Store the position after what was found into *POS_PTR. */
3985
3986static int
3987display_count_lines (from, limit, n, pos_ptr)
3988 int from, limit, n;
3989 int *pos_ptr;
3990{
3991 int oldbegv = BEGV;
3992 int oldzv = ZV;
3993 int shortage = 0;
3994
3995 if (limit < from)
3996 BEGV = limit;
3997 else
3998 ZV = limit;
3999
59b49f63 4000 *pos_ptr = display_scan_buffer (from, n, &shortage);
aa6d10fa
RS
4001
4002 ZV = oldzv;
4003 BEGV = oldbegv;
4004
4005 if (n < 0)
4006 /* When scanning backwards, scan_buffer stops *after* the last newline
4007 it finds, but does count it. Compensate for that. */
4008 return - n - shortage - (*pos_ptr != limit);
4009 return n - shortage;
4010}
a2889657
JB
4011\f
4012/* Display STRING on one line of window W, starting at HPOS.
4013 Display at position VPOS. Caller should have done get_display_line.
11e82b76 4014 If VPOS == -1, display it as the current frame's title.
90adcf20 4015 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
a2889657
JB
4016
4017 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
4018
4019 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
4020 MAXCOL is the last column ok to end at. Truncate here.
4021 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
44fa5b1e 4022 Both count from the left edge of the frame, as does HPOS.
a2889657
JB
4023 The right edge of W is an implicit maximum.
4024 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
4025
278feba9
RS
4026 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
4027 at the place where the current window ends in this line
4028 and not display anything beyond there. Otherwise, only MAXCOL
4029 controls where to stop output.
4030
4031 Returns ending hpos. */
a2889657
JB
4032
4033static int
278feba9
RS
4034display_string (w, vpos, string, length, hpos, truncate,
4035 obey_window_width, mincol, maxcol)
a2889657
JB
4036 struct window *w;
4037 unsigned char *string;
90adcf20 4038 int length;
a2889657
JB
4039 int vpos, hpos;
4040 GLYPH truncate;
278feba9 4041 int obey_window_width;
a2889657
JB
4042 int mincol, maxcol;
4043{
4044 register int c;
d3413a53 4045 int truncated;
a2889657
JB
4046 register GLYPH *p1;
4047 int hscroll = XINT (w->hscroll);
253c7d2f 4048 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
a2889657
JB
4049 register GLYPH *start;
4050 register GLYPH *end;
b1d1124b
JB
4051 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
4052 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
a2889657
JB
4053 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
4054 int window_width = XFASTINT (w->width);
4055
4056 /* Use the standard display table, not the window's display table.
4057 We don't want the mode line in rot13. */
f908610f 4058 register struct Lisp_Char_Table *dp = 0;
efc63ef0 4059 int i;
a2889657 4060
f908610f
RS
4061 if (DISP_TABLE_P (Vstandard_display_table))
4062 dp = XCHAR_TABLE (Vstandard_display_table);
a2889657 4063
54ff581a 4064 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657
JB
4065
4066 p1 = p1start;
4067 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
a2889657 4068
278feba9 4069 if (obey_window_width)
b1d1124b 4070 {
278feba9
RS
4071 end = start + window_width - (truncate != 0);
4072
4073 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f))
b1d1124b 4074 {
278feba9
RS
4075 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4076 {
4077 int i;
b1d1124b 4078
5802e919 4079 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
278feba9
RS
4080 *end-- = ' ';
4081 }
4082 else
4083 *end-- = '|';
b1d1124b 4084 }
b1d1124b 4085 }
a2889657 4086
278feba9
RS
4087 if (! obey_window_width
4088 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
a2889657 4089 end = desired_glyphs->glyphs[vpos] + maxcol;
278feba9 4090
efc63ef0 4091 /* Store 0 in charstart for these columns. */
bd5dec8e 4092 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
efc63ef0
RS
4093 desired_glyphs->charstarts[vpos][i] = 0;
4094
a2889657
JB
4095 if (maxcol >= 0 && mincol > maxcol)
4096 mincol = maxcol;
4097
d3413a53
RS
4098 /* We set truncated to 1 if we get stopped by trying to pass END
4099 (that is, trying to pass MAXCOL.) */
4100 truncated = 0;
4101 while (1)
a2889657 4102 {
90adcf20
RS
4103 if (length == 0)
4104 break;
a2889657 4105 c = *string++;
90adcf20
RS
4106 /* Specified length. */
4107 if (length >= 0)
4108 length--;
4109 /* Unspecified length (null-terminated string). */
4110 else if (c == 0)
4111 break;
4112
d3413a53
RS
4113 if (p1 >= end)
4114 {
4115 truncated = 1;
4116 break;
4117 }
4118
376b0e59
RS
4119 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
4120 {
4121 p1 = copy_part_of_rope (f, p1, start,
4122 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
4123 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
4124 0);
4125 }
4126 else if (c >= 040 && c < 0177)
a2889657
JB
4127 {
4128 if (p1 >= start)
4129 *p1 = c;
4130 p1++;
4131 }
4132 else if (c == '\t')
4133 {
4134 do
4135 {
4136 if (p1 >= start && p1 < end)
4137 *p1 = SPACEGLYPH;
4138 p1++;
4139 }
4140 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
4141 }
ded34426 4142 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
a2889657
JB
4143 {
4144 if (p1 >= start)
e24c997d 4145 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
278feba9
RS
4146 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
4147 0);
a2889657 4148 p1++;
6e8290aa 4149 if (p1 >= start && p1 < end)
a2889657
JB
4150 *p1 = c ^ 0100;
4151 p1++;
4152 }
4153 else
4154 {
4155 if (p1 >= start)
e24c997d 4156 *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
278feba9
RS
4157 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
4158 0);
a2889657 4159 p1++;
6e8290aa 4160 if (p1 >= start && p1 < end)
a2889657
JB
4161 *p1 = (c >> 6) + '0';
4162 p1++;
6e8290aa 4163 if (p1 >= start && p1 < end)
a2889657
JB
4164 *p1 = (7 & (c >> 3)) + '0';
4165 p1++;
6e8290aa 4166 if (p1 >= start && p1 < end)
a2889657
JB
4167 *p1 = (7 & c) + '0';
4168 p1++;
4169 }
4170 }
4171
d3413a53 4172 if (truncated)
a2889657
JB
4173 {
4174 p1 = end;
278feba9 4175 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
a2889657
JB
4176 }
4177 else if (mincol >= 0)
4178 {
4179 end = desired_glyphs->glyphs[vpos] + mincol;
4180 while (p1 < end)
4181 *p1++ = SPACEGLYPH;
4182 }
4183
4184 {
4185 register int len = p1 - desired_glyphs->glyphs[vpos];
4186
4187 if (len > desired_glyphs->used[vpos])
4188 desired_glyphs->used[vpos] = len;
4189 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
4190
4191 return len;
4192 }
4193}
4194\f
642eefc6
RS
4195/* This is like a combination of memq and assq.
4196 Return 1 if PROPVAL appears as an element of LIST
4197 or as the car of an element of LIST.
af460d46
RS
4198 If PROPVAL is a list, compare each element against LIST
4199 in that way, and return 1 if any element of PROPVAL is found in LIST.
642eefc6
RS
4200 Otherwise return 0.
4201 This function cannot quit. */
4202
4203int
4204invisible_p (propval, list)
4205 register Lisp_Object propval;
4206 Lisp_Object list;
4207{
af460d46
RS
4208 register Lisp_Object tail, proptail;
4209 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
642eefc6
RS
4210 {
4211 register Lisp_Object tem;
af460d46 4212 tem = XCONS (tail)->car;
642eefc6
RS
4213 if (EQ (propval, tem))
4214 return 1;
4215 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4216 return 1;
4217 }
af460d46
RS
4218 if (CONSP (propval))
4219 for (proptail = propval; CONSP (proptail);
4220 proptail = XCONS (proptail)->cdr)
4221 {
4222 Lisp_Object propelt;
4223 propelt = XCONS (proptail)->car;
4224 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4225 {
4226 register Lisp_Object tem;
4227 tem = XCONS (tail)->car;
4228 if (EQ (propelt, tem))
4229 return 1;
4230 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4231 return 1;
4232 }
4233 }
642eefc6
RS
4234 return 0;
4235}
4236
4237/* Return 1 if PROPVAL appears as the car of an element of LIST
4238 and the cdr of that element is non-nil.
af460d46
RS
4239 If PROPVAL is a list, check each element of PROPVAL in that way,
4240 and the first time some element is found,
4241 return 1 if the cdr of that element is non-nil.
642eefc6
RS
4242 Otherwise return 0.
4243 This function cannot quit. */
4244
4245int
4246invisible_ellipsis_p (propval, list)
4247 register Lisp_Object propval;
4248 Lisp_Object list;
4249{
af460d46
RS
4250 register Lisp_Object tail, proptail;
4251 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
642eefc6
RS
4252 {
4253 register Lisp_Object tem;
af460d46 4254 tem = XCONS (tail)->car;
642eefc6
RS
4255 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
4256 return ! NILP (XCONS (tem)->cdr);
4257 }
af460d46
RS
4258 if (CONSP (propval))
4259 for (proptail = propval; CONSP (proptail);
4260 proptail = XCONS (proptail)->cdr)
4261 {
4262 Lisp_Object propelt;
4263 propelt = XCONS (proptail)->car;
4264 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
4265 {
4266 register Lisp_Object tem;
4267 tem = XCONS (tail)->car;
4268 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
4269 return ! NILP (XCONS (tem)->cdr);
4270 }
4271 }
642eefc6
RS
4272 return 0;
4273}
4274\f
a2889657
JB
4275void
4276syms_of_xdisp ()
4277{
cf074754
RS
4278 staticpro (&Qmenu_bar_update_hook);
4279 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
4280
d46fb96a 4281 staticpro (&Qoverriding_terminal_local_map);
7079aefa 4282 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 4283
399164b4
KH
4284 staticpro (&Qoverriding_local_map);
4285 Qoverriding_local_map = intern ("overriding-local-map");
4286
75c43375
RS
4287 staticpro (&Qwindow_scroll_functions);
4288 Qwindow_scroll_functions = intern ("window-scroll-functions");
4289
e0bfbde6
RS
4290 staticpro (&Qredisplay_end_trigger_functions);
4291 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
67481ae5 4292
a2889657
JB
4293 staticpro (&last_arrow_position);
4294 staticpro (&last_arrow_string);
4295 last_arrow_position = Qnil;
4296 last_arrow_string = Qnil;
4297
4298 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 4299 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
4300 Vglobal_mode_string = Qnil;
4301
4302 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
4303 "Marker for where to display an arrow on top of the buffer text.\n\
4304This must be the beginning of a line in order to work.\n\
4305See also `overlay-arrow-string'.");
4306 Voverlay_arrow_position = Qnil;
4307
4308 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
4309 "String to display as an arrow. See also `overlay-arrow-position'.");
4310 Voverlay_arrow_string = Qnil;
4311
4312 DEFVAR_INT ("scroll-step", &scroll_step,
4313 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
4314If that fails to bring point back on frame, point is centered instead.\n\
4315If this is zero, point is always centered after it moves off frame.");
a2889657
JB
4316
4317 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
4318
4319 DEFVAR_BOOL ("truncate-partial-width-windows",
4320 &truncate_partial_width_windows,
44fa5b1e 4321 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
4322 truncate_partial_width_windows = 1;
4323
4324 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
4325 "*Non-nil means use inverse video for the mode line.");
4326 mode_line_inverse_video = 1;
aa6d10fa
RS
4327
4328 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
4329 "*Maximum buffer size for which line number should be displayed.");
4330 line_number_display_limit = 1000000;
fba9ce76
RS
4331
4332 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
4333 "*Non-nil means highlight region even in nonselected windows.");
4334 highlight_nonselected_windows = 1;
d39b6696
KH
4335
4336 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
4337 "Non-nil if more than one frame is visible on this display.\n\
4338Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
4339This variable is not guaranteed to be accurate except while processing\n\
4340`frame-title-format' and `icon-title-format'.");
d39b6696
KH
4341
4342 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
4343 "Template for displaying the titlebar of visible frames.\n\
4344\(Assuming the window manager supports this feature.)\n\
4345This variable has the same structure as `mode-line-format' (which see),\n\
4346and is used only on frames for which no explicit name has been set\n\
4347\(see `modify-frame-parameters').");
4348 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
4349 "Template for displaying the titlebar of an iconified frame.\n\
4350\(Assuming the window manager supports this feature.)\n\
4351This variable has the same structure as `mode-line-format' (which see),\n\
4352and is used only on frames for which no explicit name has been set\n\
4353\(see `modify-frame-parameters').");
4354 Vicon_title_format
4355 = Vframe_title_format
4356 = Fcons (intern ("multiple-frames"),
4357 Fcons (build_string ("%b"),
4358 Fcons (Fcons (build_string (""),
4359 Fcons (intern ("invocation-name"),
4360 Fcons (build_string ("@"),
4361 Fcons (intern ("system-name"),
4362 Qnil)))),
4363 Qnil)));
5992c4f7
KH
4364
4365 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
4366 "Maximum number of lines to keep in the message log buffer.\n\
4367If nil, disable message logging. If t, log messages but don't truncate\n\
4368the buffer when it becomes large.");
4369 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
4370
4371 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
4372 "Functions called before redisplay, if window sizes have changed.\n\
4373The value should be a list of functions that take one argument.\n\
4374Just before redisplay, for each frame, if any of its windows have changed\n\
4375size since the last redisplay, or have been split or deleted,\n\
4376all the functions in the list are called, with the frame as argument.");
4377 Vwindow_size_change_functions = Qnil;
75c43375
RS
4378
4379 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
f908610f 4380 "List of Functions to call before redisplaying a window with scrolling.\n\
75c43375 4381Each function is called with two arguments, the window\n\
8d9583b0
RS
4382and its new display-start position. Note that the value of `window-end'\n\
4383is not valid when these functions are called.");
75c43375 4384 Vwindow_scroll_functions = Qnil;
a2889657
JB
4385}
4386
4387/* initialize the window system */
4388init_xdisp ()
4389{
4390 Lisp_Object root_window;
4391#ifndef COMPILER_REGISTER_BUG
4392 register
4393#endif /* COMPILER_REGISTER_BUG */
4394 struct window *mini_w;
4395
4396 this_line_bufpos = 0;
4397
4398 mini_w = XWINDOW (minibuf_window);
11e82b76 4399 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657
JB
4400
4401 echo_area_glyphs = 0;
4402 previous_echo_glyphs = 0;
4403
4404 if (!noninteractive)
4405 {
44fa5b1e 4406 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
c2213350 4407 XSETFASTINT (XWINDOW (root_window)->top, 0);
44fa5b1e 4408 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
c2213350 4409 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
4410 set_window_height (minibuf_window, 1, 0);
4411
c2213350
KH
4412 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
4413 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
a2889657
JB
4414 }
4415}