(array-mode): Add autoload cookie.
[emacs.git] / src / xdisp.c
blob84a80d519a810fab18508a4a434d5c23535ee42b
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.
5 This file is part of GNU Emacs.
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.
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.
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. */
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"
45 #ifdef HAVE_WINDOW_SYSTEM
46 #include "xterm.h"
47 #endif
49 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
50 extern void set_frame_menubar ();
51 extern int pending_menu_activation;
52 #endif
54 extern int interrupt_input;
55 extern int command_loop_level;
57 extern int minibuffer_auto_raise;
59 extern Lisp_Object Qface;
61 extern Lisp_Object Voverriding_local_map;
62 extern Lisp_Object Voverriding_local_map_menu_flag;
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;
68 /* Nonzero means print newline to stdout before next minibuffer message. */
70 int noninteractive_need_newline;
72 /* Nonzero means print newline to message log before next message. */
74 static int message_log_need_newline;
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))
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;
86 /* Number of characters past the end of this line,
87 including the terminating newline */
88 static int this_line_endpos;
90 /* The vertical position of this frame line. */
91 static int this_line_vpos;
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;
98 /* Buffer that this_line variables are describing. */
99 static struct buffer *this_line_buffer;
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;
107 /* Nonzero means truncate lines in all windows less wide than the frame */
108 int truncate_partial_width_windows;
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;
114 Lisp_Object Vglobal_mode_string;
116 /* Marker for where to display an arrow on top of the buffer text. */
117 Lisp_Object Voverlay_arrow_position;
119 /* String to display for the arrow. */
120 Lisp_Object Voverlay_arrow_string;
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;
127 /* Like mode-line-format, but for the titlebar on a visible frame. */
128 Lisp_Object Vframe_title_format;
130 /* Like mode-line-format, but for the titlebar on an iconified frame. */
131 Lisp_Object Vicon_title_format;
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;
138 Lisp_Object Qmenu_bar_update_hook;
140 /* Nonzero if overlay arrow has been displayed once in this window. */
141 static int overlay_arrow_seen;
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;
148 /* Nonzero means highlight the region even in nonselected windows. */
149 static int highlight_nonselected_windows;
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;
155 /* Non-0 means scroll just far enough to bring point back on the screen,
156 when appropriate. */
157 static int scroll_conservatively;
159 /* Recenter the window whenever point gets within this many lines
160 of the top or bottom of the window. */
161 int scroll_margin;
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;
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;
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;
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. */
180 static int cursor_vpos;
181 static int cursor_hpos;
183 static int debug_end_pos;
185 /* Nonzero means display mode line highlighted */
186 int mode_line_inverse_video;
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 ();
205 /* Prompt to display in front of the minibuffer contents */
206 Lisp_Object minibuf_prompt;
208 /* Width in columns of current minibuffer prompt. */
209 int minibuf_prompt_width;
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;
217 /* This is the length of the message in echo_area_glyphs. */
218 int echo_area_glyphs_length;
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;
225 /* Nonzero means multibyte characters were enabled when the echo area
226 message was specified. */
227 int message_enable_multibyte;
229 /* true iff we should redraw the mode lines on the next redisplay */
230 int update_mode_lines;
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;
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;
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;
248 /* OVERLAY_MODIFF as of last redisplay that finished. */
249 int overlay_unchanged_modified;
251 /* Nonzero if window sizes or contents have changed
252 since last redisplay that finished */
253 int windows_or_buffers_changed;
255 /* Nonzero after display_mode_line if %l was used
256 and it displayed a line number. */
257 int line_number_displayed;
259 /* Maximum buffer size for which to display line numbers. */
260 static int line_number_display_limit;
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;
266 #define COERCE_MARKER(X) \
267 (MARKERP ((X)) ? Fmarker_position (X) : (X))
269 static int pos_tab_offset P_ ((struct window *, int, int));
271 /* Output a newline in the *Messages* buffer if "needs" one. */
273 void
274 message_log_maybe_newline ()
276 if (message_log_need_newline)
277 message_dolog ("", 0, 1, 0);
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. */
286 void
287 message_dolog (m, len, nlflag, multibyte)
288 char *m;
289 int len, nlflag, multibyte;
291 if (!NILP (Vmessage_log_max))
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;
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;
305 oldpoint = Fpoint_marker ();
306 oldbegv = Fpoint_min_marker ();
307 oldzv = Fpoint_max_marker ();
309 if (PT == Z)
310 point_at_end = 1;
311 if (ZV == Z)
312 zv_at_end = 1;
314 BEGV = BEG;
315 BEGV_BYTE = BEG_BYTE;
316 ZV = Z;
317 ZV_BYTE = Z_BYTE;
318 TEMP_SET_PT_BOTH (Z, Z_BYTE);
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))
325 int c, i = 0, nbytes;
326 /* Convert a multibyte string to single-byte
327 for the *Message* buffer. */
328 while (i < len)
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);
339 else if (! multibyte
340 && ! NILP (current_buffer->enable_multibyte_characters))
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)
348 int c = unibyte_char_to_multibyte (msg[i++]);
349 insert_char (c);
352 else if (len)
353 insert_1 (m, len, 1, 0, 0);
355 if (nlflag)
357 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
358 insert_1 ("\n", 1, 1, 0, 0);
360 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
361 this_bol = PT;
362 this_bol_byte = PT_BYTE;
364 if (this_bol > BEG)
366 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
367 prev_bol = PT;
368 prev_bol_byte = PT_BYTE;
370 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
371 this_bol, this_bol_byte);
372 if (dup)
374 del_range_both (prev_bol, prev_bol_byte,
375 this_bol, this_bol_byte, 0);
376 if (dup > 1)
378 char dupstr[40];
379 int duplen;
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);
391 if (NATNUMP (Vmessage_log_max))
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);
398 BEGV = XMARKER (oldbegv)->charpos;
399 BEGV_BYTE = marker_byte_position (oldbegv);
401 if (zv_at_end)
403 ZV = Z;
404 ZV_BYTE = Z_BYTE;
406 else
408 ZV = XMARKER (oldzv)->charpos;
409 ZV_BYTE = marker_byte_position (oldzv);
412 if (point_at_end)
413 TEMP_SET_PT_BOTH (Z, Z_BYTE);
414 else
415 Fgoto_char (oldpoint);
417 free_marker (oldpoint);
418 free_marker (oldbegv);
419 free_marker (oldzv);
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;
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]". */
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;
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);
445 for (i = 0; i < len; i++)
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;
453 p1 += len;
454 if (*p1 == '\n')
455 return 2;
456 if (*p1++ == ' ' && *p1++ == '[')
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;
464 return 0;
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.
471 The buffer M must continue to exist until after the echo area
472 gets cleared or some other message gets displayed there.
474 Do not pass text that is stored in a Lisp string.
475 Do not pass text in a buffer that was alloca'd. */
477 void
478 message2 (m, len, multibyte)
479 char *m;
480 int len;
481 int multibyte;
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);
491 /* The non-logging counterpart of message2. */
493 void
494 message2_nolog (m, len, multibyte)
495 char *m;
496 int len;
498 message_enable_multibyte = multibyte;
500 if (noninteractive)
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);
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))
516 Lisp_Object mini_window;
517 FRAME_PTR f;
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)));
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)));
529 if (m)
531 echo_area_glyphs = m;
532 echo_area_glyphs_length = len;
534 if (minibuffer_auto_raise)
535 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
537 else
538 echo_area_glyphs = previous_echo_glyphs = 0;
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);
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.
553 The string M must continue to exist until after the echo area
554 gets cleared or some other message gets displayed there.
556 Do not pass text that is stored in a Lisp string.
557 Do not pass text in a buffer that was alloca'd. */
559 void
560 message1 (m)
561 char *m;
563 message2 (m, (m ? strlen (m) : 0), 0);
566 void
567 message1_nolog (m)
568 char *m;
570 message2_nolog (m, (m ? strlen (m) : 0), 0);
573 /* Display a message M which contains a single %s
574 which gets replaced with STRING. */
576 void
577 message_with_string (m, string, log)
578 char *m;
579 Lisp_Object string;
580 int log;
582 if (noninteractive)
584 if (m)
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);
595 else if (INTERACTIVE)
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;
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)));
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))
613 int len;
614 char *a[1];
615 a[0] = (char *) XSTRING (string)->data;
617 len = doprnt (FRAME_MESSAGE_BUF (f),
618 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
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));
627 /* Print should start at the beginning of the message
628 buffer next time. */
629 message_buf_print = 0;
634 /* Truncate what will be displayed in the echo area
635 the next time we display it--but don't redisplay it now. */
637 void
638 truncate_echo_area (len)
639 int len;
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;
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;
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. */
655 /* VARARGS 1 */
656 void
657 message (m, a1, a2, a3)
658 char *m;
659 EMACS_INT a1, a2, a3;
661 if (noninteractive)
663 if (m)
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);
674 else if (INTERACTIVE)
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;
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)));
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))
692 if (m)
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;
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 */
709 message2 (FRAME_MESSAGE_BUF (f), len, 0);
711 else
712 message1 (0);
714 /* Print should start at the beginning of the message
715 buffer next time. */
716 message_buf_print = 0;
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;
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;
734 void
735 update_echo_area ()
737 message2 (echo_area_glyphs, echo_area_glyphs_length,
738 ! NILP (current_buffer->enable_multibyte_characters));
741 static void
742 echo_area_display ()
744 register int vpos;
745 FRAME_PTR f;
746 Lisp_Object mini_window;
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)));
754 if (! FRAME_VISIBLE_P (f))
755 return;
757 if (frame_garbaged)
759 redraw_garbaged_frames ();
760 frame_garbaged = 0;
763 if (echo_area_glyphs || minibuf_level == 0)
765 int i;
767 echo_area_window = mini_window;
769 vpos = XFASTINT (XWINDOW (mini_window)->top);
770 get_display_line (f, vpos, 0);
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;
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);
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
793 /* Fill the rest of the minibuffer window with blank lines. */
795 int i;
797 for (i = vpos + 1;
798 i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
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),
812 else if (!EQ (mini_window, selected_window))
813 windows_or_buffers_changed++;
815 if (EQ (mini_window, selected_window))
816 this_line_bufpos = 0;
818 previous_echo_glyphs = echo_area_glyphs;
821 /* Update frame titles. */
823 #ifdef HAVE_WINDOW_SYSTEM
824 static char frame_title_buf[512];
825 static char *frame_title_ptr;
827 static int
828 store_frame_title (str, mincol, maxcol)
829 char *str;
830 int mincol, maxcol;
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;
843 static void
844 x_consider_frame_title (frame)
845 Lisp_Object frame;
847 Lisp_Object fmt;
848 struct buffer *obuf;
849 int len;
850 FRAME_PTR f = XFRAME (frame);
852 if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
853 return;
855 /* Do we have more than one visible frame on this X display? */
857 Lisp_Object tail;
859 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
861 FRAME_PTR tf = XFRAME (XCONS (tail)->car);
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;
869 multiple_frames = CONSP (tail);
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);
889 #else
890 #define frame_title_ptr ((char *)0)
891 #define store_frame_title(str, mincol, maxcol) 0
892 #endif
894 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
895 This can call eval. */
897 void
898 prepare_menu_bars ()
900 register struct window *w = XWINDOW (selected_window);
901 int all_windows;
902 struct gcpro gcpro1, gcpro2;
904 all_windows = (update_mode_lines || buffer_shared > 1
905 || windows_or_buffers_changed);
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.
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)
920 Lisp_Object tail, frame;
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);
927 #endif
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)
934 Lisp_Object tail, frame;
935 int count = specpdl_ptr - specpdl;
937 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
939 FOR_EACH_FRAME (tail, frame)
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)))
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))
952 call1 (XCONS (functions)->car, frame);
953 functions = XCONS (functions)->cdr;
955 UNGCPRO;
957 GCPRO1 (tail);
958 update_menu_bar (XFRAME (frame), 0);
959 UNGCPRO;
962 unbind_to (count, Qnil);
964 else
965 update_menu_bar (selected_frame, 1);
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
974 /* Do a frame update, taking possible shortcuts into account.
975 This is the main external entry point for redisplay.
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.
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.
989 See Fcall_process; if you called it from here, it could be
990 entered recursively. */
992 static int do_verify_charstarts;
994 /* Counter is used to clear the face cache
995 no more than once ever 1000 redisplays. */
996 static int clear_face_cache_count;
998 /* Record the previous terminal frame we displayed. */
999 static FRAME_PTR previous_terminal_frame;
1001 void
1002 redisplay ()
1004 redisplay_internal (0);
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. */
1013 static void
1014 redisplay_internal (preserve_echo_area)
1015 int preserve_echo_area;
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;
1025 if (noninteractive)
1026 return;
1028 #ifdef USE_X_TOOLKIT
1029 if (popup_activated ())
1030 return;
1031 #endif
1033 retry:
1035 if (! FRAME_WINDOW_P (selected_frame)
1036 && previous_terminal_frame != selected_frame)
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);
1044 previous_terminal_frame = selected_frame;
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. */
1051 Lisp_Object tail, frame;
1053 number_of_visible_frames = 0;
1055 FOR_EACH_FRAME (tail, frame)
1057 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
1059 if (FRAME_VISIBLE_P (XFRAME (frame)))
1060 number_of_visible_frames++;
1062 /* Clear out all the display lines in which we will generate the
1063 glyphs to display. */
1064 init_desired_glyphs (XFRAME (frame));
1068 /* Notice any pending interrupt request to change frame size. */
1069 do_pending_window_change ();
1071 if (frame_garbaged)
1073 redraw_garbaged_frames ();
1074 frame_garbaged = 0;
1077 prepare_menu_bars ();
1079 if (windows_or_buffers_changed)
1080 update_mode_lines++;
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))
1085 w->update_mode_line = Qt;
1086 if (buffer_shared > 1)
1087 update_mode_lines++;
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;
1100 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
1102 all_windows = update_mode_lines || buffer_shared > 1;
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;
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)
1116 echo_area_display ();
1117 must_finish = 1;
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;
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)))
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))
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).
1172 For instance, in the following case:
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 -------- --------
1180 As we have to redraw the line above, we should goto cancel. */
1182 struct position val;
1183 int prevline;
1184 int opoint = PT, opoint_byte = PT_BYTE;
1186 scan_newline (tlbufpos, tlbufpos_byte, BEGV, BEGV_BYTE, -1, 1);
1188 val = *compute_motion (PT, 0,
1189 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 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;
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)
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))
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;
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];
1231 adjust_window_charstarts (w, this_line_vpos, adjust);
1234 if (!WINDOW_FULL_WIDTH_P (w))
1235 preserve_other_columns (w);
1236 goto update;
1238 else
1239 goto cancel;
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)))
1248 if (!must_finish)
1250 do_pending_window_change ();
1251 return;
1253 goto update;
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)
1264 pos = *compute_motion (tlbufpos, 0,
1265 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 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),
1272 if (pos.vpos < 1)
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;
1280 else
1281 goto cancel;
1283 cancel:
1284 /* Text changed drastically or point moved off of line */
1285 cancel_line (this_line_vpos, selected_frame);
1288 this_line_bufpos = 0;
1289 all_windows |= buffer_shared > 1;
1291 clear_face_cache_count++;
1293 if (all_windows)
1295 Lisp_Object tail, frame;
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)
1302 clear_face_cache ();
1303 clear_face_cache_count = 0;
1305 #endif
1307 /* Recompute # windows showing selected buffer.
1308 This will be incremented each time such a window is displayed. */
1309 buffer_shared = 0;
1311 FOR_EACH_FRAME (tail, frame)
1313 FRAME_PTR f = XFRAME (frame);
1314 if (FRAME_WINDOW_P (f) || f == selected_frame)
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);
1322 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
1323 redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
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);
1332 else if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame))
1334 redisplay_window (selected_window, 1, preserve_echo_area);
1335 if (!WINDOW_FULL_WIDTH_P (w))
1336 preserve_other_columns (w);
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 ();
1347 if (all_windows)
1349 Lisp_Object tail;
1351 pause = 0;
1353 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1355 FRAME_PTR f;
1357 if (!FRAMEP (XCONS (tail)->car))
1358 continue;
1360 f = XFRAME (XCONS (tail)->car);
1362 if ((FRAME_WINDOW_P (f) || f == selected_frame)
1363 && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
1365 pause |= update_frame (f, 0, 0);
1366 if (!pause)
1368 mark_window_display_accurate (f->root_window, 1);
1369 if (frame_up_to_date_hook != 0)
1370 (*frame_up_to_date_hook) (f);
1375 else
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;
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. */
1388 Lisp_Object mini_window;
1389 FRAME_PTR mini_frame;
1391 mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
1392 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
1394 if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
1395 pause |= update_frame (mini_frame, 0, 0);
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)
1403 this_line_bufpos = 0;
1404 if (!NILP (last_arrow_position))
1406 last_arrow_position = Qt;
1407 last_arrow_string = Qt;
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;
1417 /* Now text on frame agrees with windows, so
1418 put info into the windows for partial redisplay to follow */
1420 if (!pause)
1422 register struct buffer *b = XBUFFER (w->buffer);
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);
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));
1434 if (all_windows)
1435 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
1436 else
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);
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);
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);
1463 update_mode_lines = 0;
1464 windows_or_buffers_changed = 0;
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. */
1474 if (interrupt_input)
1475 request_sigio ();
1476 start_polling ();
1478 /* If something has become visible now which was not before,
1479 redisplay again, so that we get them. */
1480 if (!pause)
1482 Lisp_Object tail, frame;
1483 int new_count = 0;
1485 FOR_EACH_FRAME (tail, frame)
1487 int this_is_visible = 0;
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;
1495 if (this_is_visible)
1496 new_count++;
1499 if (new_count != number_of_visible_frames)
1500 windows_or_buffers_changed++;
1503 /* Change frame size now if a change is pending. */
1504 do_pending_window_change ();
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;
1512 /* Redisplay, but leave alone any recent echo area message
1513 unless another message has been requested in its place.
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. */
1520 void
1521 redisplay_preserve_echo_area ()
1523 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
1525 echo_area_glyphs = previous_echo_glyphs;
1526 redisplay_internal (1);
1527 echo_area_glyphs = 0;
1529 else
1530 redisplay_internal (1);
1533 void
1534 mark_window_display_accurate (window, flag)
1535 Lisp_Object window;
1536 int flag;
1538 register struct window *w;
1540 for (;!NILP (window); window = w->next)
1542 if (!WINDOWP (window)) abort ();
1543 w = XWINDOW (window);
1545 if (!NILP (w->buffer))
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);
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);
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;
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);
1576 if (flag)
1578 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
1579 last_arrow_string = Voverlay_arrow_string;
1581 else
1583 /* t is unequal to any useful value of Voverlay_arrow_... */
1584 last_arrow_position = Qt;
1585 last_arrow_string = Qt;
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.
1593 If SAVE_MATCH_DATA is 1, we must save and restore it here. */
1595 static void
1596 update_menu_bar (f, save_match_data)
1597 FRAME_PTR f;
1598 int save_match_data;
1600 struct buffer *old = current_buffer;
1601 Lisp_Object window;
1602 register struct window *w;
1604 window = FRAME_SELECTED_WINDOW (f);
1605 w = XWINDOW (window);
1607 if (update_mode_lines)
1608 w->update_mode_line = Qt;
1610 if (FRAME_WINDOW_P (f)
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)
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)))
1635 struct buffer *prev = current_buffer;
1636 int count = specpdl_ptr - specpdl;
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))
1643 specbind (Qoverriding_terminal_local_map, Qnil);
1644 specbind (Qoverriding_local_map, Qnil);
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) */
1669 unbind_to (count, Qnil);
1670 set_buffer_internal_1 (prev);
1675 int do_id = 1;
1677 /* Redisplay WINDOW and its subwindows and siblings. */
1679 static void
1680 redisplay_windows (window, preserve_echo_area)
1681 Lisp_Object window;
1682 int preserve_echo_area;
1684 for (; !NILP (window); window = XWINDOW (window)->next)
1685 redisplay_window (window, 0, preserve_echo_area);
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;
1697 int code[4], i;
1698 Lisp_Object val;
1700 if (SINGLE_BYTE_CHAR_P (c)) return (dp->contents[c]);
1702 SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
1703 if (code[0] != CHARSET_COMPOSITION)
1705 if (code[1] < 32) code[1] = -1;
1706 else if (code[2] < 32) code[2] = -1;
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 */
1715 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
1717 val = dp->contents[code[i]];
1718 if (!SUB_CHAR_TABLE_P (val))
1719 return (NILP (val) ? dp->defalt : val);
1721 /* Here, VAL is a sub char table. We return the default value of it. */
1722 return (dp->defalt);
1725 /* Redisplay window WINDOW and its subwindows. */
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;
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;
1749 if (Z == Z_BYTE && lpoint != lpoint_byte)
1750 abort ();
1751 if (lpoint_byte < lpoint)
1752 abort ();
1754 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1756 /* If this is a combination window, do its children; that's all. */
1758 if (!NILP (w->vchild))
1760 redisplay_windows (w->vchild, preserve_echo_area);
1761 return;
1763 if (!NILP (w->hchild))
1765 redisplay_windows (w->hchild, preserve_echo_area);
1766 return;
1768 if (NILP (w->buffer))
1769 abort ();
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;
1776 if (MINI_WINDOW_P (w))
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))
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;
1788 for (i = 0; i < height; i++)
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);
1796 goto finish_scroll_bars;
1800 /* Otherwise set up data on this window; select its buffer and point value */
1802 if (update_mode_line)
1803 /* Really select the buffer, for the sake of buffer-local variables. */
1805 set_buffer_internal_1 (XBUFFER (w->buffer));
1806 really_switched_buffer = 1;
1808 else
1809 set_buffer_temp (XBUFFER (w->buffer));
1811 opoint = PT;
1812 opoint_byte = PT_BYTE;
1814 if (Z == Z_BYTE && opoint != opoint_byte)
1815 abort ();
1816 if (opoint_byte < opoint)
1817 abort ();
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;
1829 /* Count number of windows showing the selected buffer.
1830 An indirect buffer counts as its base buffer. */
1832 if (!just_this_one)
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++;
1845 /* POINT refers normally to the selected window.
1846 For any other window, set up appropriate value. */
1848 if (!EQ (window, selected_window))
1850 int new_pt = XMARKER (w->pointm)->charpos;
1851 int new_pt_byte = marker_byte_position (w->pointm);
1852 if (new_pt < BEGV)
1854 new_pt = BEGV;
1855 new_pt_byte = BEGV_BYTE;
1856 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
1858 else if (new_pt > (ZV - 1))
1860 new_pt = ZV;
1861 new_pt_byte = ZV_BYTE;
1862 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
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);
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)
1875 struct Lisp_Char_Table *disptab = buffer_display_table ();
1877 if (! disptab_matches_widthtab (disptab,
1878 XVECTOR (current_buffer->width_table)))
1880 invalidate_region_cache (current_buffer,
1881 current_buffer->width_run_cache,
1882 BEG, Z);
1883 recompute_width_table (current_buffer, disptab);
1887 /* If window-start is screwed up, choose a new one. */
1888 if (XMARKER (w->start)->buffer != current_buffer)
1889 goto recenter;
1891 startp = marker_position (w->start);
1892 startp_byte = marker_byte_position (w->start);
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))
1898 w->optional_new_start = Qnil;
1899 /* Check whether this start pos is usable given where point is. */
1901 pos = *compute_motion (startp, 0,
1902 (((EQ (window, minibuf_window)
1903 && startp == BEG)
1904 ? minibuf_prompt_width : 0)
1905 + (hscroll ? 1 - hscroll : 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;
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))
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))
1936 Lisp_Object temp[3];
1938 if (!really_switched_buffer)
1940 set_buffer_temp (old);
1941 set_buffer_internal_1 (XBUFFER (w->buffer));
1943 really_switched_buffer = 1;
1944 update_mode_line = 1;
1945 w->update_mode_line = Qt;
1946 if (! NILP (Vwindow_scroll_functions))
1948 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1949 make_number (startp));
1950 startp = marker_position (w->start);
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)
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)),
1967 ZV, height / 2,
1968 - (1 << (BITS_PER_SHORT - 1)),
1969 width, hscroll,
1970 pos_tab_offset (w, startp, startp_byte),
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
1977 if (current_buffer == old)
1979 lpoint = PT;
1980 lpoint_byte = PT_BYTE;
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);
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))
1991 cancel_my_columns (XWINDOW (window));
1992 try_window (window, startp);
1995 goto done;
1998 /* Handle case where text has not changed, only point,
1999 and it has not moved off the frame. */
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. */
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))
2026 /* All positions in this clause are relative to the window edge. */
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));
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)
2037 pos.hpos = last_point_x;
2038 pos.vpos = last_point_y;
2039 pos.bufpos = PT;
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))
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));
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,
2062 else
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),
2074 /* Don't use a scroll margin that is negative or too large. */
2075 if (this_scroll_margin < 0)
2076 this_scroll_margin = 0;
2078 if (XINT (w->height) < 4 * scroll_margin)
2079 this_scroll_margin = XINT (w->height) / 4;
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))
2086 /* Ok, point is still on frame */
2087 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
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);
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);
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)));
2106 goto done;
2108 /* Don't bother trying redisplay with same start;
2109 we already know it will lose */
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'))
2117 goto recenter;
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)
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;
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)))
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)
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;
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)));
2176 goto done;
2178 else
2179 cancel_my_columns (w);
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)
2187 if (!really_switched_buffer)
2189 set_buffer_temp (old);
2190 set_buffer_internal_1 (XBUFFER (w->buffer));
2192 update_mode_line = 1;
2193 w->update_mode_line = Qt;
2196 /* Try to scroll by specified few lines */
2198 if (scroll_conservatively && !current_buffer->clip_changed
2199 && startp >= BEGV && startp <= ZV)
2201 int this_scroll_margin = scroll_margin;
2202 int scroll_margin_pos;
2204 /* Don't use a scroll margin that is negative or too large. */
2205 if (this_scroll_margin < 0)
2206 this_scroll_margin = 0;
2208 if (XINT (w->height) < 4 * this_scroll_margin)
2209 this_scroll_margin = XINT (w->height) / 4;
2211 scroll_margin_pos = Z - XFASTINT (w->window_end_pos);
2212 if (this_scroll_margin)
2214 pos = *vmotion (scroll_margin_pos, -this_scroll_margin, w);
2215 scroll_margin_pos = pos.bufpos;
2217 if (PT >= scroll_margin_pos)
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),
2225 if (pos.vpos > scroll_conservatively)
2226 goto scroll_fail_1;
2228 pos = *vmotion (startp, pos.vpos + 1, w);
2230 if (! NILP (Vwindow_scroll_functions))
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);
2237 try_window (window, pos.bufpos);
2238 if (cursor_vpos >= 0)
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;
2246 else
2247 cancel_my_columns (w);
2250 scroll_margin_pos = startp;
2251 if (this_scroll_margin)
2253 pos = *vmotion (scroll_margin_pos, this_scroll_margin, w);
2254 scroll_margin_pos = pos.bufpos;
2256 if (PT < scroll_margin_pos)
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),
2264 if (pos.vpos > scroll_conservatively)
2265 goto scroll_fail_1;
2267 pos = *vmotion (startp, -pos.vpos, w);
2269 if (! NILP (Vwindow_scroll_functions))
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);
2276 try_window (window, pos.bufpos);
2277 if (cursor_vpos >= 0)
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;
2285 else
2286 cancel_my_columns (w);
2288 scroll_fail_1: ;
2291 if (scroll_step && !current_buffer->clip_changed
2292 && startp >= BEGV && startp <= ZV)
2294 if (PT > startp)
2296 pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
2297 if (pos.vpos >= height)
2298 goto scroll_fail;
2301 pos = *vmotion (startp, (PT < startp ? - scroll_step : scroll_step), w);
2303 if (PT >= pos.bufpos)
2305 if (! NILP (Vwindow_scroll_functions))
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);
2312 try_window (window, pos.bufpos);
2313 if (cursor_vpos >= 0)
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;
2321 else
2322 cancel_my_columns (w);
2324 scroll_fail: ;
2327 /* Finally, just choose place to start which centers point */
2329 recenter:
2330 /* Forget any previously recorded base line for line number display. */
2331 w->base_line_number = Qnil;
2333 pos = *vmotion (PT, - (height / 2), w);
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')
2347 pos.bufpos = PT - minibuffer_scroll_overlap;
2348 pos.bytepos = CHAR_TO_BYTE (pos.bufpos);
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))
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);
2361 try_window (window, pos.bufpos);
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;
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))
2378 FRAME_PTR oframe = selected_frame;
2379 if (!really_switched_buffer)
2381 set_buffer_temp (old);
2382 set_buffer_internal_1 (XBUFFER (w->buffer));
2383 really_switched_buffer = 1;
2385 selected_frame = f;
2386 display_mode_line (w);
2387 selected_frame = oframe;
2389 if (! line_number_displayed
2390 && ! BUFFERP (w->base_line_pos))
2392 w->base_line_pos = Qnil;
2393 w->base_line_number = Qnil;
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)
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);
2409 finish_scroll_bars:
2410 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2412 int start, end, whole;
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.
2420 Note that minibuffers sometimes aren't displaying any text. */
2421 if (! MINI_WINDOW_P (w)
2422 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
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;
2430 if (end < start) end = start;
2431 if (whole < (end - start)) whole = end - start;
2433 else
2434 start = end = whole = 0;
2436 /* Indicate what this scroll bar ought to be displaying now. */
2437 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
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);
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);
2452 /* Do full redisplay on one window, starting at position `pos'. */
2454 static void
2455 try_window (window, pos)
2456 Lisp_Object window;
2457 register int pos;
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;
2467 /* POS should never be out of range! */
2468 if (pos < XBUFFER (w->buffer)->begv
2469 || pos > XBUFFER (w->buffer)->zv)
2470 abort ();
2472 if (XMARKER (w->start)->charpos != pos)
2473 Fset_marker (w->start, make_number (pos), Qnil);
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);
2483 while (--height >= 0)
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)
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
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));
2510 pos = val.bufpos;
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++;
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;
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;
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. */
2537 static int
2538 try_window_id (window)
2539 Lisp_Object window;
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;
2564 int start_byte = marker_byte_position (w->start);
2566 if (GPT - BEG < beg_unchanged)
2567 beg_unchanged = GPT - BEG;
2568 if (Z - GPT < end_unchanged)
2569 end_unchanged = Z - GPT;
2571 if (beg_unchanged + BEG < start)
2572 return 0; /* Give up if changes go above top of window */
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),
2583 if (bp.vpos >= height)
2585 if (PT < bp.bufpos)
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;
2602 return 0;
2605 vpos = bp.vpos;
2607 /* Find beginning of that frame line. Must display from there. */
2608 bp = *vmotion (bp.bufpos, 0, w);
2610 pos = bp.bufpos;
2611 pos_byte = bp.bytepos;
2612 val.hpos = lmargin;
2613 if (pos < start)
2614 return -1;
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)
2622 /* Likewise if we have to worry about selective display. */
2623 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
2625 bp = *vmotion (bp.bufpos, -1, w);
2626 --vpos;
2627 pos = bp.bufpos;
2628 pos_byte = bp.bytepos;
2630 val.tab_offset = bp.tab_offset; /* Update tab offset. */
2632 if (bp.contin && bp.hpos != lmargin)
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);
2640 bp.vpos = vpos;
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);
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);
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;
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;
2677 cursor_vpos = -1;
2678 overlay_arrow_seen = 0;
2679 zv_strings_seen = 0;
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)
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);
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++)
2699 tem = FETCH_BYTE (i);
2700 if (tem != ' ' && tem != '\n' && tem != '\t')
2701 break;
2703 if (i == xp.bytepos)
2704 return -2;
2706 XSETFASTINT (w->window_end_vpos,
2707 XFASTINT (w->window_end_vpos) + scroll_amount);
2709 /* Before doing any scrolling, verify that point will be on frame. */
2710 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.vpos < height))
2712 if (PT <= xp.bufpos)
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);
2720 else
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);
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);
2734 if (stop_vpos - scroll_amount >= height
2735 || ep.bufpos == xp.bufpos)
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;
2748 else if (!scroll_amount)
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);
2757 else if (bp.bufpos == Z - end_unchanged)
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
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);
2794 else if (scroll_amount)
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;
2815 /* In any case, do not display past bottom of window */
2816 if (stop_vpos >= height)
2818 stop_vpos = height;
2819 scroll_amount = 0;
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);
2827 val.bytepos = pos_byte;
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)
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;
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 */
2868 if (vpos == height)
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);
2878 /* If scrolling made blank lines at window bottom,
2879 redisplay to fill those lines */
2880 if (scroll_amount < 0)
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;
2896 else if (xp.contin && xp.hpos != lmargin)
2898 val.hpos = xp.prevhpos - width + lmargin;
2899 val.tab_offset = xp.tab_offset + bp.prevhpos - width;
2900 DEC_BOTH (pos, pos_byte);
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)
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;
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;
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;
2940 /* Attempt to adjust end-of-text positions to new bottom line */
2941 if (scroll_amount)
2943 delta = height - xp.vpos;
2944 if (delta < 0
2945 || (delta > 0 && xp.bufpos <= ZV)
2946 || (delta == 0 && xp.hpos))
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);
2955 w->window_end_valid = Qnil;
2957 /* If point was not in a line that was displayed, find it */
2958 if (cursor_vpos < 0)
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),
2969 /* Admit failure if point is off frame now */
2970 if (val.vpos >= height)
2972 for (vpos = 0; vpos < height; vpos++)
2973 cancel_line (vpos + top, f);
2974 return 0;
2976 cursor_vpos = val.vpos + top;
2977 cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width);
2980 FRAME_CURSOR_X (f) = cursor_hpos;
2981 FRAME_CURSOR_Y (f) = cursor_vpos;
2983 if (debug_end_pos)
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),
2990 if (val.vpos != XFASTINT (w->window_end_vpos))
2991 abort ();
2992 if (XFASTINT (w->window_end_pos)
2993 != Z - val.bufpos)
2994 abort ();
2997 return 1;
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. */
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. */
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;
3020 #ifdef HAVE_FACES
3021 if (! FRAME_TERMCAP_P (f))
3022 while (n--)
3024 GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
3025 int facecode;
3026 unsigned int c = FAST_GLYPH_CHAR (glyph);
3028 if (c > MAX_CHAR)
3029 /* For an invalid character code, use space. */
3030 c = ' ';
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
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);
3045 if (to >= s)
3046 *to = FAST_MAKE_GLYPH (c, facecode);
3047 ++to;
3048 ++fp;
3050 else
3051 #endif
3052 while (n--)
3054 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
3055 ++to;
3056 ++fp;
3058 return to;
3061 /* Correct a glyph by replacing its specified user-level face code
3062 with a displayable computed face code. */
3064 static GLYPH
3065 fix_glyph (f, glyph, cface)
3066 FRAME_PTR f;
3067 GLYPH glyph;
3068 int cface;
3070 #ifdef HAVE_FACES
3071 if (! FRAME_TERMCAP_P (f))
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);
3077 #endif
3078 return glyph;
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. */
3087 static int
3088 pos_tab_offset (w, pos, pos_byte)
3089 struct window *w;
3090 register int pos, pos_byte;
3092 int opoint = PT;
3093 int opoint_byte = PT_BYTE;
3094 int col;
3095 int width = window_internal_width (w) - 1;
3097 if (pos == BEGV)
3098 return MINI_WINDOW_P (w) ? -minibuf_prompt_width : 0;
3100 if (FETCH_BYTE (pos_byte - 1) == '\n')
3101 return 0;
3103 TEMP_SET_PT_BOTH (pos, pos_byte);
3104 col = current_column ();
3105 TEMP_SET_PT_BOTH (opoint, opoint_byte);
3107 return col;
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.
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.
3121 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
3123 OVSTR_DONE is the number of chars of overlay before/after strings
3124 at this position which have already been processed.
3126 Display on position VPOS on the frame. It is origin 0, relative to
3127 the top of the frame, not W.
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 */
3133 struct position val_display_text_line;
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;
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));
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;
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);
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);
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)));
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);
3216 /* The next buffer location at which the face should change, due
3217 to overlays or text property changes. */
3218 int next_face_change;
3220 /* The next location where the `invisible' property changes, or an
3221 overlay starts or ends. */
3222 int next_boundary;
3224 /* The face we're currently using. */
3225 int current_face = 0;
3226 int i;
3228 XSETFASTINT (default_invis_vector[2], '.');
3229 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
3231 get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
3232 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
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))))
3242 region_beg = marker_position (current_buffer->mark);
3243 if (PT < region_beg)
3245 region_end = region_beg;
3246 region_beg = PT;
3248 else
3249 region_end = PT;
3250 w->region_showing = Qt;
3252 else
3254 region_beg = region_end = -1;
3255 w->region_showing = Qnil;
3258 if (MINI_WINDOW_P (w)
3259 && start == BEG
3260 && vpos == XFASTINT (w->top))
3262 if (! NILP (minibuf_prompt))
3264 int old_width = minibuf_prompt_width;
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;
3283 else
3284 minibuf_prompt_width = 0;
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)
3292 struct position *left_edge
3293 = compute_motion (pos, vpos, hpos, 0,
3294 ZV, vpos, 0,
3295 width, hscroll, taboffset, w);
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.
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)
3308 pos = left_edge->bufpos;
3309 pos_byte = left_edge->bytepos;
3310 DEC_BOTH (pos, pos_byte);
3311 hpos = left_edge->prevhpos;
3313 else
3315 pos = left_edge->bufpos;
3316 pos_byte = left_edge->bytepos;
3317 hpos = left_edge->hpos;
3321 hpos += WINDOW_LEFT_MARGIN (w);
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;
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);
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;
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)
3356 cursor_vpos = vpos;
3357 cursor_hpos = p1 - leftmargin;
3360 while (p1 < endp)
3362 if (pos >= pause)
3364 int e_t_h;
3366 while (pos == next_boundary)
3368 Lisp_Object position, limit, prop, ww;
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++)
3375 int ovlen;
3376 unsigned char *ovstr;
3377 ovlen = overlay_strings (pos, w, &ovstr);
3379 if (ovlen > 0)
3381 /* Skip the ones we did in a previous line. */
3382 ovstr += ovstr_done;
3383 ovlen -= ovstr_done;
3385 while (ovlen > 0)
3387 int charset, cols;
3388 GLYPH g;
3390 if (multibyte)
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));
3399 else
3401 c = *ovstr++, ovlen--, ovstr_done++;
3402 cols = 1;
3404 g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
3405 while (cols-- > 0)
3407 if (p1 >= leftmargin && p1 < endp)
3408 *p1 = g, g |= GLYPH_MASK_PADDING;
3409 p1++;
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;
3420 /* Did we reach point? Record the cursor location. */
3421 if (pos == PT && cursor_vpos < 0)
3423 cursor_vpos = vpos;
3424 cursor_hpos = p1 - leftmargin;
3427 if (pos >= ZV)
3428 break;
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)
3437 int limitpos = pos + 50;
3438 XSETFASTINT (limit, limitpos);
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))
3450 if (pos < PT && next_boundary >= PT)
3452 cursor_vpos = vpos;
3453 cursor_hpos = p1 - leftmargin;
3455 pos = next_boundary;
3456 pos_byte = CHAR_TO_BYTE (pos);
3457 last_invis_skip = pos;
3458 last_invis_prop = prop;
3462 /* Did we reach point? Record the cursor location. */
3463 if (pos == PT && cursor_vpos < 0)
3465 cursor_vpos = vpos;
3466 cursor_hpos = p1 - leftmargin;
3469 /* Did we hit the end of the visible region of the buffer?
3470 Stop here. */
3471 if (pos >= ZV)
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)
3477 int *p2x = &charstart[(p1 < leftmargin
3478 ? leftmargin : p1)
3479 - p1start];
3480 *p2x++ = pos;
3482 break;
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;
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)
3499 Lisp_Object args[3];
3501 args[0] = Qredisplay_end_trigger_functions;
3502 XSETWINDOW (args[1], w);
3503 XSETINT (args[2], e_t_h);
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);
3510 e_t_h = ZV;
3511 /* Notice if it changed the face of this character. */
3512 next_face_change = pos;
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)))
3522 int limit = pos + 50;
3524 current_face = compute_char_face (f, w, pos,
3525 region_beg, region_end,
3526 &next_face_change, limit, 0);
3528 #endif
3530 /* Compute the next place we need to stop
3531 and do something special; set PAUSE. */
3533 pause = ZV;
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;
3540 if (e_t_h < pause)
3541 pause = e_t_h;
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;
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;
3558 int temp = CHAR_TO_BYTE (pos);
3559 p = BYTE_POS_ADDR (temp);
3563 if (p1 >= endp)
3564 break;
3566 p1prev = p1;
3567 p1_wide_column_end = (GLYPH *) 0;
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)))
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);
3581 else if (c >= 040 && c < 0177)
3583 if (p1 >= leftmargin)
3584 *p1 = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
3585 p1++;
3587 else if (c == '\n')
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
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))
3603 int opoint = PT, opoint_byte = PT_BYTE;
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')
3611 pos--;
3612 pos_byte--;
3614 SET_PT_BOTH (opoint, opoint_byte);
3616 if (invis && selective_rlen > 0 && p1 >= leftmargin)
3618 #if 0
3619 GLYPH *cs, *csend;
3621 cs = charstart + (p1 - p1start);
3622 #endif
3624 p1 += selective_rlen;
3625 if (p1 - leftmargin > width)
3626 p1 = endp;
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
3639 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
3640 (p1 - p1prev), current_face, rev_dir_bit);
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)
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];
3656 *p2x++ = pos;
3657 while (p2x < p2)
3658 *p2x++ = -1;
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)
3665 if (p1 < leftmargin)
3666 p1 = leftmargin;
3667 while (p1 < endp)
3668 *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
3670 #endif
3672 break;
3674 else if (c == '\t')
3678 if (p1 >= leftmargin && p1 < endp)
3679 *p1 = MAKE_GLYPH (f, ' ', current_face) | rev_dir_bit;
3680 p1++;
3682 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
3683 % tab_width);
3685 else if (c == Ctl ('M') && selective == -1)
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);
3692 if (FETCH_BYTE (pos_byte - 1) == '\n')
3693 pos--, pos_byte--;
3694 if (selective_rlen > 0)
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);
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)
3707 if (p1 < leftmargin)
3708 p1 = leftmargin;
3709 while (p1 < endp)
3710 *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
3712 #endif
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)
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];
3727 *p2x++ = pos;
3728 while (p2x < p2)
3729 *p2x++ = -1;
3731 break;
3733 else if (c < 0200 && ctl_arrow)
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++;
3747 else
3749 /* C is a multibyte character or a character to be displayed
3750 by octral form. */
3751 int remaining_bytes = len;
3753 if (c >= 0400)
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;
3762 while (columns--)
3764 if (p1 >= leftmargin && p1 < endp)
3765 *p1 = g, g |= GLYPH_MASK_PADDING;
3766 p1++;
3768 p1_wide_column_end = p1;
3769 remaining_bytes -= CHARSET_BYTES (charset);
3772 while (remaining_bytes > 0)
3774 c = *(p - remaining_bytes--);
3776 if (p1 >= leftmargin && p1 < endp)
3777 *p1 = (fix_glyph
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++;
3800 prevpos = pos;
3801 prevpos_byte = pos_byte;
3802 pos++;
3803 pos_byte += len;
3805 /* Update charstarts for the character just output. */
3807 /* Do nothing here for a char that's entirely off the left edge. */
3808 if (p1 >= leftmargin)
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)
3815 int *p2x = &charstart[(p1prev < leftmargin
3816 ? leftmargin : p1prev)
3817 - p1start];
3818 int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
3820 if (p2x < p2)
3821 *p2x++ = prevpos;
3822 while (p2x < p2)
3823 *p2x++ = -1;
3828 val.hpos = - XINT (w->hscroll);
3829 if (val.hpos)
3830 val.hpos++;
3832 val.vpos = 1;
3834 lastpos = pos;
3835 lastpos_byte = pos_byte;
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;
3849 /* Handle continuation in middle of a character */
3850 /* by backing up over it */
3851 if (p1 > endp)
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)
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;
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
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. */
3880 GLYPH g = fix_glyph (f, truncate ? truncator : continuer, 0);
3881 while (p1prev < endp)
3882 *p1prev++ = g;
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;
3892 /* Keep in this line everything up to the continuation column. */
3893 p1 = endp;
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. */
3901 if (pos < ZV)
3903 if (FETCH_BYTE (pos_byte) == '\n')
3905 int opoint = PT, opoint_byte = PT_BYTE;
3907 /* If stopped due to a newline, start next line after it */
3908 SET_PT_BOTH (pos + 1, pos_byte + 1);
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);
3917 pos = PT, pos_byte = PT_BYTE;
3918 SET_PT_BOTH (opoint, opoint_byte);
3920 else
3921 /* Stopped due to right margin of window */
3923 if (truncate)
3925 int opoint = PT, opoint_byte = PT_BYTE;
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 */
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);
3940 lastpos = pos - (FETCH_BYTE (pos_byte - 1) == '\n');
3941 lastpos_byte = CHAR_TO_BYTE (lastpos);
3942 val.tab_offset = 0;
3944 else
3946 *p1++ = fix_glyph (f, continuer, 0);
3947 val.vpos = 0;
3948 DEC_BOTH (lastpos, lastpos_byte);
3949 val.tab_offset = taboffset + width;
3953 else
3954 val.tab_offset = 0;
3956 /* If point is at eol or in invisible text at eol,
3957 record its frame location now. */
3959 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
3961 cursor_vpos = vpos;
3962 cursor_hpos = p1 - leftmargin;
3965 if (cursor_vpos == vpos)
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)))
3972 if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
3973 && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
3975 FRAME_CURSOR_Y (f) = cursor_vpos;
3976 FRAME_CURSOR_X (f) = cursor_hpos;
3979 if (w == XWINDOW (selected_window))
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)
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;
3993 else
3994 this_line_bufpos = 0;
3999 /* If hscroll and line not empty, insert truncation-at-left marker */
4000 if (hscroll && lastpos != start)
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 */
4008 p1prev = leftmargin + 1;
4009 while (p1prev < p1 && *p1prev & GLYPH_MASK_PADDING)
4010 *p1prev++ = g;
4014 if (!WINDOW_RIGHTMOST_P (w))
4016 endp++;
4017 if (p1 < leftmargin) p1 = leftmargin;
4018 while (p1 < endp) *p1++ = SPACEGLYPH;
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))
4026 int i;
4027 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
4028 *p1++ = SPACEGLYPH;
4030 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4031 *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
4032 ? XINT (DISP_BORDER_GLYPH (dp))
4033 : '|');
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;
4039 /* If the start of this line is the overlay arrow-position,
4040 then put the arrow string into the display-line. */
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)
4048 int i, i_byte;
4049 int len = XSTRING (Voverlay_arrow_string)->size;
4050 int arrow_end;
4052 if (len > width)
4053 len = width;
4055 /* If the arrow string has text props, obey them when displaying. */
4056 for (i = 0, i_byte = 0; i < len; )
4058 int c;
4059 Lisp_Object face, ilisp;
4060 int newface;
4061 int idx = i;
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++];
4068 XSETFASTINT (ilisp, i);
4069 #ifdef HAVE_FACES
4070 if (FRAME_WINDOW_P (f))
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);
4076 #endif /* HAVE_FACES */
4077 leftmargin[idx] = c;
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;
4085 overlay_arrow_seen = 1;
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;
4095 /* Redisplay the menu bar in the frame for window W. */
4097 static void
4098 display_menu_bar (w)
4099 struct window *w;
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;
4108 #ifdef HAVE_NTGUI
4109 if (!NILP (Vwindow_system))
4110 return;
4111 #endif
4113 #ifdef USE_X_TOOLKIT
4114 if (FRAME_X_P (f))
4115 return;
4116 #endif /* USE_X_TOOLKIT */
4118 get_display_line (f, vpos, 0);
4120 items = FRAME_MENU_BAR_ITEMS (f);
4121 for (i = 0; i < XVECTOR (items)->size; i += 4)
4123 Lisp_Object pos, string;
4124 string = XVECTOR (items)->contents[i + 1];
4125 if (NILP (string))
4126 break;
4128 XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
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)
4139 int hpos1 = hpos + 1;
4140 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
4141 min (hpos1, maxendcol), maxendcol, 0);
4145 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
4146 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
4148 /* Fill out the line with spaces. */
4149 if (maxendcol > hpos)
4150 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol, 0);
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);
4158 /* Display the mode line for window w */
4160 static void
4161 display_mode_line (w)
4162 struct window *w;
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));
4169 line_number_displayed = 0;
4170 w->column_number_displayed = Qnil;
4172 get_display_line (f, vpos, left);
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);
4179 display_mode_element (w, vpos, left, 0, right, right,
4180 current_buffer->mode_line_format);
4182 pop_frame_kboard ();
4184 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
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)
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)
4198 padding = ptr[i] & GLYPH_MASK_PADDING;
4199 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1) | padding;
4202 else
4203 #endif
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;
4216 /* Contribute ELT to the mode line for window W.
4217 How it translates into text depends on its data type.
4219 VPOS is the position of the mode line being displayed.
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.
4225 DEPTH is the depth in recursion. It is used to prevent
4226 infinite recursion here.
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.
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.)
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. */
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;
4249 tail_recurse:
4250 if (depth > 10)
4251 goto invalid;
4253 depth++;
4255 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
4257 case Lisp_String:
4259 /* A string: output it and check for %-constructs within it. */
4260 register unsigned char c;
4261 register unsigned char *this = XSTRING (elt)->data;
4263 while (hpos < maxendcol && *this)
4265 unsigned char *last = this;
4266 while ((c = *this++) != '\0' && c != '%')
4268 if (this - 1 != last)
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));
4278 else /* c == '%' */
4280 register int minendcol;
4281 register int spec_width = 0;
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) */
4288 while ((c = *this++) >= '0' && c <= '9')
4290 spec_width = spec_width * 10 + (c - '0');
4293 minendcol = hpos + spec_width;
4294 if (minendcol > maxendcol)
4296 spec_width = maxendcol - hpos;
4297 minendcol = maxendcol;
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)
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);
4318 break;
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. */
4326 register Lisp_Object tem;
4327 tem = Fboundp (elt);
4328 if (!NILP (tem))
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))
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));
4344 /* Give up right away for nil or t. */
4345 else if (!EQ (tem, elt))
4346 { elt = tem; goto tail_recurse; }
4349 break;
4351 case Lisp_Cons:
4353 register Lisp_Object car, tem;
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))
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))
4374 tem = Fsymbol_value (car);
4375 if (!NILP (tem))
4376 { elt = XCONS (elt)->car; goto tail_recurse; }
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;
4389 else if (INTEGERP (car))
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)
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;
4412 goto tail_recurse;
4414 else if (STRINGP (car) || CONSP (car))
4416 register int limit = 50;
4417 /* LIMIT is to protect against circular lists. */
4418 while (CONSP (elt) && --limit > 0
4419 && hpos < maxendcol)
4421 hpos = display_mode_element (w, vpos, hpos, depth,
4422 hpos, maxendcol,
4423 XCONS (elt)->car);
4424 elt = XCONS (elt)->cdr;
4428 break;
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;
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;
4449 /* Write a null-terminated, right justified decimal representation of
4450 the positive integer D to BUF using a minimal field width WIDTH. */
4452 static void
4453 pint2str (buf, width, d)
4454 register char *buf;
4455 register int width;
4456 register int d;
4458 register char *p = buf;
4460 if (d <= 0)
4461 *p++ = '0';
4462 else
4463 while (d > 0)
4465 *p++ = d % 10 + '0';
4466 d /= 10;
4468 for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
4469 *p-- = '\0';
4470 while (p > buf)
4472 d = *buf;
4473 *buf++ = *p;
4474 *p-- = d;
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. */
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;
4488 Lisp_Object val;
4489 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
4491 val = coding_system;
4493 if (NILP (val)) /* Not yet decided. */
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. */
4501 else
4503 Lisp_Object eolvalue;
4505 eolvalue = Fget (coding_system, Qeol_type);
4507 while (!NILP (val) && SYMBOLP (val))
4509 val = Fget (val, Qcoding_system);
4510 if (NILP (eolvalue))
4511 eolvalue = Fget (val, Qeol_type);
4514 if (multibyte)
4515 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
4517 if (eol_flag)
4519 /* The EOL conversion we are using. */
4520 int eoltype;
4521 /* The EOL conversion that is normal on this system. */
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));
4533 /* Mention the EOL conversion if it is not the usual one. */
4534 *buf++ = eoltype;
4537 return buf;
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. */
4545 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
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;
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);
4559 obj = Qnil;
4560 if (maxwidth > FRAME_WIDTH (f))
4561 maxwidth = FRAME_WIDTH (f);
4563 switch (c)
4565 case '*':
4566 if (!NILP (b->read_only))
4567 return "%";
4568 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4569 return "*";
4570 return "-";
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 "-";
4580 case '&':
4581 /* This differs from %* in ignoring read-only-ness. */
4582 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
4583 return "*";
4584 return "-";
4586 case '%':
4587 return "%";
4589 case '[':
4591 int i;
4592 char *p;
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;
4603 case ']':
4605 int i;
4606 char *p;
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;
4617 case '-':
4619 register char *p;
4620 register int i;
4622 if (maxwidth < sizeof (lots_of_dashes))
4623 return lots_of_dashes;
4624 else
4626 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
4627 *p++ = '-';
4628 *p = '\0';
4630 return decode_mode_spec_buf;
4633 case 'b':
4634 obj = b->name;
4635 #if 0
4636 if (maxwidth >= 3 && STRING_BYTES (XSTRING (obj)) > maxwidth)
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;
4643 #endif
4644 break;
4646 case 'c':
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;
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";
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)
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;
4677 #endif
4678 break;
4680 case 'l':
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);
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;
4697 /* If the buffer is very big, don't waste time. */
4698 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
4700 w->base_line_pos = Qnil;
4701 w->base_line_number = Qnil;
4702 goto no_value;
4705 if (!NILP (w->base_line_number)
4706 && !NILP (w->base_line_pos)
4707 && XFASTINT (w->base_line_pos) <= startpos)
4709 line = XFASTINT (w->base_line_number);
4710 linepos = XFASTINT (w->base_line_pos);
4711 linepos_byte = buf_charpos_to_bytepos (b, linepos);
4713 else
4715 line = 1;
4716 linepos = BUF_BEGV (b);
4717 linepos_byte = BUF_BEGV_BYTE (b);
4720 /* Count lines from base line to window start position. */
4721 nlines = display_count_lines (linepos, linepos_byte,
4722 startpos_byte,
4723 startpos, &junk);
4725 topline = nlines + line;
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))
4733 XSETFASTINT (w->base_line_number, topline);
4734 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
4736 else if (nlines < height + 25 || nlines > height * 3 + 50
4737 || linepos == BUF_BEGV (b))
4739 int limit = BUF_BEGV (b);
4740 int limit_byte = BUF_BEGV_BYTE (b);
4741 int position;
4742 int distance = (height * 2 + 30) * 200;
4744 if (startpos - distance > limit)
4746 limit = startpos - distance;
4747 limit_byte = CHAR_TO_BYTE (limit);
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)
4759 w->base_line_pos = w->buffer;
4760 w->base_line_number = Qnil;
4761 goto no_value;
4764 XSETFASTINT (w->base_line_number, topline - nlines);
4765 XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
4768 /* Now count lines from the start pos to point. */
4769 nlines = display_count_lines (startpos, startpos_byte,
4770 PT_BYTE, PT, &junk);
4772 /* Record that we did display the line number. */
4773 line_number_displayed = 1;
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:
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;
4786 break;
4788 case 'm':
4789 obj = b->mode_name;
4790 break;
4792 case 'n':
4793 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
4794 return " Narrow";
4795 break;
4797 case 'p':
4799 int pos = marker_position (w->start);
4800 int total = BUF_ZV (b) - BUF_BEGV (b);
4802 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
4804 if (pos <= BUF_BEGV (b))
4805 return "All";
4806 else
4807 return "Bottom";
4809 else if (pos <= BUF_BEGV (b))
4810 return "Top";
4811 else
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;
4827 /* Display percentage of size above the bottom of the screen. */
4828 case 'P':
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);
4834 if (botpos >= BUF_ZV (b))
4836 if (toppos <= BUF_BEGV (b))
4837 return "All";
4838 else
4839 return "Bottom";
4841 else
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;
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;
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
4877 case 'z':
4878 /* coding-system (not including end-of-line format) */
4879 case 'Z':
4880 /* coding-system (including end-of-line type) */
4882 int eol_flag = (c == 'Z');
4883 char *p = decode_mode_spec_buf;
4885 if (! FRAME_WINDOW_P (f))
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);
4892 p = decode_mode_spec_coding (b->buffer_file_coding_system,
4893 p, eol_flag);
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))
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);
4905 #endif /* subprocesses */
4906 #endif /* 0 */
4907 *p = 0;
4908 return decode_mode_spec_buf;
4912 if (STRINGP (obj))
4913 return (char *) XSTRING (obj)->data;
4914 else
4915 return "";
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).
4922 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
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;
4929 register unsigned char *cursor;
4930 unsigned char *base;
4932 register int ceiling;
4933 register unsigned char *ceiling_addr;
4934 int orig_count = count;
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));
4941 if (count > 0)
4943 while (start_byte < limit_byte)
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)
4951 if (selective_display)
4952 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
4954 else
4955 while (*cursor != '\n' && ++cursor != ceiling_addr)
4958 if (cursor != ceiling_addr)
4960 if (--count == 0)
4962 start_byte += cursor - base + 1;
4963 *byte_pos_ptr = start_byte;
4964 return orig_count;
4966 else
4967 if (++cursor == ceiling_addr)
4968 break;
4970 else
4971 break;
4973 start_byte += cursor - base;
4976 else
4978 while (start_byte > limit_byte)
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)
4986 if (selective_display)
4987 while (--cursor != ceiling_addr
4988 && *cursor != '\n' && *cursor != 015)
4990 else
4991 while (--cursor != ceiling_addr && *cursor != '\n')
4994 if (cursor != ceiling_addr)
4996 if (++count == 0)
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;
5005 else
5006 break;
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;
5014 *byte_pos_ptr = limit_byte;
5016 if (count < 0)
5017 return - orig_count + count;
5018 return orig_count - count;
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.
5027 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
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.
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.
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.
5045 Returns ending hpos. */
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;
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);
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;
5076 if (multibyte == -1)
5077 multibyte = !NILP (current_buffer->enable_multibyte_characters);
5078 /* Now multibyte is 1 if we should display multibyte characters. */
5080 if (DISP_TABLE_P (Vstandard_display_table))
5081 dp = XCHAR_TABLE (Vstandard_display_table);
5083 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
5085 p1 = p1start;
5086 start = desired_glyphs->glyphs[vpos];
5088 if (obey_window_width)
5090 start += XFASTINT (w->left);
5091 end = start + window_width - (truncate != 0);
5093 if (!WINDOW_RIGHTMOST_P (w))
5095 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5097 int i;
5099 for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
5100 *end-- = ' ';
5102 else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5103 *end-- = '|';
5107 if (! obey_window_width
5108 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
5109 end = desired_glyphs->glyphs[vpos] + maxcol;
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;
5115 if (maxcol >= 0 && mincol > maxcol)
5116 mincol = maxcol;
5118 if (length < 0)
5119 /* We need this value for multibyte characters. */
5120 length = strlen (string);
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)
5127 int len;
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;
5136 string += len, length -= len;
5138 if (p1 >= end)
5140 truncated = 1;
5141 break;
5144 if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
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,
5151 else if (c >= 040 && c < 0177)
5153 if (p1 >= start)
5154 *p1 = c;
5155 p1++;
5157 else if (c == '\t')
5161 if (p1 >= start && p1 < end)
5162 *p1 = SPACEGLYPH;
5163 p1++;
5165 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
5167 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
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++;
5180 else if (len == 1)
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++;
5200 else
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));
5208 if (p1 < start)
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--)
5216 if (p1 < end)
5217 *p1 = SPACEGLYPH;
5218 p1++;
5221 else if (p1 + columns > end)
5223 /* Since we can't show the right part of C, fill all
5224 columns with TRUNCATE if TRUNCATE is specified. */
5225 if (truncate)
5227 while (p1 < end)
5228 *p1++ = fix_glyph (f, truncate, 0);
5229 /* And tell the line is truncated. */
5230 truncated = 1;
5232 break;
5234 else
5236 /* We can show the whole glyph of C. */
5237 *p1++ = c;
5238 while (--columns)
5239 *p1++ = c | GLYPH_MASK_PADDING;
5244 if (truncated)
5246 p1 = end;
5247 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
5249 else if (mincol >= 0)
5251 end = desired_glyphs->glyphs[vpos] + mincol;
5252 while (p1 < end)
5253 *p1++ = SPACEGLYPH;
5257 register int len = p1 - desired_glyphs->glyphs[vpos];
5259 if (len > desired_glyphs->used[vpos])
5260 desired_glyphs->used[vpos] = len;
5261 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
5263 return len;
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. */
5276 invisible_p (propval, list)
5277 register Lisp_Object propval;
5278 Lisp_Object list;
5280 register Lisp_Object tail, proptail;
5281 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
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;
5290 if (CONSP (propval))
5291 for (proptail = propval; CONSP (proptail);
5292 proptail = XCONS (proptail)->cdr)
5294 Lisp_Object propelt;
5295 propelt = XCONS (proptail)->car;
5296 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
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;
5306 return 0;
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. */
5318 invisible_ellipsis_p (propval, list)
5319 register Lisp_Object propval;
5320 Lisp_Object list;
5322 register Lisp_Object tail, proptail;
5323 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
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);
5330 if (CONSP (propval))
5331 for (proptail = propval; CONSP (proptail);
5332 proptail = XCONS (proptail)->cdr)
5334 Lisp_Object propelt;
5335 propelt = XCONS (proptail)->car;
5336 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
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);
5344 return 0;
5347 void
5348 syms_of_xdisp ()
5350 staticpro (&Qmenu_bar_update_hook);
5351 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
5353 staticpro (&Qoverriding_terminal_local_map);
5354 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
5356 staticpro (&Qoverriding_local_map);
5357 Qoverriding_local_map = intern ("overriding-local-map");
5359 staticpro (&Qwindow_scroll_functions);
5360 Qwindow_scroll_functions = intern ("window-scroll-functions");
5362 staticpro (&Qredisplay_end_trigger_functions);
5363 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
5365 staticpro (&last_arrow_position);
5366 staticpro (&last_arrow_string);
5367 last_arrow_position = Qnil;
5368 last_arrow_string = Qnil;
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;
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;
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;
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.");
5389 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
5390 "*Scroll up to this many lines, to bring point back on screen.");
5391 scroll_conservatively = 0;
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;
5399 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
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;
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;
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;
5416 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
5417 "*Non-nil means highlight region even in nonselected windows.");
5418 highlight_nonselected_windows = 0;
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'.");
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)));
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);
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;
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;
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;
5476 /* initialize the window system */
5477 void
5478 init_xdisp ()
5480 Lisp_Object root_window;
5481 #ifndef COMPILER_REGISTER_BUG
5482 register
5483 #endif /* COMPILER_REGISTER_BUG */
5484 struct window *mini_w;
5486 this_line_bufpos = 0;
5488 mini_w = XWINDOW (minibuf_window);
5489 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
5491 echo_area_glyphs = 0;
5492 previous_echo_glyphs = 0;
5494 if (!noninteractive)
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),
5501 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
5502 set_window_height (minibuf_window, 1, 0);
5504 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
5505 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));