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