(sys_socket): Make sockets non-inheritable.
[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 2499 Lisp_Object invis_prop;
975d21ea
AS
2500 invis_prop = Fget_char_property (make_number (val.bufpos - 1),
2501 Qinvisible, window);
642eefc6 2502 invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
e885523c 2503#endif
642eefc6
RS
2504
2505 last_text_vpos
2506 /* Next line, unless prev line ended in end of buffer with no cr */
2507 = vpos - (val.vpos
12adba34 2508 && (FETCH_BYTE (val.bytepos - 1) != '\n' || invis));
642eefc6 2509 }
a2889657
JB
2510 pos = val.bufpos;
2511 }
2512
2513 /* If last line is continued in middle of character,
44fa5b1e 2514 include the split character in the text considered on the frame */
a2889657
JB
2515 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
2516 pos++;
2517
44fa5b1e 2518 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
2519 if (XFASTINT (w->window_end_pos) == 0
2520 && Z != pos)
2521 w->update_mode_line = Qt;
2522
44fa5b1e 2523 /* Say where last char on frame will be, once redisplay is finished. */
c2213350
KH
2524 XSETFASTINT (w->window_end_pos, Z - pos);
2525 XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
a2889657
JB
2526 /* But that is not valid info until redisplay finishes. */
2527 w->window_end_valid = Qnil;
2528}
2529\f
2530/* Try to redisplay when buffer is modified locally,
2531 computing insert/delete line to preserve text outside
2532 the bounds of the changes.
2533 Return 1 if successful, 0 if if cannot tell what to do,
2534 or -1 to tell caller to find a new window start,
2535 or -2 to tell caller to do normal redisplay with same window start. */
2536
2537static int
2538try_window_id (window)
2539 Lisp_Object window;
2540{
12adba34
RS
2541 int pos, pos_byte;
2542 int opoint, opoint_byte;
a2889657
JB
2543 register struct window *w = XWINDOW (window);
2544 register int height = window_internal_height (w);
44fa5b1e 2545 FRAME_PTR f = XFRAME (w->frame);
a2889657
JB
2546 int top = XFASTINT (w->top);
2547 int start = marker_position (w->start);
b1d1124b 2548 int width = window_internal_width (w) - 1;
a2889657
JB
2549 int hscroll = XINT (w->hscroll);
2550 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
ca26e1c8 2551 int did_motion;
a2889657
JB
2552 register int vpos;
2553 register int i, tem;
2554 int last_text_vpos = 0;
2555 int stop_vpos;
e24c997d
KH
2556 int selective = (INTEGERP (current_buffer->selective_display)
2557 ? XINT (current_buffer->selective_display)
2558 : !NILP (current_buffer->selective_display) ? -1 : 0);
a2889657
JB
2559 struct position val, bp, ep, xp, pp;
2560 int scroll_amount = 0;
2561 int delta;
1c9241f5 2562 int epto, old_tick;
a2889657 2563
12adba34
RS
2564 int start_byte = marker_byte_position (w->start);
2565
a2889657
JB
2566 if (GPT - BEG < beg_unchanged)
2567 beg_unchanged = GPT - BEG;
2568 if (Z - GPT < end_unchanged)
2569 end_unchanged = Z - GPT;
2570
6a1dc7ac 2571 if (beg_unchanged + BEG < start)
a2889657
JB
2572 return 0; /* Give up if changes go above top of window */
2573
2574 /* Find position before which nothing is changed. */
ca26e1c8 2575 bp = *compute_motion (start, 0, lmargin, 0,
1c9241f5
KH
2576 min (ZV, beg_unchanged + BEG), height,
2577 /* BUG FIX: See the comment of
12adba34 2578 Fpos_visible_in_window_p (window.c). */
1c9241f5 2579 - (1 << (BITS_PER_SHORT - 1)),
12adba34
RS
2580 width, hscroll,
2581 pos_tab_offset (w, start, start_byte),
2582 w);
a2889657 2583 if (bp.vpos >= height)
6e8290aa 2584 {
632ab665 2585 if (PT < bp.bufpos)
6e8290aa 2586 {
67481ae5
RS
2587 /* All changes are beyond the window end, and point is on the screen.
2588 We don't need to change the text at all.
6e8290aa
JB
2589 But we need to update window_end_pos to account for
2590 any change in buffer size. */
ca26e1c8 2591 bp = *compute_motion (start, 0, lmargin, 0,
1c9241f5
KH
2592 ZV, height,
2593 /* BUG FIX: See the comment of
2594 Fpos_visible_in_window_p() (window.c). */
2595 - (1 << (BITS_PER_SHORT - 1)),
12adba34
RS
2596 width, hscroll,
2597 pos_tab_offset (w, start, start_byte), w);
c2213350
KH
2598 XSETFASTINT (w->window_end_vpos, height);
2599 XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
4d641a15 2600 goto findpoint;
6e8290aa
JB
2601 }
2602 return 0;
2603 }
a2889657
JB
2604
2605 vpos = bp.vpos;
2606
44fa5b1e 2607 /* Find beginning of that frame line. Must display from there. */
210e752f 2608 bp = *vmotion (bp.bufpos, 0, w);
a2889657
JB
2609
2610 pos = bp.bufpos;
12adba34 2611 pos_byte = bp.bytepos;
a2889657
JB
2612 val.hpos = lmargin;
2613 if (pos < start)
2614 return -1;
2615
ca26e1c8 2616 did_motion = 0;
a2889657 2617 /* If about to start displaying at the beginning of a continuation line,
44fa5b1e 2618 really start with previous frame line, in case it was not
a2889657 2619 continued when last redisplayed */
05ba02eb
JB
2620 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
2621 ||
2622 /* Likewise if we have to worry about selective display. */
9f412332 2623 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
a2889657 2624 {
210e752f 2625 bp = *vmotion (bp.bufpos, -1, w);
a2889657
JB
2626 --vpos;
2627 pos = bp.bufpos;
12adba34 2628 pos_byte = bp.bytepos;
a2889657 2629 }
1c9241f5 2630 val.tab_offset = bp.tab_offset; /* Update tab offset. */
a2889657
JB
2631
2632 if (bp.contin && bp.hpos != lmargin)
2633 {
2634 val.hpos = bp.prevhpos - width + lmargin;
1c9241f5 2635 val.tab_offset = bp.tab_offset + bp.prevhpos - width;
ca26e1c8 2636 did_motion = 1;
93fdf93b 2637 DEC_BOTH (pos, pos_byte);
a2889657
JB
2638 }
2639
2640 bp.vpos = vpos;
2641
2642 /* Find first visible newline after which no more is changed. */
12adba34
RS
2643 opoint = PT, opoint_byte = PT_BYTE;
2644 SET_PT (Z - max (end_unchanged, Z - ZV));
2645 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
9f412332 2646 if (selective > 0)
12adba34
RS
2647 while (PT < ZV - 1 && indented_beyond_p (PT, PT_BYTE, selective))
2648 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
2649 tem = PT;
2650 SET_PT_BOTH (opoint, opoint_byte);
a2889657
JB
2651
2652 /* Compute the cursor position after that newline. */
ca26e1c8 2653 ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
68be917d 2654 height, - (1 << (BITS_PER_SHORT - 1)),
1c9241f5
KH
2655 width, hscroll,
2656 /* We have tab offset in VAL, use it. */
2657 val.tab_offset, w);
a2889657 2658
44fa5b1e
JB
2659 /* If changes reach past the text available on the frame,
2660 just display rest of frame. */
a2889657
JB
2661 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
2662 stop_vpos = height;
2663 else
2664 stop_vpos = ep.vpos;
2665
2666 /* If no newline before ep, the line ep is on includes some changes
2667 that must be displayed. Make sure we don't stop before it. */
2668 /* Also, if changes reach all the way until ep.bufpos,
2669 it is possible that something was deleted after the
2670 newline before it, so the following line must be redrawn. */
2671 if (stop_vpos == ep.vpos
2672 && (ep.bufpos == BEGV
f1c87a7d 2673 || FETCH_BYTE (ep.bytepos - 1) != '\n'
a2889657
JB
2674 || ep.bufpos == Z - end_unchanged))
2675 stop_vpos = ep.vpos + 1;
2676
2677 cursor_vpos = -1;
2678 overlay_arrow_seen = 0;
ca26e1c8 2679 zv_strings_seen = 0;
a2889657
JB
2680
2681 /* If changes do not reach to bottom of window,
2682 figure out how much to scroll the rest of the window */
2683 if (stop_vpos < height)
2684 {
2685 /* Now determine how far up or down the rest of the window has moved */
ca26e1c8 2686 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
a2889657 2687 Z - XFASTINT (w->window_end_pos),
1c9241f5
KH
2688 /* Don't care for VPOS... */
2689 1 << (BITS_PER_SHORT - 1),
2690 /* ... nor HPOS. */
2691 1 << (BITS_PER_SHORT - 1),
2692 width, hscroll, ep.tab_offset, w);
a2889657
JB
2693 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
2694
44fa5b1e 2695 /* Is everything on frame below the changes whitespace?
a2889657 2696 If so, no scrolling is really necessary. */
f1c87a7d 2697 for (i = ep.bytepos; i < xp.bytepos; i++)
a2889657 2698 {
1c9241f5 2699 tem = FETCH_BYTE (i);
a2889657
JB
2700 if (tem != ' ' && tem != '\n' && tem != '\t')
2701 break;
2702 }
f1c87a7d 2703 if (i == xp.bytepos)
a2889657
JB
2704 return -2;
2705
e8e536a9
KH
2706 XSETFASTINT (w->window_end_vpos,
2707 XFASTINT (w->window_end_vpos) + scroll_amount);
a2889657 2708
44fa5b1e 2709 /* Before doing any scrolling, verify that point will be on frame. */
010a899e 2710 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.vpos < height))
a2889657 2711 {
ae3b1442 2712 if (PT <= xp.bufpos)
a2889657 2713 {
ca26e1c8 2714 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
68be917d 2715 PT, height, - (1 << (BITS_PER_SHORT - 1)),
1c9241f5
KH
2716 width, hscroll,
2717 /* We have tab offset in EP, use it. */
2718 ep.tab_offset, w);
a2889657
JB
2719 }
2720 else
2721 {
ca26e1c8 2722 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
68be917d 2723 PT, height, - (1 << (BITS_PER_SHORT - 1)),
e37f06d7 2724 width, hscroll,
1c9241f5
KH
2725 /* We have tab offset in XP, use it. */
2726 xp.tab_offset, w);
a2889657 2727 }
ae3b1442 2728 if (pp.bufpos < PT || pp.vpos == height)
a2889657
JB
2729 return 0;
2730 cursor_vpos = pp.vpos + top;
73f194f1 2731 cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, pp.hpos, width);
a2889657
JB
2732 }
2733
2734 if (stop_vpos - scroll_amount >= height
2735 || ep.bufpos == xp.bufpos)
2736 {
2737 if (scroll_amount < 0)
2738 stop_vpos -= scroll_amount;
2739 scroll_amount = 0;
2740 /* In this path, we have altered window_end_vpos
2741 and not left it negative.
2742 We must make sure that, in case display is preempted
44fa5b1e 2743 before the frame changes to reflect what we do here,
a2889657 2744 further updates will not come to try_window_id
44fa5b1e 2745 and assume the frame and window_end_vpos match. */
a2889657
JB
2746 blank_end_of_window = 1;
2747 }
2748 else if (!scroll_amount)
0d231165
RS
2749 {
2750 /* Even if we don't need to scroll, we must adjust the
2751 charstarts of subsequent lines (that we won't redisplay)
2752 according to the amount of text inserted or deleted. */
2753 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2754 int adjust = ep.bufpos - oldpos;
2755 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
2756 }
a2889657
JB
2757 else if (bp.bufpos == Z - end_unchanged)
2758 {
2759 /* If reprinting everything is nearly as fast as scrolling,
2760 don't bother scrolling. Can happen if lines are short. */
44fa5b1e 2761 if (scroll_cost (f, bp.vpos + top - scroll_amount,
a2889657
JB
2762 top + height - max (0, scroll_amount),
2763 scroll_amount)
2764 > xp.bufpos - bp.bufpos - 20)
2765 /* Return "try normal display with same window-start."
2766 Too bad we can't prevent further scroll-thinking. */
2767 return -2;
2768 /* If pure deletion, scroll up as many lines as possible.
2769 In common case of killing a line, this can save the
2770 following line from being overwritten by scrolling
2771 and therefore having to be redrawn. */
44fa5b1e 2772 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
d1cb44a4
RS
2773 top + height - max (0, scroll_amount),
2774 scroll_amount, bp.bufpos);
d2f84654
RS
2775 if (!tem)
2776 stop_vpos = height;
2777 else
2778 {
2779 /* scroll_frame_lines did not properly adjust subsequent
2780 lines' charstarts in the case where the text of the
2781 screen line at bp.vpos has changed.
2782 (This can happen in a deletion that ends in mid-line.)
8e6208c5
KH
2783 To adjust properly, we need to make things consistent
2784 at the position ep.
d2f84654
RS
2785 So do a second adjust to make that happen.
2786 Note that stop_vpos >= ep.vpos, so it is sufficient
2787 to update the charstarts for lines at ep.vpos and below. */
2788 int oldstart
2789 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
2790 adjust_window_charstarts (w, ep.vpos + top - 1,
2791 ep.bufpos - oldstart);
2792 }
a2889657
JB
2793 }
2794 else if (scroll_amount)
2795 {
2796 /* If reprinting everything is nearly as fast as scrolling,
2797 don't bother scrolling. Can happen if lines are short. */
2798 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
2799 overestimate of cost of reprinting, since xp.bufpos
2800 would end up below the bottom of the window. */
44fa5b1e 2801 if (scroll_cost (f, ep.vpos + top - scroll_amount,
a2889657
JB
2802 top + height - max (0, scroll_amount),
2803 scroll_amount)
2804 > xp.bufpos - ep.bufpos - 20)
2805 /* Return "try normal display with same window-start."
2806 Too bad we can't prevent further scroll-thinking. */
2807 return -2;
44fa5b1e 2808 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
a2889657 2809 top + height - max (0, scroll_amount),
d1cb44a4 2810 scroll_amount, ep.bufpos);
a2889657
JB
2811 if (!tem) stop_vpos = height;
2812 }
2813 }
2814
2815 /* In any case, do not display past bottom of window */
2816 if (stop_vpos >= height)
2817 {
2818 stop_vpos = height;
2819 scroll_amount = 0;
2820 }
2821
2822 /* Handle case where pos is before w->start --
2823 can happen if part of line had been clipped and is not clipped now */
2824 if (vpos == 0 && pos < marker_position (w->start))
2825 Fset_marker (w->start, make_number (pos), Qnil);
2826
12adba34
RS
2827 val.bytepos = pos_byte;
2828
a2889657
JB
2829 /* Redisplay the lines where the text was changed */
2830 last_text_vpos = vpos;
1c9241f5
KH
2831 /* The following code is omitted because we maintain tab offset in
2832 val.tab_offset. */
2833#if 0
12adba34 2834 tab_offset = pos_tab_offset (w, pos, pos_byte);
a2889657
JB
2835 /* If we are starting display in mid-character, correct tab_offset
2836 to account for passing the line that that character really starts in. */
2837 if (val.hpos < lmargin)
2838 tab_offset += width;
1c9241f5 2839#endif /* 0 */
d3413a53 2840 old_tick = MODIFF;
a2889657
JB
2841 while (vpos < stop_vpos)
2842 {
12adba34
RS
2843 val = *display_text_line (w, pos, val.bytepos, top + vpos++,
2844 val.hpos, val.tab_offset,
0f9c0ff0 2845 val.ovstring_chars_done);
d3413a53
RS
2846 /* If display_text_line ran a hook and changed some text,
2847 redisplay all the way to bottom of buffer
2848 So that we show the changes. */
2849 if (old_tick != MODIFF)
2850 stop_vpos = height;
1c9241f5
KH
2851 /* The following code is omitted because we maintain tab offset
2852 in val.tab_offset. */
2853#if 0
a2889657
JB
2854 tab_offset += width;
2855 if (val.vpos) tab_offset = 0;
1c9241f5 2856#endif
a2889657
JB
2857 if (pos != val.bufpos)
2858 last_text_vpos
2859 /* Next line, unless prev line ended in end of buffer with no cr */
f1c87a7d 2860 = vpos - (val.vpos && FETCH_BYTE (val.bytepos - 1) != '\n');
a2889657
JB
2861 pos = val.bufpos;
2862 }
2863
2864 /* There are two cases:
2865 1) we have displayed down to the bottom of the window
2866 2) we have scrolled lines below stop_vpos by scroll_amount */
2867
2868 if (vpos == height)
2869 {
2870 /* If last line is continued in middle of character,
44fa5b1e 2871 include the split character in the text considered on the frame */
a2889657
JB
2872 if (val.hpos < lmargin)
2873 val.bufpos++;
c2213350
KH
2874 XSETFASTINT (w->window_end_vpos, last_text_vpos);
2875 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
a2889657
JB
2876 }
2877
2878 /* If scrolling made blank lines at window bottom,
2879 redisplay to fill those lines */
2880 if (scroll_amount < 0)
2881 {
2882 /* Don't consider these lines for general-purpose scrolling.
2883 That will save time in the scrolling computation. */
44fa5b1e 2884 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
a2889657
JB
2885 vpos = xp.vpos;
2886 pos = xp.bufpos;
12adba34 2887 pos_byte = xp.bytepos;
1c9241f5
KH
2888 val.hpos = xp.hpos;
2889 val.tab_offset = xp.tab_offset;
a2889657 2890 if (pos == ZV)
010a899e
KH
2891 { /* Display from next line */
2892 vpos = height + scroll_amount;
2893 val.hpos = lmargin;
2894 val.tab_offset = 0;
2895 }
a2889657
JB
2896 else if (xp.contin && xp.hpos != lmargin)
2897 {
2898 val.hpos = xp.prevhpos - width + lmargin;
1c9241f5 2899 val.tab_offset = xp.tab_offset + bp.prevhpos - width;
93fdf93b 2900 DEC_BOTH (pos, pos_byte);
a2889657
JB
2901 }
2902
2903 blank_end_of_window = 1;
1c9241f5
KH
2904 /* The following code is omitted because we maintain tab offset
2905 in val.tab_offset. */
2906#if 0
12adba34 2907 tab_offset = pos_tab_offset (w, pos, pos_byte);
a2889657
JB
2908 /* If we are starting display in mid-character, correct tab_offset
2909 to account for passing the line that that character starts in. */
2910 if (val.hpos < lmargin)
2911 tab_offset += width;
1c9241f5 2912#endif
f1c87a7d 2913 val.bytepos = pos_byte;
a2889657
JB
2914 while (vpos < height)
2915 {
12adba34
RS
2916 val = *display_text_line (w, pos, val.bytepos,
2917 top + vpos++, val.hpos,
1c9241f5
KH
2918 val.tab_offset, val.ovstring_chars_done);
2919 /* The following code is omitted because we maintain tab
2920 offset in val.tab_offset. */
2921#if 0
a2889657
JB
2922 tab_offset += width;
2923 if (val.vpos) tab_offset = 0;
1c9241f5 2924#endif /* 0 */
a2889657
JB
2925 pos = val.bufpos;
2926 }
2927
2928 /* Here is a case where display_text_line sets cursor_vpos wrong.
2929 Make it be fixed up, below. */
2930 if (xp.bufpos == ZV
ae3b1442 2931 && xp.bufpos == PT)
a2889657
JB
2932 cursor_vpos = -1;
2933 }
2934
44fa5b1e 2935 /* If bottom just moved off end of frame, change mode line percentage. */
a2889657
JB
2936 if (XFASTINT (w->window_end_pos) == 0
2937 && Z != val.bufpos)
2938 w->update_mode_line = Qt;
2939
2940 /* Attempt to adjust end-of-text positions to new bottom line */
2941 if (scroll_amount)
2942 {
2943 delta = height - xp.vpos;
2944 if (delta < 0
2945 || (delta > 0 && xp.bufpos <= ZV)
2946 || (delta == 0 && xp.hpos))
2947 {
210e752f 2948 val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
c2213350 2949 XSETFASTINT (w->window_end_pos, Z - val.bufpos);
e8e536a9
KH
2950 XSETFASTINT (w->window_end_vpos,
2951 XFASTINT (w->window_end_vpos) + val.vpos);
a2889657
JB
2952 }
2953 }
2954
2955 w->window_end_valid = Qnil;
2956
2957 /* If point was not in a line that was displayed, find it */
2958 if (cursor_vpos < 0)
2959 {
4d641a15 2960 findpoint:
1c9241f5
KH
2961 val = *compute_motion (start, 0, lmargin, 0, PT,
2962 /* Don't care for VPOS... */
2963 1 << (BITS_PER_SHORT - 1),
2964 /* ... nor HPOS. */
2965 1 << (BITS_PER_SHORT - 1),
12adba34
RS
2966 width, hscroll,
2967 pos_tab_offset (w, start, start_byte),
2968 w);
44fa5b1e 2969 /* Admit failure if point is off frame now */
a2889657
JB
2970 if (val.vpos >= height)
2971 {
2972 for (vpos = 0; vpos < height; vpos++)
44fa5b1e 2973 cancel_line (vpos + top, f);
a2889657
JB
2974 return 0;
2975 }
2976 cursor_vpos = val.vpos + top;
73f194f1 2977 cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width);
a2889657
JB
2978 }
2979
210e752f 2980 FRAME_CURSOR_X (f) = cursor_hpos;
44fa5b1e 2981 FRAME_CURSOR_Y (f) = cursor_vpos;
a2889657
JB
2982
2983 if (debug_end_pos)
2984 {
ca26e1c8 2985 val = *compute_motion (start, 0, lmargin, 0, ZV,
68be917d 2986 height, - (1 << (BITS_PER_SHORT - 1)),
12adba34
RS
2987 width, hscroll,
2988 pos_tab_offset (w, start, start_byte),
2989 w);
a2889657
JB
2990 if (val.vpos != XFASTINT (w->window_end_vpos))
2991 abort ();
2992 if (XFASTINT (w->window_end_pos)
2993 != Z - val.bufpos)
2994 abort ();
2995 }
2996
2997 return 1;
2998}
2999\f
278feba9 3000/* Copy LEN glyphs starting address FROM to the rope TO.
f7430cb6 3001 But don't actually copy the parts that would come in before S.
278feba9
RS
3002 Value is TO, advanced past the copied data.
3003 F is the frame we are displaying in. */
a2889657 3004
278feba9
RS
3005static GLYPH *
3006copy_part_of_rope (f, to, s, from, len, face)
3007 FRAME_PTR f;
3008 register GLYPH *to; /* Copy to here. */
a2889657 3009 register GLYPH *s; /* Starting point. */
278feba9
RS
3010 Lisp_Object *from; /* Data to copy. */
3011 int len;
1c2250c2 3012 int face; /* Face to apply to glyphs which don't specify one. */
a2889657 3013{
278feba9
RS
3014 int n = len;
3015 register Lisp_Object *fp = from;
3016 /* These cache the results of the last call to compute_glyph_face. */
3017 int last_code = -1;
3018 int last_merged = 0;
c581d710 3019
87485d6f 3020#ifdef HAVE_FACES
4cdc65eb
KH
3021 if (! FRAME_TERMCAP_P (f))
3022 while (n--)
3023 {
e57bca5d 3024 GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb 3025 int facecode;
e57bca5d
KH
3026 unsigned int c = FAST_GLYPH_CHAR (glyph);
3027
3028 if (c > MAX_CHAR)
3029 /* For an invalid character code, use space. */
3030 c = ' ';
4cdc65eb
KH
3031
3032 if (FAST_GLYPH_FACE (glyph) == 0)
3033 /* If GLYPH has no face code, use FACE. */
3034 facecode = face;
3035 else if (FAST_GLYPH_FACE (glyph) == last_code)
3036 /* If it's same as previous glyph, use same result. */
3037 facecode = last_merged;
3038 else
3039 {
3040 /* Merge this glyph's face and remember the result. */
3041 last_code = FAST_GLYPH_FACE (glyph);
3042 last_merged = facecode = compute_glyph_face (f, last_code, face);
3043 }
b2a76982 3044
4cdc65eb 3045 if (to >= s)
e57bca5d 3046 *to = FAST_MAKE_GLYPH (c, facecode);
4cdc65eb
KH
3047 ++to;
3048 ++fp;
3049 }
3050 else
3051#endif
3052 while (n--)
3053 {
dedd1182 3054 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
4cdc65eb
KH
3055 ++to;
3056 ++fp;
3057 }
278feba9 3058 return to;
c581d710
RS
3059}
3060
278feba9
RS
3061/* Correct a glyph by replacing its specified user-level face code
3062 with a displayable computed face code. */
c581d710 3063
278feba9 3064static GLYPH
659a218f 3065fix_glyph (f, glyph, cface)
278feba9
RS
3066 FRAME_PTR f;
3067 GLYPH glyph;
659a218f 3068 int cface;
c581d710 3069{
87485d6f 3070#ifdef HAVE_FACES
659a218f
KH
3071 if (! FRAME_TERMCAP_P (f))
3072 {
3073 if (FAST_GLYPH_FACE (glyph) != 0)
3074 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
3075 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
3076 }
4cdc65eb
KH
3077#endif
3078 return glyph;
a2889657
JB
3079}
3080\f
12adba34 3081/* Return the column of position POS / POS_BYTE in window W's buffer.
4a4c24d0
RS
3082 When used on the character at the beginning of a line,
3083 starting at column 0, this says how much to subtract from
3084 the column position of any character in the line
3085 to get its horizontal position on the screen. */
12adba34
RS
3086
3087static int
3088pos_tab_offset (w, pos, pos_byte)
3089 struct window *w;
3090 register int pos, pos_byte;
3091{
3092 int opoint = PT;
3093 int opoint_byte = PT_BYTE;
3094 int col;
3095 int width = window_internal_width (w) - 1;
3096
3097 if (pos == BEGV)
3098 return MINI_WINDOW_P (w) ? -minibuf_prompt_width : 0;
3099
3100 if (FETCH_BYTE (pos_byte - 1) == '\n')
3101 return 0;
3102
3103 TEMP_SET_PT_BOTH (pos, pos_byte);
3104 col = current_column ();
3105 TEMP_SET_PT_BOTH (opoint, opoint_byte);
3106
3107 return col;
3108}
3109\f\f
3110/* Display one line of window W, starting at char position START in W's buffer.
3111 START_BYTE is the corresponding byte position.
f4faa47c
JB
3112
3113 Display starting at horizontal position HPOS, expressed relative to
3114 W's left edge. In situations where the text at START shouldn't
3115 start at the left margin (i.e. when the window is hscrolled, or
3116 we're continuing a line which left off in the midst of a
3117 multi-column character), HPOS should be negative; we throw away
3118 characters up 'til hpos = 0. So, HPOS must take hscrolling into
3119 account.
a2889657
JB
3120
3121 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
3122
0f9c0ff0
RS
3123 OVSTR_DONE is the number of chars of overlay before/after strings
3124 at this position which have already been processed.
3125
f4faa47c
JB
3126 Display on position VPOS on the frame. It is origin 0, relative to
3127 the top of the frame, not W.
a2889657
JB
3128
3129 Returns a STRUCT POSITION giving character to start next line with
3130 and where to display it, including a zero or negative hpos.
3131 The vpos field is not really a vpos; it is 1 unless the line is continued */
3132
3133struct position val_display_text_line;
3134
3135static struct position *
12adba34 3136display_text_line (w, start, start_byte, vpos, hpos, taboffset, ovstr_done)
a2889657
JB
3137 struct window *w;
3138 int start;
3139 int vpos;
3140 int hpos;
3141 int taboffset;
0f9c0ff0 3142 int ovstr_done;
a2889657
JB
3143{
3144 register int pos = start;
12adba34 3145 int pos_byte = start_byte;
a2889657
JB
3146 register int c;
3147 register GLYPH *p1;
12adba34 3148 int pause, limit_byte;
a2889657
JB
3149 register unsigned char *p;
3150 GLYPH *endp;
d2f84654 3151 register GLYPH *leftmargin;
ca26e1c8 3152 register GLYPH *p1prev;
efc63ef0 3153 register GLYPH *p1start;
0d09d1e6 3154 GLYPH *p1_wide_column_end = (GLYPH *) 0;
12adba34 3155 int prevpos, prevpos_byte;
efc63ef0 3156 int *charstart;
44fa5b1e 3157 FRAME_PTR f = XFRAME (w->frame);
a2889657 3158 int tab_width = XINT (current_buffer->tab_width);
265a9e55 3159 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
b1d1124b 3160 int width = window_internal_width (w) - 1;
a2889657 3161 struct position val;
12adba34 3162 int lastpos, lastpos_byte;
a2889657 3163 int invis;
642eefc6
RS
3164 int last_invis_skip = 0;
3165 Lisp_Object last_invis_prop;
a2889657 3166 int hscroll = XINT (w->hscroll);
d2f84654
RS
3167 int truncate = (hscroll
3168 || (truncate_partial_width_windows
73f194f1 3169 && !WINDOW_FULL_WIDTH_P (w))
d2f84654 3170 || !NILP (current_buffer->truncate_lines));
bd66d1ba 3171
409bb864 3172 /* 1 if this buffer has a region to highlight. */
bd66d1ba 3173 int highlight_region
2bf32c5d 3174 = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)
409bb864 3175 && XMARKER (current_buffer->mark)->buffer != 0);
bd66d1ba
RS
3176 int region_beg, region_end;
3177
e24c997d
KH
3178 int selective = (INTEGERP (current_buffer->selective_display)
3179 ? XINT (current_buffer->selective_display)
3180 : !NILP (current_buffer->selective_display) ? -1 : 0);
44fa5b1e 3181 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
f908610f 3182 register struct Lisp_Char_Table *dp = window_display_table (w);
68a37fa8
RS
3183
3184 Lisp_Object default_invis_vector[3];
642eefc6
RS
3185 /* Number of characters of ellipsis to display after an invisible line
3186 if it calls for an ellipsis.
3187 Note that this value can be nonzero regardless of whether
3188 selective display is enabled--you must check that separately. */
a2889657 3189 int selective_rlen
642eefc6 3190 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
68a37fa8 3191 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
642eefc6 3192 : !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
68a37fa8
RS
3193 /* This is the sequence of Lisp objects to display
3194 when there are invisible lines. */
3195 Lisp_Object *invis_vector_contents
e24c997d 3196 = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
68a37fa8
RS
3197 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
3198 : default_invis_vector);
3199
e24c997d 3200 GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
e57bca5d 3201 || !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp)))
278feba9 3202 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
e24c997d 3203 GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
e57bca5d 3204 || !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp)))
278feba9 3205 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
a2889657 3206
1c9241f5
KH
3207 /* If 1, we must handle multibyte characters. */
3208 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
3209 /* Length of multibyte form of each character. */
3210 int len;
3211 /* Glyphs generated should be set this bit mask if text must be
3212 displayed from right to left. */
3213 GLYPH rev_dir_bit = (NILP (current_buffer->direction_reversed)
3214 ? 0 : GLYPH_MASK_REV_DIR);
3215
31b24551
JB
3216 /* The next buffer location at which the face should change, due
3217 to overlays or text property changes. */
3218 int next_face_change;
3219
ca26e1c8
KH
3220 /* The next location where the `invisible' property changes, or an
3221 overlay starts or ends. */
3222 int next_boundary;
3223
31b24551 3224 /* The face we're currently using. */
1c2250c2 3225 int current_face = 0;
efc63ef0 3226 int i;
31b24551 3227
c2213350 3228 XSETFASTINT (default_invis_vector[2], '.');
68a37fa8
RS
3229 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
3230
73f194f1 3231 get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
54ff581a 3232 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657 3233
bd66d1ba 3234 /* Show where to highlight the region. */
409bb864 3235 if (highlight_region
fba9ce76
RS
3236 /* Maybe highlight only in selected window. */
3237 && (highlight_nonselected_windows
409bb864
KH
3238 || w == XWINDOW (selected_window)
3239 || (MINI_WINDOW_P (XWINDOW (selected_window))
3240 && w == XWINDOW (Vminibuf_scroll_window))))
bd66d1ba
RS
3241 {
3242 region_beg = marker_position (current_buffer->mark);
3243 if (PT < region_beg)
3244 {
3245 region_end = region_beg;
3246 region_beg = PT;
3247 }
3248 else
3249 region_end = PT;
3250 w->region_showing = Qt;
3251 }
3252 else
3ee4159a
RS
3253 {
3254 region_beg = region_end = -1;
3255 w->region_showing = Qnil;
3256 }
bd66d1ba 3257
f4faa47c 3258 if (MINI_WINDOW_P (w)
ca26e1c8 3259 && start == BEG
a2889657
JB
3260 && vpos == XFASTINT (w->top))
3261 {
8c5b6a0a 3262 if (! NILP (minibuf_prompt))
f7b4b63a 3263 {
12a274bf
RS
3264 int old_width = minibuf_prompt_width;
3265
f7b4b63a 3266 minibuf_prompt_width
8c5b6a0a 3267 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
fc932ac6 3268 STRING_BYTES (XSTRING (minibuf_prompt)),
377dbd97 3269 hpos + WINDOW_LEFT_MARGIN (w),
ce006f69
RS
3270 /* Display a space if we truncate. */
3271 ' ',
3272 1, -1,
3273 /* Truncate the prompt a little before the
3274 margin, so user input can at least start
3275 on the first line. */
8bb6ca14 3276 (XFASTINT (w->width) > 10
a3788d53 3277 ? XFASTINT (w->width) - 4 : -1),
0a9dc68b 3278 STRING_MULTIBYTE (minibuf_prompt))
377dbd97 3279 - hpos - WINDOW_LEFT_MARGIN (w));
f7b4b63a 3280 hpos += minibuf_prompt_width;
12a274bf 3281 taboffset -= minibuf_prompt_width - old_width;
f7b4b63a
KH
3282 }
3283 else
3284 minibuf_prompt_width = 0;
a2889657
JB
3285 }
3286
f4faa47c
JB
3287 /* If we're hscrolled at all, use compute_motion to skip over any
3288 text off the left edge of the window. compute_motion may know
3289 tricks to do this faster than we can. */
3290 if (hpos < 0)
3291 {
3292 struct position *left_edge
ca26e1c8
KH
3293 = compute_motion (pos, vpos, hpos, 0,
3294 ZV, vpos, 0,
f4faa47c
JB
3295 width, hscroll, taboffset, w);
3296
3297 /* Retrieve the buffer position and column provided by
3298 compute_motion. We can't assume that the column will be
3299 zero, because you may have multi-column characters crossing
3300 the left margin.
3301
3302 compute_motion may have moved us past the screen position we
3303 requested, if we hit a multi-column character, or the end of
3304 the line. If so, back up. */
3305 if (left_edge->vpos > vpos
3306 || left_edge->hpos > 0)
3307 {
93fdf93b 3308 pos = left_edge->bufpos;
0d09d1e6 3309 pos_byte = left_edge->bytepos;
93fdf93b 3310 DEC_BOTH (pos, pos_byte);
f4faa47c
JB
3311 hpos = left_edge->prevhpos;
3312 }
3313 else
3314 {
3315 pos = left_edge->bufpos;
12adba34 3316 pos_byte = left_edge->bytepos;
f4faa47c
JB
3317 hpos = left_edge->hpos;
3318 }
3319 }
3320
377dbd97
RS
3321 hpos += WINDOW_LEFT_MARGIN (w);
3322
f4faa47c 3323 desired_glyphs->bufp[vpos] = start;
a2889657 3324 p1 = desired_glyphs->glyphs[vpos] + hpos;
efc63ef0
RS
3325 p1start = p1;
3326 charstart = desired_glyphs->charstarts[vpos] + hpos;
3327 /* In case we don't ever write anything into it... */
73f194f1
RS
3328 desired_glyphs->charstarts[vpos][WINDOW_LEFT_MARGIN (w)] = -1;
3329 leftmargin = desired_glyphs->glyphs[vpos] + WINDOW_LEFT_MARGIN (w);
d2f84654 3330 endp = leftmargin + width;
a2889657 3331
1c2250c2
JB
3332 /* Arrange the overlays nicely for our purposes. Usually, we call
3333 display_text_line on only one line at a time, in which case this
3334 can't really hurt too much, or we call it on lines which appear
3335 one after another in the buffer, in which case all calls to
3336 recenter_overlay_lists but the first will be pretty cheap. */
3337 recenter_overlay_lists (current_buffer, pos);
3338
a2889657
JB
3339 /* Loop generating characters.
3340 Stop at end of buffer, before newline,
31b24551
JB
3341 if reach or pass continuation column,
3342 or at face change. */
a2889657 3343 pause = pos;
12adba34 3344 limit_byte = pos_byte;
31b24551 3345 next_face_change = pos;
ca26e1c8
KH
3346 next_boundary = pos;
3347 p1prev = p1;
3348 prevpos = pos;
12adba34 3349 prevpos_byte = pos_byte;
1fca3fae
RS
3350
3351 /* If the window is hscrolled and point is in the invisible part of the
3352 current line beyond the left margin we can record the cursor location
3353 right away. */
3354 if (hscroll && start <= PT && PT < pos && cursor_vpos < 0)
3355 {
3356 cursor_vpos = vpos;
3357 cursor_hpos = p1 - leftmargin;
3358 }
3359
2384c010 3360 while (p1 < endp)
a2889657 3361 {
31b24551 3362 if (pos >= pause)
a2889657 3363 {
67481ae5
RS
3364 int e_t_h;
3365
ca26e1c8 3366 while (pos == next_boundary)
a2889657 3367 {
ca26e1c8
KH
3368 Lisp_Object position, limit, prop, ww;
3369
3370 /* Display the overlay strings here, unless we're at ZV
3371 and have already displayed the appropriate strings
3372 on an earlier line. */
3373 if (pos < ZV || !zv_strings_seen++)
3374 {
3375 int ovlen;
b4222ffa 3376 unsigned char *ovstr;
ca26e1c8 3377 ovlen = overlay_strings (pos, w, &ovstr);
0f9c0ff0
RS
3378
3379 if (ovlen > 0)
ca26e1c8 3380 {
0f9c0ff0
RS
3381 /* Skip the ones we did in a previous line. */
3382 ovstr += ovstr_done;
3383 ovlen -= ovstr_done;
3384
1c9241f5 3385 while (ovlen > 0)
0f9c0ff0 3386 {
1c9241f5
KH
3387 int charset, cols;
3388 GLYPH g;
3389
3390 if (multibyte)
3391 {
3392 c = STRING_CHAR_AND_LENGTH (ovstr, ovlen, len);
3393 ovstr += len, ovlen -= len, ovstr_done += len;
3394 charset = CHAR_CHARSET (c);
3395 cols = (charset == CHARSET_COMPOSITION
3396 ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
3397 : CHARSET_WIDTH (charset));
3398 }
3399 else
3400 {
3401 c = *ovstr++, ovlen--, ovstr_done++;
3402 cols = 1;
3403 }
3404 g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
3405 while (cols-- > 0)
3406 {
3407 if (p1 >= leftmargin && p1 < endp)
3408 *p1 = g, g |= GLYPH_MASK_PADDING;
3409 p1++;
3410 }
0f9c0ff0
RS
3411 }
3412 /* If we did all the overlay strings
3413 and we have room for text, clear ovstr_done
3414 just for neatness' sake. */
3415 if (ovlen == 0 && p1 < endp)
3416 ovstr_done = 0;
ca26e1c8
KH
3417 }
3418 }
3419
3420 /* Did we reach point? Record the cursor location. */
3421 if (pos == PT && cursor_vpos < 0)
3422 {
3423 cursor_vpos = vpos;
3424 cursor_hpos = p1 - leftmargin;
3425 }
3426
3427 if (pos >= ZV)
3428 break;
a2889657 3429
c2213350 3430 XSETFASTINT (position, pos);
ca26e1c8
KH
3431 limit = Fnext_overlay_change (position);
3432#ifdef USE_TEXT_PROPERTIES
dfabd9a0
RS
3433 /* This is just an estimate to give reasonable
3434 performance; nothing should go wrong if it is too small. */
fe3d6921 3435 if (XFASTINT (limit) > pos + 50)
1c9241f5
KH
3436 {
3437 int limitpos = pos + 50;
1c9241f5
KH
3438 XSETFASTINT (limit, limitpos);
3439 }
ca26e1c8
KH
3440 limit = Fnext_single_property_change (position, Qinvisible,
3441 Fcurrent_buffer (), limit);
3442#endif
3443 next_boundary = XFASTINT (limit);
3444 /* if the `invisible' property is set, we can skip to
3445 the next property change. */
3446 XSETWINDOW (ww, w);
3447 prop = Fget_char_property (position, Qinvisible, ww);
642eefc6 3448 if (TEXT_PROP_MEANS_INVISIBLE (prop))
dfabd9a0 3449 {
ca26e1c8 3450 if (pos < PT && next_boundary >= PT)
dfabd9a0
RS
3451 {
3452 cursor_vpos = vpos;
d2f84654 3453 cursor_hpos = p1 - leftmargin;
dfabd9a0 3454 }
ca26e1c8 3455 pos = next_boundary;
f6e7abc1 3456 pos_byte = CHAR_TO_BYTE (pos);
642eefc6
RS
3457 last_invis_skip = pos;
3458 last_invis_prop = prop;
dfabd9a0 3459 }
b0a0fbda 3460 }
ca26e1c8
KH
3461
3462 /* Did we reach point? Record the cursor location. */
3463 if (pos == PT && cursor_vpos < 0)
3464 {
3465 cursor_vpos = vpos;
3466 cursor_hpos = p1 - leftmargin;
3467 }
3468
3469 /* Did we hit the end of the visible region of the buffer?
3470 Stop here. */
3471 if (pos >= ZV)
eff87c2c
RS
3472 {
3473 /* Update charstarts for the end of this line. */
3474 /* Do nothing if off the left edge or at the right edge. */
3475 if (p1 >= leftmargin && p1 + 1 != endp)
3476 {
3477 int *p2x = &charstart[(p1 < leftmargin
3478 ? leftmargin : p1)
3479 - p1start];
3480 *p2x++ = pos;
3481 }
3482 break;
3483 }
b0a0fbda 3484
67481ae5
RS
3485 /* Figure out where (if at all) the
3486 redisplay_end_trigger-hook should run. */
f6fd109b
RS
3487 if (MARKERP (w->redisplay_end_trigger)
3488 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
d3413a53
RS
3489 e_t_h = marker_position (w->redisplay_end_trigger);
3490 else if (INTEGERP (w->redisplay_end_trigger))
3491 e_t_h = XINT (w->redisplay_end_trigger);
67481ae5
RS
3492 else
3493 e_t_h = ZV;
3494
3495 /* If we've gone past the place to run a hook,
3496 run the hook. */
3497 if (pos >= e_t_h && e_t_h != ZV)
3498 {
e0bfbde6
RS
3499 Lisp_Object args[3];
3500
3501 args[0] = Qredisplay_end_trigger_functions;
3502 XSETWINDOW (args[1], w);
3503 XSETINT (args[2], e_t_h);
e0bfbde6 3504
9c49d3d7
KH
3505 /* Since we are *trying* to run these functions,
3506 don't try to run them again, even if they get an error. */
d3413a53 3507 w->redisplay_end_trigger = Qnil;
9c49d3d7
KH
3508 Frun_hook_with_args (3, args);
3509
67481ae5 3510 e_t_h = ZV;
f6fd109b
RS
3511 /* Notice if it changed the face of this character. */
3512 next_face_change = pos;
67481ae5
RS
3513 }
3514
f6fd109b
RS
3515#ifdef HAVE_FACES
3516 /* Did we hit a face change? Figure out what face we should
3517 use now. We also hit this the first time through the
3518 loop, to see what face we should start with. */
ab6ce60e
RS
3519 if (pos >= next_face_change
3520 && (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f)))
1c9241f5
KH
3521 {
3522 int limit = pos + 50;
3523
1c9241f5
KH
3524 current_face = compute_char_face (f, w, pos,
3525 region_beg, region_end,
3526 &next_face_change, limit, 0);
3527 }
f6fd109b
RS
3528#endif
3529
67481ae5
RS
3530 /* Compute the next place we need to stop
3531 and do something special; set PAUSE. */
3532
ca26e1c8 3533 pause = ZV;
1c2250c2 3534
ca26e1c8
KH
3535 if (pos < next_boundary && next_boundary < pause)
3536 pause = next_boundary;
1c2250c2
JB
3537 if (pos < next_face_change && next_face_change < pause)
3538 pause = next_face_change;
3539
67481ae5
RS
3540 if (e_t_h < pause)
3541 pause = e_t_h;
3542
31b24551
JB
3543 /* Wouldn't you hate to read the next line to someone over
3544 the phone? */
ae3b1442
KH
3545 if (pos < PT && PT < pause)
3546 pause = PT;
a2889657
JB
3547 if (pos < GPT && GPT < pause)
3548 pause = GPT;
3549
12adba34
RS
3550 /* LIMIT_BYTE is not the same place in the buffer as PAUSE.
3551 It is a limit on valid characters.
3552 We use it to bound STRING_CHAR_AND_LENGTH. */
3553 limit_byte = ZV_BYTE;
3554 if (pos < GPT && GPT_BYTE < limit_byte)
3555 limit_byte = GPT_BYTE;
3556
3557 {
3558 int temp = CHAR_TO_BYTE (pos);
3559 p = BYTE_POS_ADDR (temp);
3560 }
a2889657 3561 }
ca26e1c8 3562
ca26e1c8
KH
3563 if (p1 >= endp)
3564 break;
3565
3566 p1prev = p1;
0d09d1e6 3567 p1_wide_column_end = (GLYPH *) 0;
ca26e1c8 3568
1c9241f5 3569 if (multibyte)
12adba34 3570 c = STRING_CHAR_AND_LENGTH (p, limit_byte - pos_byte, len), p += len;
1c9241f5
KH
3571 else
3572 c = *p++, len = 1;
376b0e59
RS
3573 /* Let a display table override all standard display methods. */
3574 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
3575 {
3576 p1 = copy_part_of_rope (f, p1, leftmargin,
3577 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
3578 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
1c9241f5 3579 current_face, rev_dir_bit);
376b0e59
RS
3580 }
3581 else if (c >= 040 && c < 0177)
a2889657 3582 {
d2f84654 3583 if (p1 >= leftmargin)
1c9241f5 3584 *p1 = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
a2889657
JB
3585 p1++;
3586 }
3587 else if (c == '\n')
3588 {
1842fc1a
RS
3589#if 0
3590 /* Same as p1prev, but after the invis_vector_contents text
3591 (if we have that on this line). */
3592 GLYPH *p1prev_modified;
3593#endif
3594
a2889657 3595 invis = 0;
642eefc6
RS
3596 if (last_invis_skip == pos
3597 && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
3598 invis = 1;
ca26e1c8 3599 while (pos + 1 < ZV
a2889657 3600 && selective > 0
12adba34 3601 && indented_beyond_p (pos + 1, pos_byte + 1, selective))
a2889657 3602 {
12adba34
RS
3603 int opoint = PT, opoint_byte = PT_BYTE;
3604
a2889657 3605 invis = 1;
9ce37c9d 3606 INC_BOTH (pos, pos_byte);
12adba34 3607 scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
b5231eda 3608 pos = PT, pos_byte = PT_BYTE;
12adba34
RS
3609 if (FETCH_BYTE (pos_byte - 1) == '\n')
3610 {
3611 pos--;
3612 pos_byte--;
3613 }
3614 SET_PT_BOTH (opoint, opoint_byte);
a2889657 3615 }
d2f84654 3616 if (invis && selective_rlen > 0 && p1 >= leftmargin)
a2889657 3617 {
1842fc1a
RS
3618#if 0
3619 GLYPH *cs, *csend;
3620
3621 cs = charstart + (p1 - p1start);
3622#endif
3623
a2889657 3624 p1 += selective_rlen;
d2f84654 3625 if (p1 - leftmargin > width)
a2889657 3626 p1 = endp;
1842fc1a
RS
3627
3628#if 0 /* This needs more work; charstarts needs to record
3629 both whether a position ho;ds an ellipsis character
3630 and what buffer position it corresponds to. */
3631 csend = charstart + (p1 - p1start);
3632 while (cs != csend)
3633 *cs++ = -2;
3634 /* The idea is to use p1prev_modified instead of p1prev
3635 in the loop below over p2x. */
3636 p1prev_modified = p1;
3637#endif
3638
278feba9 3639 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c9241f5 3640 (p1 - p1prev), current_face, rev_dir_bit);
a2889657 3641 }
545e04f6
KH
3642
3643 /* Update charstarts for the newline that ended this line. */
3644 /* Do nothing here for a char that's entirely off the left edge
3645 or if it starts at the right edge. */
3646 if (p1 >= leftmargin && p1prev != endp)
3647 {
3648 /* Store the newline's position into charstarts
3649 for the column where the newline starts.
3650 Store -1 for the rest of the glyphs it occupies. */
3651 int *p2x = &charstart[(p1prev < leftmargin
3652 ? leftmargin : p1prev)
3653 - p1start];
3654 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3655
3656 *p2x++ = pos;
3657 while (p2x < p2)
3658 *p2x++ = -1;
3659 }
1842fc1a
RS
3660#ifdef HAVE_FACES
3661 /* Draw the face of the newline character as extending all the
3662 way to the end of the frame line. */
3663 if (current_face)
3664 {
3665 if (p1 < leftmargin)
3666 p1 = leftmargin;
3667 while (p1 < endp)
3668 *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
3669 }
3670#endif
545e04f6 3671
68a37fa8 3672 break;
a2889657
JB
3673 }
3674 else if (c == '\t')
3675 {
3676 do
3677 {
d2f84654 3678 if (p1 >= leftmargin && p1 < endp)
1c9241f5 3679 *p1 = MAKE_GLYPH (f, ' ', current_face) | rev_dir_bit;
a2889657
JB
3680 p1++;
3681 }
d2f84654 3682 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
a2889657
JB
3683 % tab_width);
3684 }
6e8290aa 3685 else if (c == Ctl ('M') && selective == -1)
a2889657 3686 {
12adba34
RS
3687 int opoint = PT, opoint_byte = PT_BYTE;
3688 scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
3689 pos = PT, pos_byte = PT_BYTE;
3690 SET_PT_BOTH (opoint, opoint_byte);
3691
3692 if (FETCH_BYTE (pos_byte - 1) == '\n')
3693 pos--, pos_byte--;
a2889657
JB
3694 if (selective_rlen > 0)
3695 {
3696 p1 += selective_rlen;
d2f84654 3697 if (p1 - leftmargin > width)
a2889657 3698 p1 = endp;
278feba9 3699 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
1c9241f5 3700 (p1 - p1prev), current_face, rev_dir_bit);
a2889657 3701 }
87485d6f 3702#ifdef HAVE_FACES
3c5c35c5
JB
3703 /* Draw the face of the newline character as extending all the
3704 way to the end of the frame line. */
3705 if (current_face)
1105ff20
KH
3706 {
3707 if (p1 < leftmargin)
3708 p1 = leftmargin;
3709 while (p1 < endp)
1c9241f5 3710 *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
1105ff20 3711 }
3c5c35c5 3712#endif
545e04f6
KH
3713
3714 /* Update charstarts for the ^M that ended this line. */
3715 /* Do nothing here for a char that's entirely off the left edge
3716 or if it starts at the right edge. */
3717 if (p1 >= leftmargin && p1prev != endp)
3718 {
3719 /* Store the newline's position into charstarts
3720 for the column where the newline starts.
3721 Store -1 for the rest of the glyphs it occupies. */
3722 int *p2x = &charstart[(p1prev < leftmargin
3723 ? leftmargin : p1prev)
3724 - p1start];
3725 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3726
3727 *p2x++ = pos;
3728 while (p2x < p2)
3729 *p2x++ = -1;
3730 }
68a37fa8 3731 break;
a2889657 3732 }
a2889657
JB
3733 else if (c < 0200 && ctl_arrow)
3734 {
d2f84654 3735 if (p1 >= leftmargin)
e57bca5d
KH
3736 *p1 = (fix_glyph
3737 (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
3738 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
3739 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
3740 current_face)
1c9241f5 3741 | rev_dir_bit);
a2889657 3742 p1++;
d2f84654 3743 if (p1 >= leftmargin && p1 < endp)
1c9241f5 3744 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face) | rev_dir_bit;
a2889657
JB
3745 p1++;
3746 }
1c9241f5
KH
3747 else
3748 {
a2c983d5
KH
3749 /* C is a multibyte character or a character to be displayed
3750 by octral form. */
3751 int remaining_bytes = len;
1c9241f5 3752
a2c983d5 3753 if (c >= 0400)
1c9241f5 3754 {
a2c983d5
KH
3755 /* C is a multibyte character. */
3756 int charset = CHAR_CHARSET (c);
3757 int columns = (charset == CHARSET_COMPOSITION
3758 ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
3759 : CHARSET_WIDTH (charset));
3760 GLYPH g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
3761
3762 while (columns--)
3763 {
3764 if (p1 >= leftmargin && p1 < endp)
3765 *p1 = g, g |= GLYPH_MASK_PADDING;
3766 p1++;
3767 }
3768 p1_wide_column_end = p1;
3769 remaining_bytes -= CHARSET_BYTES (charset);
1c9241f5 3770 }
0d09d1e6 3771
a2c983d5 3772 while (remaining_bytes > 0)
0d09d1e6 3773 {
a2c983d5
KH
3774 c = *(p - remaining_bytes--);
3775
3776 if (p1 >= leftmargin && p1 < endp)
3777 *p1 = (fix_glyph
3778 (f,
3779 (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
3780 && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
3781 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
3782 current_face)
3783 | rev_dir_bit);
3784 p1++;
3785 if (p1 >= leftmargin && p1 < endp)
3786 *p1 = (MAKE_GLYPH (f, (c >> 6) + '0', current_face)
3787 | rev_dir_bit);
3788 p1++;
3789 if (p1 >= leftmargin && p1 < endp)
3790 *p1 = (MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face)
3791 | rev_dir_bit);
3792 p1++;
3793 if (p1 >= leftmargin && p1 < endp)
3794 *p1 = (MAKE_GLYPH (f, (7 & c) + '0', current_face)
3795 | rev_dir_bit);
3796 p1++;
0d09d1e6 3797 }
1c9241f5 3798 }
31b24551 3799
ca26e1c8 3800 prevpos = pos;
12adba34
RS
3801 prevpos_byte = pos_byte;
3802 pos++;
3803 pos_byte += len;
545e04f6
KH
3804
3805 /* Update charstarts for the character just output. */
3806
3807 /* Do nothing here for a char that's entirely off the left edge. */
3808 if (p1 >= leftmargin)
3809 {
3810 /* Store the char's position into charstarts
3811 for the first glyph occupied by this char.
3812 Store -1 for the rest of the glyphs it occupies. */
3813 if (p1 != p1prev)
3814 {
3815 int *p2x = &charstart[(p1prev < leftmargin
3816 ? leftmargin : p1prev)
3817 - p1start];
3818 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3819
3820 if (p2x < p2)
3821 *p2x++ = prevpos;
3822 while (p2x < p2)
3823 *p2x++ = -1;
3824 }
3825 }
a2889657
JB
3826 }
3827
3828 val.hpos = - XINT (w->hscroll);
3829 if (val.hpos)
3830 val.hpos++;
3831
3832 val.vpos = 1;
3833
3834 lastpos = pos;
12adba34 3835 lastpos_byte = pos_byte;
a2889657 3836
efc63ef0
RS
3837 /* Store 0 in this charstart line for the positions where
3838 there is no character. But do leave what was recorded
3839 for the character that ended the line. */
85bcef6c
RS
3840 /* Add 1 in the endtest to compensate for the fact that ENDP was
3841 made from WIDTH, which is 1 less than the window's actual
3842 internal width. */
a007eef6
RS
3843 i = p1 - p1start + 1;
3844 if (p1 < leftmargin)
3845 i += leftmargin - p1;
3846 for (; i < endp - p1start + 1; i++)
efc63ef0
RS
3847 charstart[i] = 0;
3848
a2889657
JB
3849 /* Handle continuation in middle of a character */
3850 /* by backing up over it */
3851 if (p1 > endp)
3852 {
5fcbb24d
JB
3853 /* Don't back up if we never actually displayed any text.
3854 This occurs when the minibuffer prompt takes up the whole line. */
3855 if (p1prev)
3856 {
1c9241f5
KH
3857 /* Start the next line with that same character whose
3858 character code is C and the length of multi-byte form is
3859 LEN. */
3860 pos = prevpos;
12adba34 3861 pos_byte = prevpos_byte;
1c9241f5 3862
0d09d1e6
KH
3863 if (p1_wide_column_end < endp)
3864 /* As ENDP is not in the middle of wide-column character,
3865 we can break the line at ENDP and start from the middle
3866 column in the next line. So, adjust VAL.HPOS to skip
3867 the columns output on this line. */
1c9241f5
KH
3868 val.hpos += p1prev - endp;
3869 else
3870 {
0d09d1e6
KH
3871 /* We displayed a wide-column character at around ENDP.
3872 Since we can't broke it in the middle, the whole
3873 character should be driven into the next line. */
1c9241f5
KH
3874 /* As the result, the actual columns occupied by the
3875 text on this line is less than WIDTH. VAL.TAB_OFFSET
3876 must be adjusted. */
3877 taboffset = taboffset + (p1prev - endp);
3878 /* Let's fill unused columns with TRUNCATOR or CONTINUER. */
3879 {
3880 GLYPH g = fix_glyph (f, truncate ? truncator : continuer, 0);
3881 while (p1prev < endp)
3882 *p1prev++ = g;
3883 }
3884 /* If POINT is at POS, cursor should not on this line. */
3885 lastpos = pos;
12adba34 3886 lastpos_byte = pos_byte;
1c9241f5
KH
3887 if (PT == pos)
3888 cursor_vpos = -1;
3889 }
5fcbb24d
JB
3890 }
3891
a2889657
JB
3892 /* Keep in this line everything up to the continuation column. */
3893 p1 = endp;
3894 }
3895
3896 /* Finish deciding which character to start the next line on,
3897 and what hpos to start it at.
3898 Also set `lastpos' to the last position which counts as "on this line"
3899 for cursor-positioning. */
3900
3901 if (pos < ZV)
3902 {
12adba34 3903 if (FETCH_BYTE (pos_byte) == '\n')
dd5f6267 3904 {
12adba34
RS
3905 int opoint = PT, opoint_byte = PT_BYTE;
3906
dd5f6267 3907 /* If stopped due to a newline, start next line after it */
12adba34
RS
3908 SET_PT_BOTH (pos + 1, pos_byte + 1);
3909
1c9241f5 3910 val.tab_offset = 0;
dd5f6267
KH
3911 /* Check again for hidden lines, in case the newline occurred exactly
3912 at the right margin. */
12adba34
RS
3913 while (PT < ZV && selective > 0
3914 && indented_beyond_p (PT, PT_BYTE, selective))
3915 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
3916
3917 pos = PT, pos_byte = PT_BYTE;
3918 SET_PT_BOTH (opoint, opoint_byte);
dd5f6267 3919 }
a2889657
JB
3920 else
3921 /* Stopped due to right margin of window */
3922 {
3923 if (truncate)
3924 {
12adba34
RS
3925 int opoint = PT, opoint_byte = PT_BYTE;
3926
3927 SET_PT_BOTH (pos, pos_byte);
278feba9 3928 *p1++ = fix_glyph (f, truncator, 0);
a2889657
JB
3929 /* Truncating => start next line after next newline,
3930 and point is on this line if it is before the newline,
3931 and skip none of first char of next line */
dd5f6267 3932 do
12adba34
RS
3933 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
3934 while (PT < ZV && selective > 0
3935 && indented_beyond_p (PT, PT_BYTE, selective));
3936 pos = PT, pos_byte = PT_BYTE;
a2889657 3937 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
12adba34 3938 SET_PT_BOTH (opoint, opoint_byte);
a2889657 3939
12adba34
RS
3940 lastpos = pos - (FETCH_BYTE (pos_byte - 1) == '\n');
3941 lastpos_byte = CHAR_TO_BYTE (lastpos);
1c9241f5 3942 val.tab_offset = 0;
a2889657
JB
3943 }
3944 else
3945 {
278feba9 3946 *p1++ = fix_glyph (f, continuer, 0);
a2889657 3947 val.vpos = 0;
93fdf93b 3948 DEC_BOTH (lastpos, lastpos_byte);
1c9241f5 3949 val.tab_offset = taboffset + width;
a2889657
JB
3950 }
3951 }
3952 }
1c9241f5
KH
3953 else
3954 val.tab_offset = 0;
a2889657
JB
3955
3956 /* If point is at eol or in invisible text at eol,
44fa5b1e 3957 record its frame location now. */
a2889657 3958
ae3b1442 3959 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
a2889657
JB
3960 {
3961 cursor_vpos = vpos;
d2f84654 3962 cursor_hpos = p1 - leftmargin;
a2889657
JB
3963 }
3964
3965 if (cursor_vpos == vpos)
3966 {
3967 if (cursor_hpos < 0) cursor_hpos = 0;
3968 if (cursor_hpos > width) cursor_hpos = width;
73f194f1 3969 cursor_hpos += WINDOW_LEFT_MARGIN (w);
44fa5b1e 3970 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
a2889657 3971 {
b5bbc9a5
KH
3972 if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
3973 && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
3974 {
3975 FRAME_CURSOR_Y (f) = cursor_vpos;
3976 FRAME_CURSOR_X (f) = cursor_hpos;
3977 }
a2889657
JB
3978
3979 if (w == XWINDOW (selected_window))
3980 {
3981 /* Line is not continued and did not start
3982 in middle of character */
73f194f1 3983 if ((hpos - WINDOW_LEFT_MARGIN (w)
a2889657
JB
3984 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
3985 && val.vpos)
3986 {
3987 this_line_bufpos = start;
3988 this_line_buffer = current_buffer;
3989 this_line_vpos = cursor_vpos;
89819bdd 3990 this_line_start_hpos = hpos - WINDOW_LEFT_MARGIN (w);
a2889657
JB
3991 this_line_endpos = Z - lastpos;
3992 }
3993 else
3994 this_line_bufpos = 0;
3995 }
3996 }
3997 }
3998
3999 /* If hscroll and line not empty, insert truncation-at-left marker */
4000 if (hscroll && lastpos != start)
4001 {
1c9241f5
KH
4002 GLYPH g = fix_glyph (f, truncator, 0);
4003 *leftmargin = g;
d2f84654
RS
4004 if (p1 <= leftmargin)
4005 p1 = leftmargin + 1;
1c9241f5
KH
4006 else /* MULE: it may be a wide-column character */
4007 {
4008 p1prev = leftmargin + 1;
4009 while (p1prev < p1 && *p1prev & GLYPH_MASK_PADDING)
4010 *p1prev++ = g;
4011 }
a2889657
JB
4012 }
4013
73f194f1 4014 if (!WINDOW_RIGHTMOST_P (w))
a2889657
JB
4015 {
4016 endp++;
d2f84654 4017 if (p1 < leftmargin) p1 = leftmargin;
a2889657 4018 while (p1 < endp) *p1++ = SPACEGLYPH;
b1d1124b 4019
88f22aff
JB
4020 /* Don't draw vertical bars if we're using scroll bars. They're
4021 covered up by the scroll bars, and it's distracting to see
4022 them when the scroll bar windows are flickering around to be
b1d1124b 4023 reconfigured. */
73f194f1 4024 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
75d13c64
KH
4025 {
4026 int i;
4027 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
4028 *p1++ = SPACEGLYPH;
4029 }
73f194f1 4030 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
75d13c64 4031 *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
8bb6ca14 4032 ? XINT (DISP_BORDER_GLYPH (dp))
75d13c64 4033 : '|');
a2889657
JB
4034 }
4035 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
4036 p1 - desired_glyphs->glyphs[vpos]);
4037 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
4038
4039 /* If the start of this line is the overlay arrow-position,
4040 then put the arrow string into the display-line. */
4041
e24c997d 4042 if (MARKERP (Voverlay_arrow_position)
a2889657
JB
4043 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
4044 && start == marker_position (Voverlay_arrow_position)
e24c997d 4045 && STRINGP (Voverlay_arrow_string)
a2889657
JB
4046 && ! overlay_arrow_seen)
4047 {
0a9dc68b 4048 int i, i_byte;
a2889657 4049 int len = XSTRING (Voverlay_arrow_string)->size;
142be3dd 4050 int arrow_end;
a2889657 4051
b1d1124b
JB
4052 if (len > width)
4053 len = width;
212e4f87
RS
4054
4055 /* If the arrow string has text props, obey them when displaying. */
4056 for (i = 0, i_byte = 0; i < len; )
c4628384 4057 {
212e4f87
RS
4058 int c;
4059 Lisp_Object face, ilisp;
4060 int newface;
4061 int idx = i;
c4628384 4062
212e4f87
RS
4063 if (STRING_MULTIBYTE (Voverlay_arrow_string))
4064 FETCH_STRING_CHAR_ADVANCE (c, Voverlay_arrow_string, i, i_byte);
4065 else
4066 c = XSTRING (Voverlay_arrow_string)->data[i++];
0a9dc68b 4067
212e4f87
RS
4068 XSETFASTINT (ilisp, i);
4069#ifdef HAVE_FACES
4070 if (FRAME_WINDOW_P (f))
4071 {
c4628384
RS
4072 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
4073 newface = compute_glyph_face_1 (f, face, 0);
212e4f87 4074 c = FAST_MAKE_GLYPH (c, newface);
c4628384 4075 }
87485d6f 4076#endif /* HAVE_FACES */
212e4f87 4077 leftmargin[idx] = c;
c4628384 4078 }
142be3dd
JB
4079
4080 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
d2f84654 4081 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
142be3dd
JB
4082 if (desired_glyphs->used[vpos] < arrow_end)
4083 desired_glyphs->used[vpos] = arrow_end;
a2889657
JB
4084
4085 overlay_arrow_seen = 1;
4086 }
4087
4088 val.bufpos = pos;
12adba34 4089 val.bytepos = pos_byte;
0f9c0ff0 4090 val.ovstring_chars_done = ovstr_done;
a2889657
JB
4091 val_display_text_line = val;
4092 return &val_display_text_line;
4093}
4094\f
7ce2c095
RS
4095/* Redisplay the menu bar in the frame for window W. */
4096
4097static void
4098display_menu_bar (w)
4099 struct window *w;
4100{
4101 Lisp_Object items, tail;
4102 register int vpos = 0;
4103 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
eeb4f710 4104 int maxendcol = FRAME_WIDTH (f);
7ce2c095 4105 int hpos = 0;
8351baf2 4106 int i;
7ce2c095 4107
dc937613 4108#ifdef HAVE_NTGUI
d129c4c2
KH
4109 if (!NILP (Vwindow_system))
4110 return;
dc937613
RS
4111#endif
4112
4113#ifdef USE_X_TOOLKIT
d3413a53 4114 if (FRAME_X_P (f))
7ce2c095 4115 return;
dc937613 4116#endif /* USE_X_TOOLKIT */
7ce2c095
RS
4117
4118 get_display_line (f, vpos, 0);
4119
8351baf2 4120 items = FRAME_MENU_BAR_ITEMS (f);
469937ac 4121 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 4122 {
8351baf2
RS
4123 Lisp_Object pos, string;
4124 string = XVECTOR (items)->contents[i + 1];
4125 if (NILP (string))
4126 break;
2d66ad19 4127
469937ac 4128 XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
7ce2c095
RS
4129
4130 if (hpos < maxendcol)
11c52c4f 4131 hpos = display_string (w, vpos,
7ce2c095 4132 XSTRING (string)->data,
fc932ac6 4133 STRING_BYTES (XSTRING (string)),
0a9dc68b
RS
4134 hpos, 0, 0, hpos, maxendcol,
4135 STRING_MULTIBYTE (string));
6b1bbc46 4136 /* Put a space between items. */
2d66ad19
RS
4137 if (hpos < maxendcol)
4138 {
6b1bbc46 4139 int hpos1 = hpos + 1;
278feba9 4140 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
a3788d53 4141 min (hpos1, maxendcol), maxendcol, 0);
2d66ad19 4142 }
7ce2c095
RS
4143 }
4144
4145 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
4146 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2d66ad19
RS
4147
4148 /* Fill out the line with spaces. */
4149 if (maxendcol > hpos)
a3788d53 4150 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol, 0);
db6f348c
JB
4151
4152 /* Clear the rest of the lines allocated to the menu bar. */
4153 vpos++;
4154 while (vpos < FRAME_MENU_BAR_LINES (f))
4155 get_display_line (f, vpos++, 0);
7ce2c095
RS
4156}
4157\f
a2889657
JB
4158/* Display the mode line for window w */
4159
4160static void
4161display_mode_line (w)
4162 struct window *w;
4163{
4164 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
73f194f1
RS
4165 register int left = WINDOW_LEFT_MARGIN (w);
4166 register int right = WINDOW_RIGHT_MARGIN (w);
44fa5b1e 4167 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
a2889657 4168
aa6d10fa 4169 line_number_displayed = 0;
155ef550 4170 w->column_number_displayed = Qnil;
aa6d10fa 4171
44fa5b1e 4172 get_display_line (f, vpos, left);
03b294dc
RS
4173
4174 /* Temporarily make frame F's kboard the current kboard
4175 so that kboard-local variables in the mode_line_format
4176 will get the right values. */
4177 push_frame_kboard (f);
4178
4179 display_mode_element (w, vpos, left, 0, right, right,
4180 current_buffer->mode_line_format);
4181
4182 pop_frame_kboard ();
4183
44fa5b1e 4184 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
a2889657 4185
73f194f1
RS
4186 /* Put the mode line in inverse video.
4187 Use faces if possible, since that lets us handle
4188 partial-width windows and avoid inverting the scroll bar columns. */
87485d6f 4189#ifdef HAVE_FACES
73f194f1 4190 if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
d7eb09a0
RS
4191 {
4192 /* For a partial width window, explicitly set face of each glyph. */
4193 int i;
1c9241f5 4194 unsigned int padding;
d7eb09a0
RS
4195 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
4196 for (i = left; i < right; ++i)
1c9241f5
KH
4197 {
4198 padding = ptr[i] & GLYPH_MASK_PADDING;
4199 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1) | padding;
4200 }
d7eb09a0 4201 }
010a899e 4202 else
4cdc65eb 4203#endif
73f194f1
RS
4204
4205 /* Make the mode line inverse video if the entire line
4206 is made of mode lines.
4207 I.e. if this window is full width,
4208 or if it is the child of a full width window
4209 (which implies that that window is split side-by-side
4210 and the rest of this line is mode lines of the sibling windows). */
010a899e
KH
4211 if (WINDOW_FULL_WIDTH_P (w)
4212 || WINDOW_FULL_WIDTH_P (XWINDOW (w->parent)))
73f194f1 4213 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
a2889657
JB
4214}
4215
4216/* Contribute ELT to the mode line for window W.
4217 How it translates into text depends on its data type.
4218
4219 VPOS is the position of the mode line being displayed.
4220
44fa5b1e 4221 HPOS is the position (absolute on frame) where this element's text
a2889657
JB
4222 should start. The output is truncated automatically at the right
4223 edge of window W.
4224
4225 DEPTH is the depth in recursion. It is used to prevent
4226 infinite recursion here.
4227
4228 MINENDCOL is the hpos before which the element may not end.
4229 The element is padded at the right with spaces if nec
4230 to reach this column.
4231
4232 MAXENDCOL is the hpos past which this element may not extend.
4233 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
4234 (This is necessary to make nested padding and truncation work.)
4235
4236 Returns the hpos of the end of the text generated by ELT.
4237 The next element will receive that value as its HPOS arg,
4238 so as to concatenate the elements. */
4239
4240static int
4241display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
4242 struct window *w;
4243 register int vpos, hpos;
4244 int depth;
4245 int minendcol;
4246 register int maxendcol;
4247 register Lisp_Object elt;
4248{
4249 tail_recurse:
4250 if (depth > 10)
4251 goto invalid;
4252
4253 depth++;
4254
0220c518 4255 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
4256 {
4257 case Lisp_String:
4258 {
4259 /* A string: output it and check for %-constructs within it. */
4260 register unsigned char c;
4261 register unsigned char *this = XSTRING (elt)->data;
4262
4263 while (hpos < maxendcol && *this)
4264 {
4265 unsigned char *last = this;
4266 while ((c = *this++) != '\0' && c != '%')
4267 ;
4268 if (this - 1 != last)
4269 {
4270 register int lim = --this - last + hpos;
d39b6696
KH
4271 if (frame_title_ptr)
4272 hpos = store_frame_title (last, hpos, min (lim, maxendcol));
4273 else
4274 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
0a9dc68b
RS
4275 hpos, min (lim, maxendcol),
4276 STRING_MULTIBYTE (elt));
a2889657
JB
4277 }
4278 else /* c == '%' */
4279 {
766525bc 4280 register int minendcol;
a2889657
JB
4281 register int spec_width = 0;
4282
4283 /* We can't allow -ve args due to the "%-" construct */
4284 /* Argument specifies minwidth but not maxwidth
4285 (maxwidth can be specified by
4286 (<negative-number> . <stuff>) mode-line elements) */
4287
4288 while ((c = *this++) >= '0' && c <= '9')
4289 {
4290 spec_width = spec_width * 10 + (c - '0');
4291 }
4292
766525bc
RS
4293 minendcol = hpos + spec_width;
4294 if (minendcol > maxendcol)
4295 {
4296 spec_width = maxendcol - hpos;
4297 minendcol = maxendcol;
4298 }
a2889657
JB
4299
4300 if (c == 'M')
4301 hpos = display_mode_element (w, vpos, hpos, depth,
4302 spec_width, maxendcol,
4303 Vglobal_mode_string);
4304 else if (c != 0)
d39b6696 4305 {
766525bc
RS
4306 char *spec = decode_mode_spec (w, c, spec_width,
4307 maxendcol - hpos);
d39b6696 4308 if (frame_title_ptr)
766525bc 4309 hpos = store_frame_title (spec, minendcol, maxendcol);
d39b6696
KH
4310 else
4311 hpos = display_string (w, vpos, spec, -1,
4312 hpos, 0, 1,
a3788d53 4313 minendcol, maxendcol, -1);
d39b6696 4314 }
a2889657
JB
4315 }
4316 }
4317 }
4318 break;
4319
4320 case Lisp_Symbol:
4321 /* A symbol: process the value of the symbol recursively
4322 as if it appeared here directly. Avoid error if symbol void.
4323 Special case: if value of symbol is a string, output the string
4324 literally. */
4325 {
4326 register Lisp_Object tem;
4327 tem = Fboundp (elt);
265a9e55 4328 if (!NILP (tem))
a2889657
JB
4329 {
4330 tem = Fsymbol_value (elt);
4331 /* If value is a string, output that string literally:
4332 don't check for % within it. */
e24c997d 4333 if (STRINGP (tem))
d39b6696
KH
4334 {
4335 if (frame_title_ptr)
4336 hpos = store_frame_title (XSTRING (tem)->data,
4337 minendcol, maxendcol);
4338 else
4339 hpos = display_string (w, vpos, XSTRING (tem)->data,
fc932ac6 4340 STRING_BYTES (XSTRING (tem)),
0a9dc68b
RS
4341 hpos, 0, 1, minendcol, maxendcol,
4342 STRING_MULTIBYTE (tem));
d39b6696 4343 }
a2889657
JB
4344 /* Give up right away for nil or t. */
4345 else if (!EQ (tem, elt))
4346 { elt = tem; goto tail_recurse; }
4347 }
4348 }
4349 break;
4350
4351 case Lisp_Cons:
4352 {
4353 register Lisp_Object car, tem;
4354
4355 /* A cons cell: three distinct cases.
4356 If first element is a string or a cons, process all the elements
4357 and effectively concatenate them.
4358 If first element is a negative number, truncate displaying cdr to
4359 at most that many characters. If positive, pad (with spaces)
4360 to at least that many characters.
4361 If first element is a symbol, process the cadr or caddr recursively
4362 according to whether the symbol's value is non-nil or nil. */
4363 car = XCONS (elt)->car;
e24c997d 4364 if (SYMBOLP (car))
a2889657
JB
4365 {
4366 tem = Fboundp (car);
4367 elt = XCONS (elt)->cdr;
e24c997d 4368 if (!CONSP (elt))
a2889657
JB
4369 goto invalid;
4370 /* elt is now the cdr, and we know it is a cons cell.
4371 Use its car if CAR has a non-nil value. */
265a9e55 4372 if (!NILP (tem))
a2889657
JB
4373 {
4374 tem = Fsymbol_value (car);
265a9e55 4375 if (!NILP (tem))
a2889657
JB
4376 { elt = XCONS (elt)->car; goto tail_recurse; }
4377 }
4378 /* Symbol's value is nil (or symbol is unbound)
4379 Get the cddr of the original list
4380 and if possible find the caddr and use that. */
4381 elt = XCONS (elt)->cdr;
265a9e55 4382 if (NILP (elt))
a2889657 4383 break;
e24c997d 4384 else if (!CONSP (elt))
a2889657
JB
4385 goto invalid;
4386 elt = XCONS (elt)->car;
4387 goto tail_recurse;
4388 }
e24c997d 4389 else if (INTEGERP (car))
a2889657
JB
4390 {
4391 register int lim = XINT (car);
4392 elt = XCONS (elt)->cdr;
4393 if (lim < 0)
4394 /* Negative int means reduce maximum width.
4395 DO NOT change MINENDCOL here!
4396 (20 -10 . foo) should truncate foo to 10 col
4397 and then pad to 20. */
4398 maxendcol = min (maxendcol, hpos - lim);
4399 else if (lim > 0)
4400 {
4401 /* Padding specified. Don't let it be more than
4402 current maximum. */
4403 lim += hpos;
4404 if (lim > maxendcol)
4405 lim = maxendcol;
4406 /* If that's more padding than already wanted, queue it.
4407 But don't reduce padding already specified even if
4408 that is beyond the current truncation point. */
4409 if (lim > minendcol)
4410 minendcol = lim;
4411 }
4412 goto tail_recurse;
4413 }
e24c997d 4414 else if (STRINGP (car) || CONSP (car))
a2889657
JB
4415 {
4416 register int limit = 50;
4417 /* LIMIT is to protect against circular lists. */
e24c997d 4418 while (CONSP (elt) && --limit > 0
a2889657
JB
4419 && hpos < maxendcol)
4420 {
4421 hpos = display_mode_element (w, vpos, hpos, depth,
4422 hpos, maxendcol,
4423 XCONS (elt)->car);
4424 elt = XCONS (elt)->cdr;
4425 }
4426 }
4427 }
4428 break;
4429
4430 default:
4431 invalid:
d39b6696
KH
4432 if (frame_title_ptr)
4433 hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
4434 else
4435 hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
a3788d53 4436 minendcol, maxendcol, 0);
d39b6696 4437 return hpos;
a2889657
JB
4438 }
4439
a2889657 4440 if (minendcol > hpos)
d39b6696
KH
4441 if (frame_title_ptr)
4442 hpos = store_frame_title ("", minendcol, maxendcol);
4443 else
a3788d53
RS
4444 hpos = display_string (w, vpos, "", 0, hpos,
4445 0, 1, minendcol, maxendcol, 0);
a2889657
JB
4446 return hpos;
4447}
4448\f
766525bc
RS
4449/* Write a null-terminated, right justified decimal representation of
4450 the positive integer D to BUF using a minimal field width WIDTH. */
4451
4452static void
4453pint2str (buf, width, d)
4454 register char *buf;
4455 register int width;
4456 register int d;
4457{
4458 register char *p = buf;
4459
4460 if (d <= 0)
4461 *p++ = '0';
4462 else
4463 while (d > 0)
4464 {
4465 *p++ = d % 10 + '0';
4466 d /= 10;
4467 }
4468 for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
4469 *p-- = '\0';
4470 while (p > buf)
4471 {
4472 d = *buf;
4473 *buf++ = *p;
4474 *p-- = d;
4475 }
4476}
4477
1c9241f5
KH
4478/* Set a mnemonic character for CODING_SYSTEM (Lisp symbol) in BUF.
4479 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
4480 type of CODING_SYSTEM. Return updated pointer into BUF. */
4481
4482static char *
4483decode_mode_spec_coding (coding_system, buf, eol_flag)
4484 Lisp_Object coding_system;
4485 register char *buf;
4486 int eol_flag;
4487{
1e1078d6 4488 Lisp_Object val;
916848d8 4489 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
1e1078d6
RS
4490
4491 val = coding_system;
1c9241f5
KH
4492
4493 if (NILP (val)) /* Not yet decided. */
4494 {
916848d8
RS
4495 if (multibyte)
4496 *buf++ = '-';
21e989e3
RS
4497 if (eol_flag)
4498 *buf++ = eol_mnemonic_undecided;
1e1078d6 4499 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
4500 }
4501 else
4502 {
1e1078d6
RS
4503 Lisp_Object eolvalue;
4504
4505 eolvalue = Fget (coding_system, Qeol_type);
4506
1c9241f5 4507 while (!NILP (val) && SYMBOLP (val))
1e1078d6
RS
4508 {
4509 val = Fget (val, Qcoding_system);
4510 if (NILP (eolvalue))
b070c1d7 4511 eolvalue = Fget (val, Qeol_type);
1e1078d6
RS
4512 }
4513
916848d8
RS
4514 if (multibyte)
4515 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
4516
1c9241f5
KH
4517 if (eol_flag)
4518 {
1e1078d6
RS
4519 /* The EOL conversion we are using. */
4520 int eoltype;
4521 /* The EOL conversion that is normal on this system. */
4522
4523 if (NILP (eolvalue)) /* Not yet decided. */
4524 eoltype = eol_mnemonic_undecided;
4525 else if (VECTORP (eolvalue)) /* Not yet decided. */
4526 eoltype = eol_mnemonic_undecided;
4527 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
4528 eoltype = (XFASTINT (eolvalue) == 0
4529 ? eol_mnemonic_unix
4530 : (XFASTINT (eolvalue) == 1
4531 ? eol_mnemonic_dos : eol_mnemonic_mac));
4532
4533 /* Mention the EOL conversion if it is not the usual one. */
4534 *buf++ = eoltype;
1c9241f5
KH
4535 }
4536 }
4537 return buf;
4538}
4539
a2889657 4540/* Return a string for the output of a mode line %-spec for window W,
766525bc
RS
4541 generated by character C. SPEC_WIDTH is the field width when
4542 padding to the left (%c, %l). The value returned from this
4543 function will later be truncated to width MAXWIDTH. */
a2889657 4544
11e82b76
JB
4545static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
4546
a2889657 4547static char *
766525bc 4548decode_mode_spec (w, c, spec_width, maxwidth)
a2889657
JB
4549 struct window *w;
4550 register char c;
766525bc 4551 register int spec_width;
a2889657
JB
4552 register int maxwidth;
4553{
0b67772d 4554 Lisp_Object obj;
44fa5b1e
JB
4555 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
4556 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
d39b6696 4557 struct buffer *b = XBUFFER (w->buffer);
a2889657 4558
0b67772d 4559 obj = Qnil;
44fa5b1e
JB
4560 if (maxwidth > FRAME_WIDTH (f))
4561 maxwidth = FRAME_WIDTH (f);
a2889657
JB
4562
4563 switch (c)
4564 {
1af9f229
RS
4565 case '*':
4566 if (!NILP (b->read_only))
4567 return "%";
4568 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4569 return "*";
4570 return "-";
4571
4572 case '+':
4573 /* This differs from %* only for a modified read-only buffer. */
4574 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4575 return "*";
4576 if (!NILP (b->read_only))
4577 return "%";
4578 return "-";
4579
4580 case '&':
4581 /* This differs from %* in ignoring read-only-ness. */
4582 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4583 return "*";
4584 return "-";
4585
4586 case '%':
4587 return "%";
4588
4589 case '[':
4590 {
4591 int i;
4592 char *p;
4593
4594 if (command_loop_level > 5)
4595 return "[[[... ";
4596 p = decode_mode_spec_buf;
4597 for (i = 0; i < command_loop_level; i++)
4598 *p++ = '[';
4599 *p = 0;
4600 return decode_mode_spec_buf;
4601 }
4602
4603 case ']':
4604 {
4605 int i;
4606 char *p;
4607
4608 if (command_loop_level > 5)
4609 return " ...]]]";
4610 p = decode_mode_spec_buf;
4611 for (i = 0; i < command_loop_level; i++)
4612 *p++ = ']';
4613 *p = 0;
4614 return decode_mode_spec_buf;
4615 }
4616
4617 case '-':
4618 {
4619 register char *p;
4620 register int i;
4621
4622 if (maxwidth < sizeof (lots_of_dashes))
4623 return lots_of_dashes;
4624 else
4625 {
4626 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
4627 *p++ = '-';
4628 *p = '\0';
4629 }
4630 return decode_mode_spec_buf;
4631 }
4632
a2889657 4633 case 'b':
d39b6696 4634 obj = b->name;
a2889657 4635#if 0
fc932ac6 4636 if (maxwidth >= 3 && STRING_BYTES (XSTRING (obj)) > maxwidth)
a2889657
JB
4637 {
4638 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
4639 decode_mode_spec_buf[maxwidth - 1] = '\\';
4640 decode_mode_spec_buf[maxwidth] = '\0';
4641 return decode_mode_spec_buf;
4642 }
4643#endif
4644 break;
4645
1af9f229
RS
4646 case 'c':
4647 {
4648 int col = current_column ();
4649 XSETFASTINT (w->column_number_displayed, col);
766525bc 4650 pint2str (decode_mode_spec_buf, spec_width, col);
1af9f229
RS
4651 return decode_mode_spec_buf;
4652 }
4653
4654 case 'F':
4655 /* %F displays the frame name. */
261bfd0e
EZ
4656 /* Systems that can only display a single frame at a time should
4657 NOT replace the frame name with the (constant) frame title,
4658 since then they won't be able to tell which frame is that. */
4659 if (FRAME_WINDOW_P (f) && !NILP (f->title))
95184b48 4660 return (char *) XSTRING (f->title)->data;
fd8ff63d 4661 if (f->explicit_name || ! FRAME_WINDOW_P (f))
95184b48 4662 return (char *) XSTRING (f->name)->data;
9c6da96f 4663 return "Emacs";
1af9f229 4664
a2889657 4665 case 'f':
d39b6696 4666 obj = b->filename;
a2889657 4667#if 0
265a9e55 4668 if (NILP (obj))
a2889657 4669 return "[none]";
fc932ac6 4670 else if (STRINGP (obj) && STRING_BYTES (XSTRING (obj)) > maxwidth)
a2889657
JB
4671 {
4672 bcopy ("...", decode_mode_spec_buf, 3);
fc932ac6 4673 bcopy (XSTRING (obj)->data + STRING_BYTES (XSTRING (obj)) - maxwidth + 3,
a2889657
JB
4674 decode_mode_spec_buf + 3, maxwidth - 3);
4675 return decode_mode_spec_buf;
4676 }
4677#endif
4678 break;
4679
aa6d10fa
RS
4680 case 'l':
4681 {
12adba34
RS
4682 int startpos = XMARKER (w->start)->charpos;
4683 int startpos_byte = marker_byte_position (w->start);
4684 int line, linepos, linepos_byte, topline;
aa6d10fa
RS
4685 int nlines, junk;
4686 Lisp_Object tem;
4687 int height = XFASTINT (w->height);
4688
4689 /* If we decided that this buffer isn't suitable for line numbers,
4690 don't forget that too fast. */
4691 if (EQ (w->base_line_pos, w->buffer))
766525bc 4692 goto no_value;
5300fd39
RS
4693 /* But do forget it, if the window shows a different buffer now. */
4694 else if (BUFFERP (w->base_line_pos))
4695 w->base_line_pos = Qnil;
aa6d10fa
RS
4696
4697 /* If the buffer is very big, don't waste time. */
d39b6696 4698 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
aa6d10fa
RS
4699 {
4700 w->base_line_pos = Qnil;
4701 w->base_line_number = Qnil;
766525bc 4702 goto no_value;
aa6d10fa
RS
4703 }
4704
4705 if (!NILP (w->base_line_number)
4706 && !NILP (w->base_line_pos)
12adba34 4707 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
4708 {
4709 line = XFASTINT (w->base_line_number);
4710 linepos = XFASTINT (w->base_line_pos);
12adba34 4711 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
4712 }
4713 else
4714 {
4715 line = 1;
d39b6696 4716 linepos = BUF_BEGV (b);
12adba34 4717 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
4718 }
4719
4720 /* Count lines from base line to window start position. */
12adba34
RS
4721 nlines = display_count_lines (linepos, linepos_byte,
4722 startpos_byte,
4723 startpos, &junk);
aa6d10fa
RS
4724
4725 topline = nlines + line;
4726
4727 /* Determine a new base line, if the old one is too close
4728 or too far away, or if we did not have one.
4729 "Too close" means it's plausible a scroll-down would
4730 go back past it. */
d39b6696 4731 if (startpos == BUF_BEGV (b))
aa6d10fa 4732 {
c2213350
KH
4733 XSETFASTINT (w->base_line_number, topline);
4734 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
4735 }
4736 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 4737 || linepos == BUF_BEGV (b))
aa6d10fa 4738 {
d39b6696 4739 int limit = BUF_BEGV (b);
12adba34 4740 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
4741 int position;
4742 int distance = (height * 2 + 30) * 200;
4743
4744 if (startpos - distance > limit)
12adba34
RS
4745 {
4746 limit = startpos - distance;
4747 limit_byte = CHAR_TO_BYTE (limit);
4748 }
aa6d10fa 4749
12adba34
RS
4750 nlines = display_count_lines (startpos, startpos_byte,
4751 limit_byte,
4752 - (height * 2 + 30),
aa6d10fa
RS
4753 &position);
4754 /* If we couldn't find the lines we wanted within
4755 200 chars per line,
4756 give up on line numbers for this window. */
12adba34 4757 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
4758 {
4759 w->base_line_pos = w->buffer;
4760 w->base_line_number = Qnil;
766525bc 4761 goto no_value;
aa6d10fa
RS
4762 }
4763
c2213350 4764 XSETFASTINT (w->base_line_number, topline - nlines);
12adba34 4765 XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
aa6d10fa
RS
4766 }
4767
4768 /* Now count lines from the start pos to point. */
12adba34
RS
4769 nlines = display_count_lines (startpos, startpos_byte,
4770 PT_BYTE, PT, &junk);
aa6d10fa
RS
4771
4772 /* Record that we did display the line number. */
4773 line_number_displayed = 1;
4774
4775 /* Make the string to show. */
766525bc 4776 pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
aa6d10fa 4777 return decode_mode_spec_buf;
766525bc
RS
4778 no_value:
4779 {
4780 char* p = decode_mode_spec_buf;
4781 for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
4782 strcpy (p, "??");
4783 return decode_mode_spec_buf;
4784 }
aa6d10fa
RS
4785 }
4786 break;
4787
a2889657 4788 case 'm':
d39b6696 4789 obj = b->mode_name;
a2889657
JB
4790 break;
4791
4792 case 'n':
d39b6696 4793 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
4794 return " Narrow";
4795 break;
4796
a2889657
JB
4797 case 'p':
4798 {
4799 int pos = marker_position (w->start);
d39b6696 4800 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 4801
d39b6696 4802 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 4803 {
d39b6696 4804 if (pos <= BUF_BEGV (b))
a2889657
JB
4805 return "All";
4806 else
4807 return "Bottom";
4808 }
d39b6696 4809 else if (pos <= BUF_BEGV (b))
a2889657
JB
4810 return "Top";
4811 else
4812 {
3c7d31b9
RS
4813 if (total > 1000000)
4814 /* Do it differently for a large value, to avoid overflow. */
4815 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
4816 else
4817 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
4818 /* We can't normally display a 3-digit number,
4819 so get us a 2-digit number that is close. */
4820 if (total == 100)
4821 total = 99;
4822 sprintf (decode_mode_spec_buf, "%2d%%", total);
4823 return decode_mode_spec_buf;
4824 }
4825 }
4826
8ffcb79f
RS
4827 /* Display percentage of size above the bottom of the screen. */
4828 case 'P':
4829 {
4830 int toppos = marker_position (w->start);
d39b6696
KH
4831 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
4832 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 4833
d39b6696 4834 if (botpos >= BUF_ZV (b))
8ffcb79f 4835 {
d39b6696 4836 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
4837 return "All";
4838 else
4839 return "Bottom";
4840 }
4841 else
4842 {
3c7d31b9
RS
4843 if (total > 1000000)
4844 /* Do it differently for a large value, to avoid overflow. */
4845 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
4846 else
4847 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
4848 /* We can't normally display a 3-digit number,
4849 so get us a 2-digit number that is close. */
4850 if (total == 100)
4851 total = 99;
d39b6696 4852 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
4853 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
4854 else
4855 sprintf (decode_mode_spec_buf, "%2d%%", total);
4856 return decode_mode_spec_buf;
4857 }
4858 }
4859
1af9f229
RS
4860 case 's':
4861 /* status of process */
4862 obj = Fget_buffer_process (w->buffer);
4863 if (NILP (obj))
4864 return "no process";
4865#ifdef subprocesses
4866 obj = Fsymbol_name (Fprocess_status (obj));
4867#endif
4868 break;
d39b6696 4869
1af9f229
RS
4870 case 't': /* indicate TEXT or BINARY */
4871#ifdef MODE_LINE_BINARY_TEXT
4872 return MODE_LINE_BINARY_TEXT (b);
4873#else
4874 return "T";
4875#endif
1c9241f5
KH
4876
4877 case 'z':
4878 /* coding-system (not including end-of-line format) */
4879 case 'Z':
4880 /* coding-system (including end-of-line type) */
4881 {
4882 int eol_flag = (c == 'Z');
539b4d41 4883 char *p = decode_mode_spec_buf;
1c9241f5 4884
d30e754b 4885 if (! FRAME_WINDOW_P (f))
1c9241f5 4886 {
11c52c4f
RS
4887 /* No need to mention EOL here--the terminal never needs
4888 to do EOL conversion. */
4889 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
4890 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 4891 }
f13c925f 4892 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 4893 p, eol_flag);
f13c925f 4894
11c52c4f 4895#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
4896#ifdef subprocesses
4897 obj = Fget_buffer_process (Fcurrent_buffer ());
4898 if (PROCESSP (obj))
4899 {
4900 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
4901 p, eol_flag);
4902 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
4903 p, eol_flag);
4904 }
4905#endif /* subprocesses */
11c52c4f 4906#endif /* 0 */
1c9241f5
KH
4907 *p = 0;
4908 return decode_mode_spec_buf;
4909 }
a2889657 4910 }
d39b6696 4911
e24c997d 4912 if (STRINGP (obj))
a2889657
JB
4913 return (char *) XSTRING (obj)->data;
4914 else
4915 return "";
4916}
59b49f63 4917\f
12adba34
RS
4918/* Count up to COUNT lines starting from START / START_BYTE.
4919 But don't go beyond LIMIT_BYTE.
4920 Return the number of lines thus found (always nonnegative).
59b49f63 4921
12adba34 4922 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
4923
4924static int
12adba34
RS
4925display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
4926 int start, start_byte, limit_byte, count;
4927 int *byte_pos_ptr;
59b49f63 4928{
59b49f63
RS
4929 register unsigned char *cursor;
4930 unsigned char *base;
4931
4932 register int ceiling;
4933 register unsigned char *ceiling_addr;
12adba34 4934 int orig_count = count;
59b49f63
RS
4935
4936 /* If we are not in selective display mode,
4937 check only for newlines. */
12adba34
RS
4938 int selective_display = (!NILP (current_buffer->selective_display)
4939 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
4940
4941 if (count > 0)
12adba34
RS
4942 {
4943 while (start_byte < limit_byte)
4944 {
4945 ceiling = BUFFER_CEILING_OF (start_byte);
4946 ceiling = min (limit_byte - 1, ceiling);
4947 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
4948 base = (cursor = BYTE_POS_ADDR (start_byte));
4949 while (1)
4950 {
4951 if (selective_display)
4952 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
4953 ;
4954 else
4955 while (*cursor != '\n' && ++cursor != ceiling_addr)
4956 ;
4957
4958 if (cursor != ceiling_addr)
4959 {
4960 if (--count == 0)
4961 {
4962 start_byte += cursor - base + 1;
4963 *byte_pos_ptr = start_byte;
4964 return orig_count;
4965 }
4966 else
4967 if (++cursor == ceiling_addr)
4968 break;
4969 }
4970 else
4971 break;
4972 }
4973 start_byte += cursor - base;
4974 }
4975 }
59b49f63
RS
4976 else
4977 {
12adba34
RS
4978 while (start_byte > limit_byte)
4979 {
4980 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
4981 ceiling = max (limit_byte, ceiling);
4982 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
4983 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
4984 while (1)
4985 {
12adba34
RS
4986 if (selective_display)
4987 while (--cursor != ceiling_addr
4988 && *cursor != '\n' && *cursor != 015)
4989 ;
4990 else
4991 while (--cursor != ceiling_addr && *cursor != '\n')
4992 ;
4993
59b49f63
RS
4994 if (cursor != ceiling_addr)
4995 {
4996 if (++count == 0)
4997 {
12adba34
RS
4998 start_byte += cursor - base + 1;
4999 *byte_pos_ptr = start_byte;
5000 /* When scanning backwards, we should
5001 not count the newline posterior to which we stop. */
5002 return - orig_count - 1;
59b49f63
RS
5003 }
5004 }
5005 else
5006 break;
5007 }
12adba34
RS
5008 /* Here we add 1 to compensate for the last decrement
5009 of CURSOR, which took it past the valid range. */
5010 start_byte += cursor - base + 1;
59b49f63
RS
5011 }
5012 }
5013
12adba34 5014 *byte_pos_ptr = limit_byte;
aa6d10fa 5015
12adba34
RS
5016 if (count < 0)
5017 return - orig_count + count;
5018 return orig_count - count;
aa6d10fa 5019
12adba34 5020}
a2889657
JB
5021\f
5022/* Display STRING on one line of window W, starting at HPOS.
5023 Display at position VPOS. Caller should have done get_display_line.
11e82b76 5024 If VPOS == -1, display it as the current frame's title.
90adcf20 5025 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
a2889657
JB
5026
5027 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
5028
5029 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
5030 MAXCOL is the last column ok to end at. Truncate here.
5031 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
44fa5b1e 5032 Both count from the left edge of the frame, as does HPOS.
a2889657
JB
5033 The right edge of W is an implicit maximum.
5034 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
5035
278feba9
RS
5036 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
5037 at the place where the current window ends in this line
5038 and not display anything beyond there. Otherwise, only MAXCOL
5039 controls where to stop output.
5040
a3788d53
RS
5041 MULTIBYTE can be 0 meaning do not display multibyte chars,
5042 1 meaning do display them, or -1 meaning obey the current buffer's
5043 value of enable_multibyte_characters.
5044
278feba9 5045 Returns ending hpos. */
a2889657
JB
5046
5047static int
278feba9 5048display_string (w, vpos, string, length, hpos, truncate,
a3788d53 5049 obey_window_width, mincol, maxcol, multibyte)
a2889657
JB
5050 struct window *w;
5051 unsigned char *string;
90adcf20 5052 int length;
a2889657
JB
5053 int vpos, hpos;
5054 GLYPH truncate;
278feba9 5055 int obey_window_width;
a2889657 5056 int mincol, maxcol;
a3788d53 5057 int multibyte;
a2889657
JB
5058{
5059 register int c;
d3413a53 5060 int truncated;
a2889657
JB
5061 register GLYPH *p1;
5062 int hscroll = XINT (w->hscroll);
253c7d2f 5063 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
a2889657
JB
5064 register GLYPH *start;
5065 register GLYPH *end;
b1d1124b
JB
5066 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
5067 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
a2889657
JB
5068 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
5069 int window_width = XFASTINT (w->width);
5070
5071 /* Use the standard display table, not the window's display table.
5072 We don't want the mode line in rot13. */
f908610f 5073 register struct Lisp_Char_Table *dp = 0;
efc63ef0 5074 int i;
a2889657 5075
a3788d53
RS
5076 if (multibyte == -1)
5077 multibyte = !NILP (current_buffer->enable_multibyte_characters);
5078 /* Now multibyte is 1 if we should display multibyte characters. */
5079
f908610f
RS
5080 if (DISP_TABLE_P (Vstandard_display_table))
5081 dp = XCHAR_TABLE (Vstandard_display_table);
a2889657 5082
54ff581a 5083 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
a2889657
JB
5084
5085 p1 = p1start;
a27062f0 5086 start = desired_glyphs->glyphs[vpos];
a2889657 5087
278feba9 5088 if (obey_window_width)
b1d1124b 5089 {
a27062f0 5090 start += XFASTINT (w->left);
278feba9
RS
5091 end = start + window_width - (truncate != 0);
5092
73f194f1 5093 if (!WINDOW_RIGHTMOST_P (w))
b1d1124b 5094 {
73f194f1 5095 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
278feba9
RS
5096 {
5097 int i;
b1d1124b 5098
5802e919 5099 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
278feba9
RS
5100 *end-- = ' ';
5101 }
73f194f1 5102 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
278feba9 5103 *end-- = '|';
b1d1124b 5104 }
b1d1124b 5105 }
a2889657 5106
278feba9
RS
5107 if (! obey_window_width
5108 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
a2889657 5109 end = desired_glyphs->glyphs[vpos] + maxcol;
278feba9 5110
efc63ef0 5111 /* Store 0 in charstart for these columns. */
bd5dec8e 5112 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
efc63ef0
RS
5113 desired_glyphs->charstarts[vpos][i] = 0;
5114
a2889657
JB
5115 if (maxcol >= 0 && mincol > maxcol)
5116 mincol = maxcol;
5117
1c9241f5
KH
5118 if (length < 0)
5119 /* We need this value for multibyte characters. */
5120 length = strlen (string);
5121
d3413a53
RS
5122 /* We set truncated to 1 if we get stopped by trying to pass END
5123 (that is, trying to pass MAXCOL.) */
5124 truncated = 0;
5125 while (1)
a2889657 5126 {
1c9241f5
KH
5127 int len;
5128
5129 if (length <= 0)
90adcf20 5130 break;
1c9241f5
KH
5131 if (multibyte)
5132 c = STRING_CHAR_AND_LENGTH (string, length, len);
5133 else
5134 c = *string, len = 1;
5135
5136 string += len, length -= len;
90adcf20 5137
d3413a53
RS
5138 if (p1 >= end)
5139 {
5140 truncated = 1;
5141 break;
5142 }
5143
376b0e59
RS
5144 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
5145 {
5146 p1 = copy_part_of_rope (f, p1, start,
5147 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
5148 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
5149 0);
5150 }
5151 else if (c >= 040 && c < 0177)
a2889657
JB
5152 {
5153 if (p1 >= start)
5154 *p1 = c;
5155 p1++;
5156 }
5157 else if (c == '\t')
5158 {
5159 do
5160 {
5161 if (p1 >= start && p1 < end)
5162 *p1 = SPACEGLYPH;
5163 p1++;
5164 }
5165 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
5166 }
ded34426 5167 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
a2889657
JB
5168 {
5169 if (p1 >= start)
e57bca5d
KH
5170 *p1 = (fix_glyph
5171 (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
5172 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
5173 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
5174 0));
a2889657 5175 p1++;
6e8290aa 5176 if (p1 >= start && p1 < end)
a2889657
JB
5177 *p1 = c ^ 0100;
5178 p1++;
5179 }
1c9241f5 5180 else if (len == 1)
a2889657 5181 {
1c9241f5 5182 /* C is a control character or a binary byte data. */
a2889657 5183 if (p1 >= start)
e57bca5d
KH
5184 *p1 = (fix_glyph
5185 (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
5186 && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
5187 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
5188 0));
a2889657 5189 p1++;
6e8290aa 5190 if (p1 >= start && p1 < end)
a2889657
JB
5191 *p1 = (c >> 6) + '0';
5192 p1++;
6e8290aa 5193 if (p1 >= start && p1 < end)
a2889657
JB
5194 *p1 = (7 & (c >> 3)) + '0';
5195 p1++;
6e8290aa 5196 if (p1 >= start && p1 < end)
a2889657
JB
5197 *p1 = (7 & c) + '0';
5198 p1++;
5199 }
1c9241f5
KH
5200 else
5201 {
5202 /* C is a multibyte character. */
5203 int charset = CHAR_CHARSET (c);
5204 int columns = (charset == CHARSET_COMPOSITION
5205 ? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
5206 : CHARSET_WIDTH (charset));
5207
5208 if (p1 < start)
5209 {
5210 /* Since we can't show the left part of C, fill all
5211 columns with spaces. */
5212 columns -= start - p1;
5213 p1 = start;
5214 while (columns--)
5215 {
5216 if (p1 < end)
5217 *p1 = SPACEGLYPH;
5218 p1++;
5219 }
5220 }
5221 else if (p1 + columns > end)
5222 {
5223 /* Since we can't show the right part of C, fill all
5224 columns with TRUNCATE if TRUNCATE is specified. */
5225 if (truncate)
5226 {
5227 while (p1 < end)
5228 *p1++ = fix_glyph (f, truncate, 0);
5229 /* And tell the line is truncated. */
5230 truncated = 1;
5231 }
5232 break;
5233 }
5234 else
5235 {
5236 /* We can show the whole glyph of C. */
5237 *p1++ = c;
5238 while (--columns)
5239 *p1++ = c | GLYPH_MASK_PADDING;
5240 }
5241 }
a2889657
JB
5242 }
5243
d3413a53 5244 if (truncated)
a2889657
JB
5245 {
5246 p1 = end;
278feba9 5247 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
a2889657
JB
5248 }
5249 else if (mincol >= 0)
5250 {
5251 end = desired_glyphs->glyphs[vpos] + mincol;
5252 while (p1 < end)
5253 *p1++ = SPACEGLYPH;
5254 }
5255
5256 {
5257 register int len = p1 - desired_glyphs->glyphs[vpos];
5258
5259 if (len > desired_glyphs->used[vpos])
5260 desired_glyphs->used[vpos] = len;
5261 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
5262
5263 return len;
5264 }
5265}
5266\f
642eefc6
RS
5267/* This is like a combination of memq and assq.
5268 Return 1 if PROPVAL appears as an element of LIST
5269 or as the car of an element of LIST.
af460d46
RS
5270 If PROPVAL is a list, compare each element against LIST
5271 in that way, and return 1 if any element of PROPVAL is found in LIST.
642eefc6
RS
5272 Otherwise return 0.
5273 This function cannot quit. */
5274
5275int
5276invisible_p (propval, list)
5277 register Lisp_Object propval;
5278 Lisp_Object list;
5279{
af460d46
RS
5280 register Lisp_Object tail, proptail;
5281 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
642eefc6
RS
5282 {
5283 register Lisp_Object tem;
af460d46 5284 tem = XCONS (tail)->car;
642eefc6
RS
5285 if (EQ (propval, tem))
5286 return 1;
5287 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
5288 return 1;
5289 }
af460d46
RS
5290 if (CONSP (propval))
5291 for (proptail = propval; CONSP (proptail);
5292 proptail = XCONS (proptail)->cdr)
5293 {
5294 Lisp_Object propelt;
5295 propelt = XCONS (proptail)->car;
5296 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
5297 {
5298 register Lisp_Object tem;
5299 tem = XCONS (tail)->car;
5300 if (EQ (propelt, tem))
5301 return 1;
5302 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
5303 return 1;
5304 }
5305 }
642eefc6
RS
5306 return 0;
5307}
5308
5309/* Return 1 if PROPVAL appears as the car of an element of LIST
5310 and the cdr of that element is non-nil.
af460d46
RS
5311 If PROPVAL is a list, check each element of PROPVAL in that way,
5312 and the first time some element is found,
5313 return 1 if the cdr of that element is non-nil.
642eefc6
RS
5314 Otherwise return 0.
5315 This function cannot quit. */
5316
5317int
5318invisible_ellipsis_p (propval, list)
5319 register Lisp_Object propval;
5320 Lisp_Object list;
5321{
af460d46
RS
5322 register Lisp_Object tail, proptail;
5323 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
642eefc6
RS
5324 {
5325 register Lisp_Object tem;
af460d46 5326 tem = XCONS (tail)->car;
642eefc6
RS
5327 if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
5328 return ! NILP (XCONS (tem)->cdr);
5329 }
af460d46
RS
5330 if (CONSP (propval))
5331 for (proptail = propval; CONSP (proptail);
5332 proptail = XCONS (proptail)->cdr)
5333 {
5334 Lisp_Object propelt;
5335 propelt = XCONS (proptail)->car;
5336 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
5337 {
5338 register Lisp_Object tem;
5339 tem = XCONS (tail)->car;
5340 if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
5341 return ! NILP (XCONS (tem)->cdr);
5342 }
5343 }
642eefc6
RS
5344 return 0;
5345}
5346\f
a2889657
JB
5347void
5348syms_of_xdisp ()
5349{
cf074754
RS
5350 staticpro (&Qmenu_bar_update_hook);
5351 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
5352
d46fb96a 5353 staticpro (&Qoverriding_terminal_local_map);
7079aefa 5354 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 5355
399164b4
KH
5356 staticpro (&Qoverriding_local_map);
5357 Qoverriding_local_map = intern ("overriding-local-map");
5358
75c43375
RS
5359 staticpro (&Qwindow_scroll_functions);
5360 Qwindow_scroll_functions = intern ("window-scroll-functions");
5361
e0bfbde6
RS
5362 staticpro (&Qredisplay_end_trigger_functions);
5363 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
67481ae5 5364
a2889657
JB
5365 staticpro (&last_arrow_position);
5366 staticpro (&last_arrow_string);
5367 last_arrow_position = Qnil;
5368 last_arrow_string = Qnil;
5369
5370 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 5371 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
5372 Vglobal_mode_string = Qnil;
5373
5374 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
5375 "Marker for where to display an arrow on top of the buffer text.\n\
5376This must be the beginning of a line in order to work.\n\
5377See also `overlay-arrow-string'.");
5378 Voverlay_arrow_position = Qnil;
5379
5380 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
5381 "String to display as an arrow. See also `overlay-arrow-position'.");
5382 Voverlay_arrow_string = Qnil;
5383
5384 DEFVAR_INT ("scroll-step", &scroll_step,
5385 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
5386If that fails to bring point back on frame, point is centered instead.\n\
5387If this is zero, point is always centered after it moves off frame.");
a2889657 5388
0789adb2
RS
5389 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
5390 "*Scroll up to this many lines, to bring point back on screen.");
5391 scroll_conservatively = 0;
5392
9afd2168
RS
5393 DEFVAR_INT ("scroll-margin", &scroll_margin,
5394 "*Number of lines of margin at the top and bottom of a window.\n\
5395Recenter the window whenever point gets within this many lines\n\
5396of the top or bottom of the window.");
5397 scroll_margin = 0;
5398
a2889657
JB
5399 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
5400
5401 DEFVAR_BOOL ("truncate-partial-width-windows",
5402 &truncate_partial_width_windows,
44fa5b1e 5403 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
5404 truncate_partial_width_windows = 1;
5405
5406 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
5407 "*Non-nil means use inverse video for the mode line.");
5408 mode_line_inverse_video = 1;
aa6d10fa
RS
5409
5410 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
db4f2bfa
KH
5411 "*Maximum buffer size (in characters) for line number display\n\
5412If the buffer is bigger than this, the line number does not appear\n\
5413in the mode line..");
aa6d10fa 5414 line_number_display_limit = 1000000;
fba9ce76
RS
5415
5416 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
5417 "*Non-nil means highlight region even in nonselected windows.");
293a54ce 5418 highlight_nonselected_windows = 0;
d39b6696
KH
5419
5420 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
5421 "Non-nil if more than one frame is visible on this display.\n\
5422Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
5423This variable is not guaranteed to be accurate except while processing\n\
5424`frame-title-format' and `icon-title-format'.");
d39b6696
KH
5425
5426 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
5427 "Template for displaying the titlebar of visible frames.\n\
5428\(Assuming the window manager supports this feature.)\n\
5429This variable has the same structure as `mode-line-format' (which see),\n\
5430and is used only on frames for which no explicit name has been set\n\
5431\(see `modify-frame-parameters').");
5432 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
5433 "Template for displaying the titlebar of an iconified frame.\n\
5434\(Assuming the window manager supports this feature.)\n\
5435This variable has the same structure as `mode-line-format' (which see),\n\
5436and is used only on frames for which no explicit name has been set\n\
5437\(see `modify-frame-parameters').");
5438 Vicon_title_format
5439 = Vframe_title_format
5440 = Fcons (intern ("multiple-frames"),
5441 Fcons (build_string ("%b"),
5442 Fcons (Fcons (build_string (""),
5443 Fcons (intern ("invocation-name"),
5444 Fcons (build_string ("@"),
5445 Fcons (intern ("system-name"),
5446 Qnil)))),
5447 Qnil)));
5992c4f7
KH
5448
5449 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
5450 "Maximum number of lines to keep in the message log buffer.\n\
5451If nil, disable message logging. If t, log messages but don't truncate\n\
5452the buffer when it becomes large.");
5453 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
5454
5455 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
5456 "Functions called before redisplay, if window sizes have changed.\n\
5457The value should be a list of functions that take one argument.\n\
5458Just before redisplay, for each frame, if any of its windows have changed\n\
5459size since the last redisplay, or have been split or deleted,\n\
5460all the functions in the list are called, with the frame as argument.");
5461 Vwindow_size_change_functions = Qnil;
75c43375
RS
5462
5463 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
010494d0 5464 "List of functions to call before redisplaying a window with scrolling.\n\
75c43375 5465Each function is called with two arguments, the window\n\
8d9583b0
RS
5466and its new display-start position. Note that the value of `window-end'\n\
5467is not valid when these functions are called.");
75c43375 5468 Vwindow_scroll_functions = Qnil;
010494d0
KH
5469
5470 DEFVAR_INT ("minibuffer-scroll-overlap", &minibuffer_scroll_overlap,
5471 "*Number of characters of overlap when scrolling a one-line window.\n\
5472This commonly affects the minibuffer window, hence the name of the variable.");
5473 minibuffer_scroll_overlap = 20;
a2889657
JB
5474}
5475
5476/* initialize the window system */
dfcf069d 5477void
a2889657
JB
5478init_xdisp ()
5479{
5480 Lisp_Object root_window;
5481#ifndef COMPILER_REGISTER_BUG
5482 register
5483#endif /* COMPILER_REGISTER_BUG */
5484 struct window *mini_w;
5485
5486 this_line_bufpos = 0;
5487
5488 mini_w = XWINDOW (minibuf_window);
11e82b76 5489 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657
JB
5490
5491 echo_area_glyphs = 0;
5492 previous_echo_glyphs = 0;
5493
5494 if (!noninteractive)
5495 {
44fa5b1e 5496 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
12c226c5
RS
5497 XSETFASTINT (XWINDOW (root_window)->top, FRAME_MENU_BAR_LINES (f));
5498 set_window_height (root_window,
5499 FRAME_HEIGHT (f) - 1 - FRAME_MENU_BAR_LINES (f),
5500 0);
c2213350 5501 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
5502 set_window_height (minibuf_window, 1, 0);
5503
c2213350
KH
5504 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
5505 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
a2889657
JB
5506 }
5507}