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