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