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