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