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