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