]> code.delx.au - gnu-emacs/blob - src/xdisp.c
(decode_mode_spec): %+ makes % for unmodified RO buffer.
[gnu-emacs] / src / xdisp.c
1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1985, 86, 87, 88, 93, 94 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 #include <config.h>
22 #include <stdio.h>
23 /*#include <ctype.h>*/
24 #undef NULL
25 #include "lisp.h"
26 #include "frame.h"
27 #include "window.h"
28 #include "termchar.h"
29 #include "dispextern.h"
30 #include "buffer.h"
31 #include "indent.h"
32 #include "commands.h"
33 #include "macros.h"
34 #include "disptab.h"
35 #include "termhooks.h"
36 #include "intervals.h"
37
38 #ifdef USE_X_TOOLKIT
39 extern void set_frame_menubar ();
40 #endif
41
42 extern int interrupt_input;
43 extern int command_loop_level;
44
45 /* Nonzero means print newline before next minibuffer message. */
46
47 int noninteractive_need_newline;
48
49 #define min(a, b) ((a) < (b) ? (a) : (b))
50 #define max(a, b) ((a) > (b) ? (a) : (b))
51
52 /* The buffer position of the first character appearing
53 entirely or partially on the current frame line.
54 Or zero, which disables the optimization for the current frame line. */
55 static int this_line_bufpos;
56
57 /* Number of characters past the end of this line,
58 including the terminating newline */
59 static int this_line_endpos;
60
61 /* The vertical position of this frame line. */
62 static int this_line_vpos;
63
64 /* Hpos value for start of display on this frame line.
65 Usually zero, but negative if first character really began
66 on previous line */
67 static int this_line_start_hpos;
68
69 /* Buffer that this_line variables are describing. */
70 static struct buffer *this_line_buffer;
71
72 /* Set by try_window_id to the vpos of first of any lines
73 scrolled on to the bottom of the frame. These lines should
74 not be included in any general scroll computation. */
75 static int scroll_bottom_vpos;
76
77 /* Value of echo_area_glyphs when it was last acted on.
78 If this is nonzero, there is a message on the frame
79 in the minibuffer and it should be erased as soon
80 as it is no longer requested to appear. */
81 char *previous_echo_glyphs;
82
83 /* Nonzero means truncate lines in all windows less wide than the frame */
84 int truncate_partial_width_windows;
85
86 Lisp_Object Vglobal_mode_string;
87
88 /* Marker for where to display an arrow on top of the buffer text. */
89 Lisp_Object Voverlay_arrow_position;
90
91 /* String to display for the arrow. */
92 Lisp_Object Voverlay_arrow_string;
93
94 /* Values of those variables at last redisplay. */
95 static Lisp_Object last_arrow_position, last_arrow_string;
96
97 Lisp_Object Qmenu_bar_update_hook;
98
99 /* Nonzero if overlay arrow has been displayed once in this window. */
100 static int overlay_arrow_seen;
101
102 /* Nonzero means highlight the region even in nonselected windows. */
103 static int highlight_nonselected_windows;
104
105 /* If cursor motion alone moves point off frame,
106 Try scrolling this many lines up or down if that will bring it back. */
107 int scroll_step;
108
109 /* Nonzero if try_window_id has made blank lines at window bottom
110 since the last redisplay that paused */
111 static int blank_end_of_window;
112
113 /* Number of windows showing the buffer of the selected window.
114 keyboard.c refers to this. */
115 int buffer_shared;
116
117 /* display_text_line sets these to the frame position (origin 0) of point,
118 whether the window is selected or not.
119 Set one to -1 first to determine whether point was found afterwards. */
120
121 static int cursor_vpos;
122 static int cursor_hpos;
123
124 int debug_end_pos;
125
126 /* Nonzero means display mode line highlighted */
127 int mode_line_inverse_video;
128
129 static void echo_area_display ();
130 void mark_window_display_accurate ();
131 static void redisplay_windows ();
132 static void redisplay_window ();
133 static void update_menu_bars ();
134 static void update_menu_bar ();
135 static void try_window ();
136 static int try_window_id ();
137 static struct position *display_text_line ();
138 static void display_mode_line ();
139 static int display_mode_element ();
140 static char *fmodetrunc ();
141 static char *decode_mode_spec ();
142 static int display_string ();
143 static void display_menu_bar ();
144 static int display_count_lines ();
145
146 /* Prompt to display in front of the minibuffer contents */
147 Lisp_Object minibuf_prompt;
148
149 /* Width in columns of current minibuffer prompt. */
150 int minibuf_prompt_width;
151
152 /* Message to display instead of minibuffer contents
153 This is what the functions error and message make,
154 and command echoing uses it as well.
155 It overrides the minibuf_prompt as well as the buffer. */
156 char *echo_area_glyphs;
157
158 /* This is the length of the message in echo_area_glyphs. */
159 int echo_area_glyphs_length;
160
161 /* true iff we should redraw the mode lines on the next redisplay */
162 int update_mode_lines;
163
164 /* Smallest number of characters before the gap
165 at any time since last redisplay that finished.
166 Valid for current buffer when try_window_id can be called. */
167 int beg_unchanged;
168
169 /* Smallest number of characters after the gap
170 at any time since last redisplay that finished.
171 Valid for current buffer when try_window_id can be called. */
172 int end_unchanged;
173
174 /* MODIFF as of last redisplay that finished;
175 if it matches MODIFF, beg_unchanged and end_unchanged
176 contain no useful information */
177 int unchanged_modified;
178
179 /* Nonzero if head_clip or tail_clip of current buffer has changed
180 since last redisplay that finished */
181 int clip_changed;
182
183 /* Nonzero if window sizes or contents have changed
184 since last redisplay that finished */
185 int windows_or_buffers_changed;
186
187 /* Nonzero after display_mode_line if %l was used
188 and it displayed a line number. */
189 int line_number_displayed;
190
191 /* Maximum buffer size for which to display line numbers. */
192 int line_number_display_limit;
193 \f
194 /* Display an echo area message M with a specified length of LEN chars.
195 The string may include null characters. If m is 0, clear out any
196 existing message, and let the minibuffer text show through.
197 Do not pass text that is stored in a Lisp string. */
198
199 void
200 message2 (m, len)
201 char *m;
202 int len;
203 {
204 if (noninteractive)
205 {
206 if (noninteractive_need_newline)
207 putc ('\n', stderr);
208 noninteractive_need_newline = 0;
209 fwrite (m, len, 1, stderr);
210 if (cursor_in_echo_area == 0)
211 fprintf (stderr, "\n");
212 fflush (stderr);
213 }
214 /* A null message buffer means that the frame hasn't really been
215 initialized yet. Error messages get reported properly by
216 cmd_error, so this must be just an informative message; toss it. */
217 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
218 {
219 #ifdef MULTI_FRAME
220 Lisp_Object minibuf_frame;
221
222 choose_minibuf_frame ();
223 minibuf_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
224 FRAME_SAMPLE_VISIBILITY (XFRAME (minibuf_frame));
225 if (FRAME_VISIBLE_P (selected_frame)
226 && ! FRAME_VISIBLE_P (XFRAME (minibuf_frame)))
227 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (minibuf_window)));
228 #endif
229
230 if (m)
231 {
232 echo_area_glyphs = m;
233 echo_area_glyphs_length = len;
234 }
235 else
236 echo_area_glyphs = previous_echo_glyphs = 0;
237
238 do_pending_window_change ();
239 echo_area_display ();
240 update_frame (XFRAME (XWINDOW (minibuf_window)->frame), 1, 1);
241 do_pending_window_change ();
242 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
243 (*frame_up_to_date_hook) (XFRAME (XWINDOW (minibuf_window)->frame));
244 }
245 }
246
247 void
248 message1 (m)
249 char *m;
250 {
251 message2 (m, (m ? strlen (m) : 0));
252 }
253
254 /* Truncate what will be displayed in the echo area
255 the next time we display it--but don't redisplay it now. */
256
257 void
258 truncate_echo_area (len)
259 int len;
260 {
261 /* A null message buffer means that the frame hasn't really been
262 initialized yet. Error messages get reported properly by
263 cmd_error, so this must be just an informative message; toss it. */
264 if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
265 echo_area_glyphs_length = len;
266 }
267
268 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print;
269 zero if being used by message. */
270 int message_buf_print;
271
272 /* Dump an informative message to the minibuf. If m is 0, clear out
273 any existing message, and let the minibuffer text show through. */
274 /* VARARGS 1 */
275 void
276 message (m, a1, a2, a3)
277 char *m;
278 {
279 if (noninteractive)
280 {
281 if (m)
282 {
283 if (noninteractive_need_newline)
284 putc ('\n', stderr);
285 noninteractive_need_newline = 0;
286 fprintf (stderr, m, a1, a2, a3);
287 if (cursor_in_echo_area == 0)
288 fprintf (stderr, "\n");
289 fflush (stderr);
290 }
291 }
292 else if (INTERACTIVE)
293 {
294 /* The frame whose minibuffer we're going to display the message on.
295 It may be larger than the selected frame, so we need
296 to use its buffer, not the selected frame's buffer. */
297 FRAME_PTR echo_frame;
298 #ifdef MULTI_FRAME
299 choose_minibuf_frame ();
300 echo_frame = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
301 #else
302 echo_frame = selected_frame;
303 #endif
304
305 /* A null message buffer means that the frame hasn't really been
306 initialized yet. Error messages get reported properly by
307 cmd_error, so this must be just an informative message; toss it. */
308 if (FRAME_MESSAGE_BUF (echo_frame))
309 {
310 if (m)
311 {
312 int len;
313 #ifdef NO_ARG_ARRAY
314 int a[3];
315 a[0] = a1;
316 a[1] = a2;
317 a[2] = a3;
318
319 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
320 FRAME_WIDTH (echo_frame), m, 0, 3, a);
321 #else
322 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
323 FRAME_WIDTH (echo_frame), m, 0, 3, &a1);
324 #endif /* NO_ARG_ARRAY */
325
326 message2 (FRAME_MESSAGE_BUF (echo_frame), len);
327 }
328 else
329 message1 (0);
330
331 /* Print should start at the beginning of the message
332 buffer next time. */
333 message_buf_print = 0;
334 }
335 }
336 }
337
338 static void
339 echo_area_display ()
340 {
341 register int vpos;
342 FRAME_PTR f;
343
344 #ifdef MULTI_FRAME
345 choose_minibuf_frame ();
346 #endif
347
348 f = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
349
350 if (! FRAME_VISIBLE_P (f))
351 return;
352
353 if (frame_garbaged)
354 {
355 redraw_garbaged_frames ();
356 frame_garbaged = 0;
357 }
358
359 if (echo_area_glyphs || minibuf_level == 0)
360 {
361 vpos = XFASTINT (XWINDOW (minibuf_window)->top);
362 get_display_line (f, vpos, 0);
363 display_string (XWINDOW (minibuf_window), vpos,
364 echo_area_glyphs ? echo_area_glyphs : "",
365 echo_area_glyphs ? echo_area_glyphs_length : -1,
366 0, 0, 0, 0, FRAME_WIDTH (f));
367
368 /* If desired cursor location is on this line, put it at end of text */
369 if (FRAME_CURSOR_Y (f) == vpos)
370 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
371
372 /* Fill the rest of the minibuffer window with blank lines. */
373 {
374 int i;
375
376 for (i = vpos + 1;
377 i < vpos + XFASTINT (XWINDOW (minibuf_window)->height); i++)
378 {
379 get_display_line (f, i, 0);
380 display_string (XWINDOW (minibuf_window), vpos,
381 "", 0, 0, 0, 0, 0, FRAME_WIDTH (f));
382 }
383 }
384 }
385 else if (!EQ (minibuf_window, selected_window))
386 windows_or_buffers_changed++;
387
388 if (EQ (minibuf_window, selected_window))
389 this_line_bufpos = 0;
390
391 previous_echo_glyphs = echo_area_glyphs;
392 }
393
394 #ifdef HAVE_X_WINDOWS
395 /* I'm trying this out because I saw Unimpress use it, but it's
396 possible that this may mess adversely with some window managers. -jla
397
398 Wouldn't it be nice to use something like mode-line-format to
399 describe frame titles? -JimB */
400
401 /* Change the title of the frame to the name of the buffer displayed
402 in the currently selected window. Don't do this for minibuffer frames,
403 and don't do it when there's only one non-minibuffer frame. */
404 static void
405 x_consider_frame_title (frame)
406 Lisp_Object frame;
407 {
408 FRAME_PTR f = XFRAME (frame);
409
410 if (FRAME_X_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
411 {
412 Lisp_Object title;
413
414 title = Qnil;
415 if (! EQ (Fnext_frame (frame, Qnil), frame))
416 title = XBUFFER (XWINDOW (f->selected_window)->buffer)->name;
417
418 x_implicitly_set_name (f, title, Qnil);
419 }
420 }
421 #endif
422 \f
423 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
424 This can't be done in `redisplay' itself because it can call eval. */
425
426 void
427 prepare_menu_bars ()
428 {
429 register struct window *w = XWINDOW (selected_window);
430 int all_windows;
431
432 if (noninteractive)
433 return;
434
435 /* Set the visible flags for all frames.
436 Do this before checking for resized or garbaged frames; they want
437 to know if their frames are visible.
438 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
439 {
440 Lisp_Object tail, frame;
441
442 FOR_EACH_FRAME (tail, frame)
443 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
444 }
445
446 /* Notice any pending interrupt request to change frame size. */
447 do_pending_window_change ();
448
449 if (frame_garbaged)
450 {
451 redraw_garbaged_frames ();
452 frame_garbaged = 0;
453 }
454
455 all_windows = (update_mode_lines || buffer_shared > 1
456 || clip_changed || windows_or_buffers_changed);
457
458 #ifdef HAVE_X_WINDOWS
459 if (windows_or_buffers_changed)
460 {
461 Lisp_Object tail, frame;
462
463 FOR_EACH_FRAME (tail, frame)
464 if (FRAME_VISIBLE_P (XFRAME (frame))
465 || FRAME_ICONIFIED_P (XFRAME (frame)))
466 x_consider_frame_title (frame);
467 }
468 #endif
469
470 /* Update the menu bar item lists, if appropriate.
471 This has to be done before any actual redisplay
472 or generation of display lines. */
473 if (all_windows)
474 {
475 Lisp_Object tail, frame;
476
477 FOR_EACH_FRAME (tail, frame)
478 update_menu_bar (XFRAME (frame));
479 }
480 else
481 update_menu_bar (selected_frame);
482 }
483 \f
484 /* Do a frame update, taking possible shortcuts into account.
485 This is the main external entry point for redisplay.
486
487 If the last redisplay displayed an echo area message and that
488 message is no longer requested, we clear the echo area
489 or bring back the minibuffer if that is in use.
490
491 Do not call eval from within this function.
492 Calls to eval after the call to echo_area_display would confuse
493 the display_line mechanism and would cause a crash.
494 Calls to eval before that point will work most of the time,
495 but can still lose, because this function
496 can be called from signal handlers; with alarms set up;
497 or with synchronous processes running.
498
499 See Fcall_process; if you called it from here, it could be
500 entered recursively. */
501
502 static int do_verify_charstarts;
503
504 void
505 redisplay ()
506 {
507 register struct window *w = XWINDOW (selected_window);
508 register int pause;
509 int must_finish = 0;
510 int all_windows;
511 register int tlbufpos, tlendpos;
512 struct position pos;
513 extern int input_pending;
514
515 if (noninteractive)
516 return;
517
518 /* Set the visible flags for all frames.
519 Do this before checking for resized or garbaged frames; they want
520 to know if their frames are visible.
521 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
522 {
523 Lisp_Object tail, frame;
524
525 FOR_EACH_FRAME (tail, frame)
526 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
527 }
528
529 /* Notice any pending interrupt request to change frame size. */
530 do_pending_window_change ();
531
532 if (frame_garbaged)
533 {
534 redraw_garbaged_frames ();
535 frame_garbaged = 0;
536 }
537
538 if (clip_changed || windows_or_buffers_changed)
539 update_mode_lines++;
540
541 /* Detect case that we need to write a star in the mode line. */
542 if (XFASTINT (w->last_modified) < MODIFF
543 && XFASTINT (w->last_modified) <= current_buffer->save_modified)
544 {
545 w->update_mode_line = Qt;
546 if (buffer_shared > 1)
547 update_mode_lines++;
548 }
549
550 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
551
552 all_windows = update_mode_lines || buffer_shared > 1;
553
554 /* If specs for an arrow have changed, do thorough redisplay
555 to ensure we remove any arrow that should no longer exist. */
556 if (! EQ (Voverlay_arrow_position, last_arrow_position)
557 || ! EQ (Voverlay_arrow_string, last_arrow_string))
558 all_windows = 1, clip_changed = 1;
559
560 /* Normally the message* functions will have already displayed and
561 updated the echo area, but the frame may have been trashed, or
562 the update may have been preempted, so display the echo area
563 again here. */
564 if (echo_area_glyphs || previous_echo_glyphs)
565 {
566 echo_area_display ();
567 must_finish = 1;
568 }
569
570 /* If showing region, and mark has changed, must redisplay whole window. */
571 if (((!NILP (Vtransient_mark_mode)
572 && !NILP (XBUFFER (w->buffer)->mark_active))
573 != !NILP (w->region_showing))
574 || (!NILP (w->region_showing)
575 && !EQ (w->region_showing,
576 Fmarker_position (XBUFFER (w->buffer)->mark))))
577 this_line_bufpos = -1;
578
579 tlbufpos = this_line_bufpos;
580 tlendpos = this_line_endpos;
581 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
582 && FRAME_VISIBLE_P (XFRAME (w->frame))
583 /* Make sure recorded data applies to current buffer, etc */
584 && this_line_buffer == current_buffer
585 && current_buffer == XBUFFER (w->buffer)
586 && NILP (w->force_start)
587 /* Point must be on the line that we have info recorded about */
588 && PT >= tlbufpos
589 && PT <= Z - tlendpos
590 /* All text outside that line, including its final newline,
591 must be unchanged */
592 && (XFASTINT (w->last_modified) >= MODIFF
593 || (beg_unchanged >= tlbufpos - 1
594 && GPT >= tlbufpos
595 /* If selective display, can't optimize
596 if the changes start at the beginning of the line. */
597 && ((XTYPE (current_buffer->selective_display) == Lisp_Int
598 && XINT (current_buffer->selective_display) > 0
599 ? (beg_unchanged >= tlbufpos
600 && GPT > tlbufpos)
601 : 1))
602 && end_unchanged >= tlendpos
603 && Z - GPT >= tlendpos)))
604 {
605 if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n'
606 && (tlbufpos == ZV
607 || FETCH_CHAR (tlbufpos) == '\n'))
608 /* Former continuation line has disappeared by becoming empty */
609 goto cancel;
610 else if (XFASTINT (w->last_modified) < MODIFF
611 || MINI_WINDOW_P (w))
612 {
613 cursor_vpos = -1;
614 overlay_arrow_seen = 0;
615 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
616 pos_tab_offset (w, tlbufpos));
617 /* If line contains point, is not continued,
618 and ends at same distance from eob as before, we win */
619 if (cursor_vpos >= 0 && this_line_bufpos
620 && this_line_endpos == tlendpos)
621 {
622 /* If this is not the window's last line,
623 we must adjust the charstarts of the lines below. */
624 if (this_line_vpos + 1
625 < XFASTINT (w->top) + window_internal_height (w))
626 {
627 int left = XFASTINT (w->left);
628 int *charstart_next_line
629 = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
630 int i;
631 int adjust;
632
633 if (Z - tlendpos == ZV)
634 /* This line ends at end of (accessible part of) buffer.
635 There is no newline to count. */
636 adjust = Z - tlendpos - charstart_next_line[left];
637 else
638 /* This line ends in a newline.
639 Must take account of the newline and the rest of the
640 text that follows. */
641 adjust = Z - tlendpos + 1 - charstart_next_line[left];
642
643 adjust_window_charstarts (w, this_line_vpos, adjust);
644 }
645
646 if (XFASTINT (w->width) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
647 preserve_other_columns (w);
648 goto update;
649 }
650 else
651 goto cancel;
652 }
653 else if (PT == XFASTINT (w->last_point))
654 {
655 if (!must_finish)
656 {
657 do_pending_window_change ();
658 return;
659 }
660 goto update;
661 }
662 /* If highlighting the region, we can't just move the cursor. */
663 else if (! (!NILP (Vtransient_mark_mode)
664 && !NILP (current_buffer->mark_active))
665 && NILP (w->region_showing))
666 {
667 pos = *compute_motion (tlbufpos, 0,
668 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
669 PT, 2, - (1 << (SHORTBITS - 1)),
670 window_internal_width (w) - 1,
671 XINT (w->hscroll),
672 pos_tab_offset (w, tlbufpos), w);
673 if (pos.vpos < 1)
674 {
675 FRAME_CURSOR_X (selected_frame)
676 = XFASTINT (w->left) + max (pos.hpos, 0);
677 FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
678 goto update;
679 }
680 else
681 goto cancel;
682 }
683 cancel:
684 /* Text changed drastically or point moved off of line */
685 cancel_line (this_line_vpos, selected_frame);
686 }
687
688 this_line_bufpos = 0;
689 all_windows |= buffer_shared > 1;
690
691 if (all_windows)
692 {
693 Lisp_Object tail, frame;
694
695 #ifdef HAVE_X_WINDOWS
696 /* Since we're doing a thorough redisplay, we might as well
697 recompute all our display faces. */
698 clear_face_vector ();
699 #endif
700
701 /* Recompute # windows showing selected buffer.
702 This will be incremented each time such a window is displayed. */
703 buffer_shared = 0;
704
705 FOR_EACH_FRAME (tail, frame)
706 {
707 FRAME_PTR f = XFRAME (frame);
708
709 /* Mark all the scroll bars to be removed; we'll redeem the ones
710 we want when we redisplay their windows. */
711 if (condemn_scroll_bars_hook)
712 (*condemn_scroll_bars_hook) (f);
713
714 if (FRAME_VISIBLE_P (f))
715 redisplay_windows (FRAME_ROOT_WINDOW (f));
716
717 /* Any scroll bars which redisplay_windows should have nuked
718 should now go away. */
719 if (judge_scroll_bars_hook)
720 (*judge_scroll_bars_hook) (f);
721 }
722 }
723 else if (FRAME_VISIBLE_P (selected_frame))
724 {
725 redisplay_window (selected_window, 1);
726 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
727 preserve_other_columns (w);
728 }
729
730 update:
731 /* Prevent various kinds of signals during display update.
732 stdio is not robust about handling signals,
733 which can cause an apparent I/O error. */
734 if (interrupt_input)
735 unrequest_sigio ();
736 stop_polling ();
737
738 #ifdef MULTI_FRAME
739 if (all_windows)
740 {
741 Lisp_Object tail;
742
743 pause = 0;
744
745 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
746 {
747 FRAME_PTR f;
748
749 if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
750 continue;
751
752 f = XFRAME (XCONS (tail)->car);
753 if (FRAME_VISIBLE_P (f))
754 {
755 pause |= update_frame (f, 0, 0);
756 if (!pause)
757 {
758 mark_window_display_accurate (f->root_window, 1);
759 if (frame_up_to_date_hook != 0)
760 (*frame_up_to_date_hook) (f);
761 }
762 }
763 }
764 }
765 else
766 #endif /* MULTI_FRAME */
767 {
768 if (FRAME_VISIBLE_P (selected_frame))
769 pause = update_frame (selected_frame, 0, 0);
770
771 /* We may have called echo_area_display at the top of this
772 function. If the echo area is on another frame, that may
773 have put text on a frame other than the selected one, so the
774 above call to update_frame would not have caught it. Catch
775 it here. */
776 {
777 FRAME_PTR mini_frame
778 = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window)));
779
780 if (mini_frame != selected_frame)
781 pause |= update_frame (mini_frame, 0, 0);
782 }
783 }
784
785 /* If frame does not match, prevent doing single-line-update next time.
786 Also, don't forget to check every line to update the arrow. */
787 if (pause)
788 {
789 this_line_bufpos = 0;
790 if (!NILP (last_arrow_position))
791 {
792 last_arrow_position = Qt;
793 last_arrow_string = Qt;
794 }
795 /* If we pause after scrolling, some lines in current_frame
796 may be null, so preserve_other_columns won't be able to
797 preserve all the vertical-bar separators. So, avoid using it
798 in that case. */
799 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame))
800 update_mode_lines = 1;
801 }
802
803 /* Now text on frame agrees with windows, so
804 put info into the windows for partial redisplay to follow */
805
806 if (!pause)
807 {
808 register struct buffer *b = XBUFFER (w->buffer);
809
810 blank_end_of_window = 0;
811 clip_changed = 0;
812 unchanged_modified = BUF_MODIFF (b);
813 beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
814 end_unchanged = BUF_Z (b) - BUF_GPT (b);
815
816 XFASTINT (w->last_point) = BUF_PT (b);
817 XFASTINT (w->last_point_x) = FRAME_CURSOR_X (selected_frame);
818 XFASTINT (w->last_point_y) = FRAME_CURSOR_Y (selected_frame);
819
820 if (all_windows)
821 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
822 else
823 {
824 w->update_mode_line = Qnil;
825 XFASTINT (w->last_modified) = BUF_MODIFF (b);
826 w->window_end_valid = w->buffer;
827 last_arrow_position = Voverlay_arrow_position;
828 last_arrow_string = Voverlay_arrow_string;
829 if (do_verify_charstarts)
830 verify_charstarts (w);
831 if (frame_up_to_date_hook != 0)
832 (*frame_up_to_date_hook) (selected_frame);
833 }
834 update_mode_lines = 0;
835 windows_or_buffers_changed = 0;
836 }
837
838 /* Start SIGIO interrupts coming again.
839 Having them off during the code above
840 makes it less likely one will discard output,
841 but not impossible, since there might be stuff
842 in the system buffer here.
843 But it is much hairier to try to do anything about that. */
844
845 if (interrupt_input)
846 request_sigio ();
847 start_polling ();
848
849 /* Change frame size now if a change is pending. */
850 do_pending_window_change ();
851
852 /* If we just did a pending size change, redisplay again
853 for the new size. */
854 if (windows_or_buffers_changed && !pause)
855 redisplay ();
856 }
857
858 /* Redisplay, but leave alone any recent echo area message
859 unless another message has been requested in its place.
860
861 This is useful in situations where you need to redisplay but no
862 user action has occurred, making it inappropriate for the message
863 area to be cleared. See tracking_off and
864 wait_reading_process_input for examples of these situations. */
865
866 redisplay_preserve_echo_area ()
867 {
868 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
869 {
870 echo_area_glyphs = previous_echo_glyphs;
871 redisplay ();
872 echo_area_glyphs = 0;
873 }
874 else
875 redisplay ();
876 }
877
878 void
879 mark_window_display_accurate (window, flag)
880 Lisp_Object window;
881 int flag;
882 {
883 register struct window *w;
884
885 for (;!NILP (window); window = w->next)
886 {
887 if (XTYPE (window) != Lisp_Window) abort ();
888 w = XWINDOW (window);
889
890 if (!NILP (w->buffer))
891 {
892 XFASTINT (w->last_modified)
893 = !flag ? 0
894 : XBUFFER (w->buffer) == current_buffer
895 ? MODIFF : BUF_MODIFF (XBUFFER (w->buffer));
896
897 /* Record if we are showing a region, so can make sure to
898 update it fully at next redisplay. */
899 w->region_showing = (!NILP (Vtransient_mark_mode)
900 && !NILP (XBUFFER (w->buffer)->mark_active)
901 ? Fmarker_position (XBUFFER (w->buffer)->mark)
902 : Qnil);
903 }
904
905 w->window_end_valid = w->buffer;
906 w->update_mode_line = Qnil;
907
908 if (!NILP (w->vchild))
909 mark_window_display_accurate (w->vchild, flag);
910 if (!NILP (w->hchild))
911 mark_window_display_accurate (w->hchild, flag);
912 }
913
914 if (flag)
915 {
916 last_arrow_position = Voverlay_arrow_position;
917 last_arrow_string = Voverlay_arrow_string;
918 }
919 else
920 {
921 /* t is unequal to any useful value of Voverlay_arrow_... */
922 last_arrow_position = Qt;
923 last_arrow_string = Qt;
924 }
925 }
926 \f
927 /* Update the menu bar item list for frame F.
928 This has to be done before we start to fill in any display lines,
929 because it can call eval. */
930
931 static void
932 update_menu_bar (f)
933 FRAME_PTR f;
934 {
935 struct buffer *old = current_buffer;
936 Lisp_Object window;
937 register struct window *w;
938 window = FRAME_SELECTED_WINDOW (f);
939 w = XWINDOW (window);
940
941 if (update_mode_lines)
942 w->update_mode_line = Qt;
943
944 if (
945 #ifdef USE_X_TOOLKIT
946 FRAME_EXTERNAL_MENU_BAR (f)
947 #else
948 FRAME_MENU_BAR_LINES (f) > 0
949 #endif
950 )
951 {
952 /* If the user has switched buffers or windows, we need to
953 recompute to reflect the new bindings. But we'll
954 recompute when update_mode_lines is set too; that means
955 that people can use force-mode-line-update to request
956 that the menu bar be recomputed. The adverse effect on
957 the rest of the redisplay algorithm is about the same as
958 windows_or_buffers_changed anyway. */
959 if (windows_or_buffers_changed
960 || !NILP (w->update_mode_line)
961 || (XFASTINT (w->last_modified) < MODIFF
962 && (XFASTINT (w->last_modified)
963 <= XBUFFER (w->buffer)->save_modified)))
964 {
965 struct buffer *prev = current_buffer;
966 call1 (Vrun_hooks, Qmenu_bar_update_hook);
967 current_buffer = XBUFFER (w->buffer);
968 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
969 current_buffer = prev;
970 #ifdef USE_X_TOOLKIT
971 set_frame_menubar (f, 0);
972 #endif /* USE_X_TOOLKIT */
973 }
974 }
975 }
976 \f
977 int do_id = 1;
978
979 /* Redisplay WINDOW and its subwindows and siblings. */
980
981 static void
982 redisplay_windows (window)
983 Lisp_Object window;
984 {
985 for (; !NILP (window); window = XWINDOW (window)->next)
986 redisplay_window (window, 0);
987 }
988
989 /* Redisplay window WINDOW and its subwindows. */
990
991 static void
992 redisplay_window (window, just_this_one)
993 Lisp_Object window;
994 int just_this_one;
995 {
996 register struct window *w = XWINDOW (window);
997 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
998 int height;
999 register int lpoint = PT;
1000 struct buffer *old = current_buffer;
1001 register int width = window_internal_width (w) - 1;
1002 register int startp;
1003 register int hscroll = XINT (w->hscroll);
1004 struct position pos;
1005 int opoint = PT;
1006 int tem;
1007 int window_needs_modeline;
1008
1009 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
1010
1011 /* If this is a combination window, do its children; that's all. */
1012
1013 if (!NILP (w->vchild))
1014 {
1015 redisplay_windows (w->vchild);
1016 return;
1017 }
1018 if (!NILP (w->hchild))
1019 {
1020 redisplay_windows (w->hchild);
1021 return;
1022 }
1023 if (NILP (w->buffer))
1024 abort ();
1025
1026 height = window_internal_height (w);
1027
1028 if (MINI_WINDOW_P (w))
1029 {
1030 if (w == XWINDOW (minibuf_window))
1031 {
1032 if (echo_area_glyphs)
1033 /* We've already displayed the echo area glyphs, if any. */
1034 goto finish_scroll_bars;
1035 }
1036 else
1037 {
1038 /* This is a minibuffer, but it's not the currently active one, so
1039 clear it. */
1040 int vpos = XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
1041 int i;
1042
1043 for (i = 0; i < height; i++)
1044 {
1045 get_display_line (f, vpos + i, 0);
1046 display_string (w, vpos + i, "", 0, 0, 0, 1, 0, width);
1047 }
1048
1049 goto finish_scroll_bars;
1050 }
1051 }
1052
1053 if (update_mode_lines)
1054 w->update_mode_line = Qt;
1055
1056 /* Otherwise set up data on this window; select its buffer and point value */
1057
1058 current_buffer = XBUFFER (w->buffer);
1059 opoint = PT;
1060
1061 /* Count number of windows showing the selected buffer. */
1062
1063 if (!just_this_one
1064 && current_buffer == XBUFFER (XWINDOW (selected_window)->buffer))
1065 buffer_shared++;
1066
1067 /* POINT refers normally to the selected window.
1068 For any other window, set up appropriate value. */
1069
1070 if (!EQ (window, selected_window))
1071 {
1072 SET_PT (marker_position (w->pointm));
1073 if (PT < BEGV)
1074 {
1075 SET_PT (BEGV);
1076 Fset_marker (w->pointm, make_number (PT), Qnil);
1077 }
1078 else if (PT > (ZV - 1))
1079 {
1080 SET_PT (ZV);
1081 Fset_marker (w->pointm, make_number (PT), Qnil);
1082 }
1083 }
1084
1085 /* If window-start is screwed up, choose a new one. */
1086 if (XMARKER (w->start)->buffer != current_buffer)
1087 goto recenter;
1088
1089 startp = marker_position (w->start);
1090
1091 /* Handle case where place to start displaying has been specified,
1092 unless the specified location is outside the accessible range. */
1093 if (!NILP (w->force_start))
1094 {
1095 /* Forget any recorded base line for line number display. */
1096 w->base_line_number = Qnil;
1097 w->update_mode_line = Qt;
1098 w->force_start = Qnil;
1099 XFASTINT (w->last_modified) = 0;
1100 if (startp < BEGV) startp = BEGV;
1101 if (startp > ZV) startp = ZV;
1102 try_window (window, startp);
1103 if (cursor_vpos < 0)
1104 {
1105 /* ??? What should happen here if highlighting a region? */
1106 /* If point does not appear, move point so it does appear */
1107 pos = *compute_motion (startp, 0,
1108 ((EQ (window, minibuf_window) && startp == 1)
1109 ? minibuf_prompt_width : 0)
1110 +
1111 (hscroll ? 1 - hscroll : 0),
1112 ZV, height / 2,
1113 - (1 << (SHORTBITS - 1)),
1114 width, hscroll, pos_tab_offset (w, startp), w);
1115 SET_PT (pos.bufpos);
1116 if (w != XWINDOW (selected_window))
1117 Fset_marker (w->pointm, make_number (PT), Qnil);
1118 else
1119 {
1120 if (current_buffer == old)
1121 lpoint = PT;
1122 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1123 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1124 }
1125 }
1126 goto done;
1127 }
1128
1129 /* Handle case where text has not changed, only point,
1130 and it has not moved off the frame */
1131
1132 /* This code is not used for minibuffer for the sake of
1133 the case of redisplaying to replace an echo area message;
1134 since in that case the minibuffer contents per se are usually unchanged.
1135 This code is of no real use in the minibuffer since
1136 the handling of this_line_bufpos, etc.,
1137 in redisplay handles the same cases. */
1138
1139 if (XFASTINT (w->last_modified) >= MODIFF
1140 && PT >= startp && !clip_changed
1141 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f))
1142 /* Can't use this case if highlighting a region. */
1143 && !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
1144 && NILP (w->region_showing)
1145 /* If end pos is out of date, scroll bar and percentage will be wrong */
1146 && INTEGERP (w->window_end_vpos)
1147 && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
1148 && !EQ (window, minibuf_window))
1149 {
1150 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
1151 PT, height + 1, 10000, width, hscroll,
1152 pos_tab_offset (w, startp), w);
1153
1154 if (pos.vpos < height)
1155 {
1156 /* Ok, point is still on frame */
1157 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1158 {
1159 /* These variables are supposed to be origin 1 */
1160 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
1161 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
1162 }
1163 /* This doesn't do the trick, because if a window to the right of
1164 this one must be redisplayed, this does nothing because there
1165 is nothing in DesiredFrame yet, and then the other window is
1166 redisplayed, making likes that are empty in this window's columns.
1167 if (XFASTINT (w->width) != FRAME_WIDTH (f))
1168 preserve_my_columns (w);
1169 */
1170 goto done;
1171 }
1172 /* Don't bother trying redisplay with same start;
1173 we already know it will lose */
1174 }
1175 /* If current starting point was originally the beginning of a line
1176 but no longer is, find a new starting point. */
1177 else if (!NILP (w->start_at_line_beg)
1178 && !(startp == BEGV
1179 || FETCH_CHAR (startp - 1) == '\n'))
1180 {
1181 goto recenter;
1182 }
1183 else if (just_this_one && !MINI_WINDOW_P (w)
1184 && PT >= startp
1185 && XFASTINT (w->last_modified)
1186 /* or else vmotion on first line won't work. */
1187 && ! NILP (w->start_at_line_beg)
1188 && ! EQ (w->window_end_valid, Qnil)
1189 && do_id && !clip_changed
1190 && !blank_end_of_window
1191 && XFASTINT (w->width) == FRAME_WIDTH (f)
1192 /* Can't use this case if highlighting a region. */
1193 && !(!NILP (Vtransient_mark_mode)
1194 && !NILP (current_buffer->mark_active))
1195 && NILP (w->region_showing)
1196 && EQ (last_arrow_position, Voverlay_arrow_position)
1197 && EQ (last_arrow_string, Voverlay_arrow_string)
1198 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
1199 && tem != -2)
1200 {
1201 /* tem > 0 means success. tem == -1 means choose new start.
1202 tem == -2 means try again with same start,
1203 and nothing but whitespace follows the changed stuff.
1204 tem == 0 means try again with same start. */
1205 if (tem > 0)
1206 goto done;
1207 }
1208 else if (startp >= BEGV && startp <= ZV
1209 /* Avoid starting display at end of buffer! */
1210 && (startp < ZV || startp == BEGV
1211 || (XFASTINT (w->last_modified) >= MODIFF)))
1212 {
1213 /* Try to redisplay starting at same place as before */
1214 /* If point has not moved off frame, accept the results */
1215 try_window (window, startp);
1216 if (cursor_vpos >= 0)
1217 {
1218 if (!just_this_one || clip_changed || beg_unchanged < startp)
1219 /* Forget any recorded base line for line number display. */
1220 w->base_line_number = Qnil;
1221 goto done;
1222 }
1223 else
1224 cancel_my_columns (w);
1225 }
1226
1227 XFASTINT (w->last_modified) = 0;
1228 w->update_mode_line = Qt;
1229
1230 /* Try to scroll by specified few lines */
1231
1232 if (scroll_step && !clip_changed)
1233 {
1234 if (PT > startp)
1235 {
1236 pos = *vmotion (Z - XFASTINT (w->window_end_pos),
1237 scroll_step, width, hscroll, window);
1238 if (pos.vpos >= height)
1239 goto scroll_fail;
1240 }
1241
1242 pos = *vmotion (startp, PT < startp ? - scroll_step : scroll_step,
1243 width, hscroll, window);
1244
1245 if (PT >= pos.bufpos)
1246 {
1247 try_window (window, pos.bufpos);
1248 if (cursor_vpos >= 0)
1249 {
1250 if (!just_this_one || clip_changed || beg_unchanged < startp)
1251 /* Forget any recorded base line for line number display. */
1252 w->base_line_number = Qnil;
1253 goto done;
1254 }
1255 else
1256 cancel_my_columns (w);
1257 }
1258 scroll_fail: ;
1259 }
1260
1261 /* Finally, just choose place to start which centers point */
1262
1263 recenter:
1264 /* Forget any previously recorded base line for line number display. */
1265 w->base_line_number = Qnil;
1266
1267 pos = *vmotion (PT, - (height / 2), width, hscroll, window);
1268 try_window (window, pos.bufpos);
1269
1270 startp = marker_position (w->start);
1271 w->start_at_line_beg =
1272 (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil;
1273
1274 done:
1275 if ((!NILP (w->update_mode_line)
1276 /* If window not full width, must redo its mode line
1277 if the window to its side is being redone */
1278 || (!just_this_one && width < FRAME_WIDTH (f) - 1)
1279 || INTEGERP (w->base_line_pos))
1280 && height != XFASTINT (w->height))
1281 display_mode_line (w);
1282 if (! line_number_displayed
1283 && ! BUFFERP (w->base_line_pos))
1284 {
1285 w->base_line_pos = Qnil;
1286 w->base_line_number = Qnil;
1287 }
1288
1289 /* When we reach a frame's selected window, redo the frame's menu bar. */
1290 if (!NILP (w->update_mode_line)
1291 #ifdef USE_X_TOOLKIT
1292 && FRAME_EXTERNAL_MENU_BAR (f)
1293 #else
1294 && FRAME_MENU_BAR_LINES (f) > 0
1295 #endif
1296 && EQ (FRAME_SELECTED_WINDOW (f), window))
1297 display_menu_bar (w);
1298
1299 finish_scroll_bars:
1300 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
1301 {
1302 int start, end, whole;
1303
1304 /* Calculate the start and end positions for the current window.
1305 At some point, it would be nice to choose between scrollbars
1306 which reflect the whole buffer size, with special markers
1307 indicating narrowing, and scrollbars which reflect only the
1308 visible region.
1309
1310 Note that minibuffers sometimes aren't displaying any text. */
1311 if (! MINI_WINDOW_P (w)
1312 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
1313 {
1314 whole = ZV - BEGV;
1315 start = startp - BEGV;
1316 /* I don't think this is guaranteed to be right. For the
1317 moment, we'll pretend it is. */
1318 end = (Z - XINT (w->window_end_pos)) - BEGV;
1319
1320 if (end < start) end = start;
1321 if (whole < (end - start)) whole = end - start;
1322 }
1323 else
1324 start = end = whole = 0;
1325
1326 /* Indicate what this scroll bar ought to be displaying now. */
1327 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
1328
1329 /* Note that we actually used the scroll bar attached to this window,
1330 so it shouldn't be deleted at the end of redisplay. */
1331 (*redeem_scroll_bar_hook) (w);
1332 }
1333
1334 SET_PT (opoint);
1335 current_buffer = old;
1336 SET_PT (lpoint);
1337 }
1338 \f
1339 /* Do full redisplay on one window, starting at position `pos'. */
1340
1341 static void
1342 try_window (window, pos)
1343 Lisp_Object window;
1344 register int pos;
1345 {
1346 register struct window *w = XWINDOW (window);
1347 register int height = window_internal_height (w);
1348 register int vpos = XFASTINT (w->top);
1349 register int last_text_vpos = vpos;
1350 int tab_offset = pos_tab_offset (w, pos);
1351 FRAME_PTR f = XFRAME (w->frame);
1352 int width = window_internal_width (w) - 1;
1353 struct position val;
1354
1355 Fset_marker (w->start, make_number (pos), Qnil);
1356 cursor_vpos = -1;
1357 overlay_arrow_seen = 0;
1358 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
1359
1360 while (--height >= 0)
1361 {
1362 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
1363 tab_offset += width;
1364 if (val.vpos) tab_offset = 0;
1365 vpos++;
1366 if (pos != val.bufpos)
1367 last_text_vpos
1368 /* Next line, unless prev line ended in end of buffer with no cr */
1369 = vpos - (val.vpos && (FETCH_CHAR (val.bufpos - 1) != '\n'
1370 #ifdef USE_TEXT_PROPERTIES
1371 || ! NILP (Fget_char_property (val.bufpos-1,
1372 Qinvisible,
1373 window))
1374 #endif
1375 ));
1376 pos = val.bufpos;
1377 }
1378
1379 /* If last line is continued in middle of character,
1380 include the split character in the text considered on the frame */
1381 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
1382 pos++;
1383
1384 /* If bottom just moved off end of frame, change mode line percentage. */
1385 if (XFASTINT (w->window_end_pos) == 0
1386 && Z != pos)
1387 w->update_mode_line = Qt;
1388
1389 /* Say where last char on frame will be, once redisplay is finished. */
1390 XFASTINT (w->window_end_pos) = Z - pos;
1391 XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
1392 /* But that is not valid info until redisplay finishes. */
1393 w->window_end_valid = Qnil;
1394 }
1395 \f
1396 /* Try to redisplay when buffer is modified locally,
1397 computing insert/delete line to preserve text outside
1398 the bounds of the changes.
1399 Return 1 if successful, 0 if if cannot tell what to do,
1400 or -1 to tell caller to find a new window start,
1401 or -2 to tell caller to do normal redisplay with same window start. */
1402
1403 static int
1404 try_window_id (window)
1405 Lisp_Object window;
1406 {
1407 int pos;
1408 register struct window *w = XWINDOW (window);
1409 register int height = window_internal_height (w);
1410 FRAME_PTR f = XFRAME (w->frame);
1411 int top = XFASTINT (w->top);
1412 int start = marker_position (w->start);
1413 int width = window_internal_width (w) - 1;
1414 int hscroll = XINT (w->hscroll);
1415 int lmargin = hscroll > 0 ? 1 - hscroll : 0;
1416 register int vpos;
1417 register int i, tem;
1418 int last_text_vpos = 0;
1419 int stop_vpos;
1420 int selective
1421 = XTYPE (current_buffer->selective_display) == Lisp_Int
1422 ? XINT (current_buffer->selective_display)
1423 : !NILP (current_buffer->selective_display) ? -1 : 0;
1424
1425 struct position val, bp, ep, xp, pp;
1426 int scroll_amount = 0;
1427 int delta;
1428 int tab_offset, epto;
1429
1430 if (GPT - BEG < beg_unchanged)
1431 beg_unchanged = GPT - BEG;
1432 if (Z - GPT < end_unchanged)
1433 end_unchanged = Z - GPT;
1434
1435 if (beg_unchanged + BEG < start)
1436 return 0; /* Give up if changes go above top of window */
1437
1438 /* Find position before which nothing is changed. */
1439 bp = *compute_motion (start, 0, lmargin,
1440 min (ZV, beg_unchanged + BEG), height + 1, 0,
1441 width, hscroll, pos_tab_offset (w, start), w);
1442 if (bp.vpos >= height)
1443 {
1444 if (PT < bp.bufpos && !bp.contin)
1445 {
1446 /* All changes are below the frame, and point is on the frame.
1447 We don't need to change the frame at all.
1448 But we need to update window_end_pos to account for
1449 any change in buffer size. */
1450 bp = *compute_motion (start, 0, lmargin,
1451 Z, height, 0,
1452 width, hscroll, pos_tab_offset (w, start), w);
1453 XFASTINT (w->window_end_vpos) = height;
1454 XFASTINT (w->window_end_pos) = Z - bp.bufpos;
1455 return 1;
1456 }
1457 return 0;
1458 }
1459
1460 vpos = bp.vpos;
1461
1462 /* Find beginning of that frame line. Must display from there. */
1463 bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
1464
1465 pos = bp.bufpos;
1466 val.hpos = lmargin;
1467 if (pos < start)
1468 return -1;
1469
1470 /* If about to start displaying at the beginning of a continuation line,
1471 really start with previous frame line, in case it was not
1472 continued when last redisplayed */
1473 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
1474 ||
1475 /* Likewise if we have to worry about selective display. */
1476 (selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
1477 {
1478 bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
1479 --vpos;
1480 pos = bp.bufpos;
1481 }
1482
1483 if (bp.contin && bp.hpos != lmargin)
1484 {
1485 val.hpos = bp.prevhpos - width + lmargin;
1486 pos--;
1487 }
1488
1489 bp.vpos = vpos;
1490
1491 /* Find first visible newline after which no more is changed. */
1492 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
1493 if (selective > 0)
1494 while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
1495 tem = find_next_newline (tem, 1);
1496
1497 /* Compute the cursor position after that newline. */
1498 ep = *compute_motion (pos, vpos, val.hpos, tem,
1499 height, - (1 << (SHORTBITS - 1)),
1500 width, hscroll, pos_tab_offset (w, bp.bufpos), w);
1501
1502 /* If changes reach past the text available on the frame,
1503 just display rest of frame. */
1504 if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
1505 stop_vpos = height;
1506 else
1507 stop_vpos = ep.vpos;
1508
1509 /* If no newline before ep, the line ep is on includes some changes
1510 that must be displayed. Make sure we don't stop before it. */
1511 /* Also, if changes reach all the way until ep.bufpos,
1512 it is possible that something was deleted after the
1513 newline before it, so the following line must be redrawn. */
1514 if (stop_vpos == ep.vpos
1515 && (ep.bufpos == BEGV
1516 || FETCH_CHAR (ep.bufpos - 1) != '\n'
1517 || ep.bufpos == Z - end_unchanged))
1518 stop_vpos = ep.vpos + 1;
1519
1520 cursor_vpos = -1;
1521 overlay_arrow_seen = 0;
1522
1523 /* If changes do not reach to bottom of window,
1524 figure out how much to scroll the rest of the window */
1525 if (stop_vpos < height)
1526 {
1527 /* Now determine how far up or down the rest of the window has moved */
1528 epto = pos_tab_offset (w, ep.bufpos);
1529 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
1530 Z - XFASTINT (w->window_end_pos),
1531 10000, 0, width, hscroll, epto, w);
1532 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
1533
1534 /* Is everything on frame below the changes whitespace?
1535 If so, no scrolling is really necessary. */
1536 for (i = ep.bufpos; i < xp.bufpos; i++)
1537 {
1538 tem = FETCH_CHAR (i);
1539 if (tem != ' ' && tem != '\n' && tem != '\t')
1540 break;
1541 }
1542 if (i == xp.bufpos)
1543 return -2;
1544
1545 XFASTINT (w->window_end_vpos) += scroll_amount;
1546
1547 /* Before doing any scrolling, verify that point will be on frame. */
1548 if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
1549 {
1550 if (PT <= xp.bufpos)
1551 {
1552 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
1553 PT, height, - (1 << (SHORTBITS - 1)),
1554 width, hscroll, epto, w);
1555 }
1556 else
1557 {
1558 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
1559 PT, height, - (1 << (SHORTBITS - 1)),
1560 width, hscroll,
1561 pos_tab_offset (w, xp.bufpos), w);
1562 }
1563 if (pp.bufpos < PT || pp.vpos == height)
1564 return 0;
1565 cursor_vpos = pp.vpos + top;
1566 cursor_hpos = pp.hpos + XFASTINT (w->left);
1567 }
1568
1569 if (stop_vpos - scroll_amount >= height
1570 || ep.bufpos == xp.bufpos)
1571 {
1572 if (scroll_amount < 0)
1573 stop_vpos -= scroll_amount;
1574 scroll_amount = 0;
1575 /* In this path, we have altered window_end_vpos
1576 and not left it negative.
1577 We must make sure that, in case display is preempted
1578 before the frame changes to reflect what we do here,
1579 further updates will not come to try_window_id
1580 and assume the frame and window_end_vpos match. */
1581 blank_end_of_window = 1;
1582 }
1583 else if (!scroll_amount)
1584 {
1585 /* Even if we don't need to scroll, we must adjust the
1586 charstarts of subsequent lines (that we won't redisplay)
1587 according to the amount of text inserted or deleted. */
1588 int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1589 int adjust = ep.bufpos - oldpos;
1590 adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
1591 }
1592 else if (bp.bufpos == Z - end_unchanged)
1593 {
1594 /* If reprinting everything is nearly as fast as scrolling,
1595 don't bother scrolling. Can happen if lines are short. */
1596 if (scroll_cost (f, bp.vpos + top - scroll_amount,
1597 top + height - max (0, scroll_amount),
1598 scroll_amount)
1599 > xp.bufpos - bp.bufpos - 20)
1600 /* Return "try normal display with same window-start."
1601 Too bad we can't prevent further scroll-thinking. */
1602 return -2;
1603 /* If pure deletion, scroll up as many lines as possible.
1604 In common case of killing a line, this can save the
1605 following line from being overwritten by scrolling
1606 and therefore having to be redrawn. */
1607 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
1608 top + height - max (0, scroll_amount),
1609 scroll_amount, bp.bufpos);
1610 if (!tem)
1611 stop_vpos = height;
1612 else
1613 {
1614 /* scroll_frame_lines did not properly adjust subsequent
1615 lines' charstarts in the case where the text of the
1616 screen line at bp.vpos has changed.
1617 (This can happen in a deletion that ends in mid-line.)
1618 To adjust properly, we need to make things constent at
1619 the position ep.
1620 So do a second adjust to make that happen.
1621 Note that stop_vpos >= ep.vpos, so it is sufficient
1622 to update the charstarts for lines at ep.vpos and below. */
1623 int oldstart
1624 = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
1625 adjust_window_charstarts (w, ep.vpos + top - 1,
1626 ep.bufpos - oldstart);
1627 }
1628 }
1629 else if (scroll_amount)
1630 {
1631 /* If reprinting everything is nearly as fast as scrolling,
1632 don't bother scrolling. Can happen if lines are short. */
1633 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
1634 overestimate of cost of reprinting, since xp.bufpos
1635 would end up below the bottom of the window. */
1636 if (scroll_cost (f, ep.vpos + top - scroll_amount,
1637 top + height - max (0, scroll_amount),
1638 scroll_amount)
1639 > xp.bufpos - ep.bufpos - 20)
1640 /* Return "try normal display with same window-start."
1641 Too bad we can't prevent further scroll-thinking. */
1642 return -2;
1643 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
1644 top + height - max (0, scroll_amount),
1645 scroll_amount, ep.bufpos);
1646 if (!tem) stop_vpos = height;
1647 }
1648 }
1649
1650 /* In any case, do not display past bottom of window */
1651 if (stop_vpos >= height)
1652 {
1653 stop_vpos = height;
1654 scroll_amount = 0;
1655 }
1656
1657 /* Handle case where pos is before w->start --
1658 can happen if part of line had been clipped and is not clipped now */
1659 if (vpos == 0 && pos < marker_position (w->start))
1660 Fset_marker (w->start, make_number (pos), Qnil);
1661
1662 /* Redisplay the lines where the text was changed */
1663 last_text_vpos = vpos;
1664 tab_offset = pos_tab_offset (w, pos);
1665 /* If we are starting display in mid-character, correct tab_offset
1666 to account for passing the line that that character really starts in. */
1667 if (val.hpos < lmargin)
1668 tab_offset += width;
1669 while (vpos < stop_vpos)
1670 {
1671 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1672 tab_offset += width;
1673 if (val.vpos) tab_offset = 0;
1674 if (pos != val.bufpos)
1675 last_text_vpos
1676 /* Next line, unless prev line ended in end of buffer with no cr */
1677 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n');
1678 pos = val.bufpos;
1679 }
1680
1681 /* There are two cases:
1682 1) we have displayed down to the bottom of the window
1683 2) we have scrolled lines below stop_vpos by scroll_amount */
1684
1685 if (vpos == height)
1686 {
1687 /* If last line is continued in middle of character,
1688 include the split character in the text considered on the frame */
1689 if (val.hpos < lmargin)
1690 val.bufpos++;
1691 XFASTINT (w->window_end_vpos) = last_text_vpos;
1692 XFASTINT (w->window_end_pos) = Z - val.bufpos;
1693 }
1694
1695 /* If scrolling made blank lines at window bottom,
1696 redisplay to fill those lines */
1697 if (scroll_amount < 0)
1698 {
1699 /* Don't consider these lines for general-purpose scrolling.
1700 That will save time in the scrolling computation. */
1701 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
1702 vpos = xp.vpos;
1703 pos = xp.bufpos;
1704 val.hpos = lmargin;
1705 if (pos == ZV)
1706 vpos = height + scroll_amount;
1707 else if (xp.contin && xp.hpos != lmargin)
1708 {
1709 val.hpos = xp.prevhpos - width + lmargin;
1710 pos--;
1711 }
1712
1713 blank_end_of_window = 1;
1714 tab_offset = pos_tab_offset (w, pos);
1715 /* If we are starting display in mid-character, correct tab_offset
1716 to account for passing the line that that character starts in. */
1717 if (val.hpos < lmargin)
1718 tab_offset += width;
1719
1720 while (vpos < height)
1721 {
1722 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
1723 tab_offset += width;
1724 if (val.vpos) tab_offset = 0;
1725 pos = val.bufpos;
1726 }
1727
1728 /* Here is a case where display_text_line sets cursor_vpos wrong.
1729 Make it be fixed up, below. */
1730 if (xp.bufpos == ZV
1731 && xp.bufpos == PT)
1732 cursor_vpos = -1;
1733 }
1734
1735 /* If bottom just moved off end of frame, change mode line percentage. */
1736 if (XFASTINT (w->window_end_pos) == 0
1737 && Z != val.bufpos)
1738 w->update_mode_line = Qt;
1739
1740 /* Attempt to adjust end-of-text positions to new bottom line */
1741 if (scroll_amount)
1742 {
1743 delta = height - xp.vpos;
1744 if (delta < 0
1745 || (delta > 0 && xp.bufpos <= ZV)
1746 || (delta == 0 && xp.hpos))
1747 {
1748 val = *vmotion (Z - XFASTINT (w->window_end_pos),
1749 delta, width, hscroll, window);
1750 XFASTINT (w->window_end_pos) = Z - val.bufpos;
1751 XFASTINT (w->window_end_vpos) += val.vpos;
1752 }
1753 }
1754
1755 w->window_end_valid = Qnil;
1756
1757 /* If point was not in a line that was displayed, find it */
1758 if (cursor_vpos < 0)
1759 {
1760 val = *compute_motion (start, 0, lmargin, PT, 10000, 10000,
1761 width, hscroll, pos_tab_offset (w, start), w);
1762 /* Admit failure if point is off frame now */
1763 if (val.vpos >= height)
1764 {
1765 for (vpos = 0; vpos < height; vpos++)
1766 cancel_line (vpos + top, f);
1767 return 0;
1768 }
1769 cursor_vpos = val.vpos + top;
1770 cursor_hpos = val.hpos + XFASTINT (w->left);
1771 }
1772
1773 FRAME_CURSOR_X (f) = max (0, cursor_hpos);
1774 FRAME_CURSOR_Y (f) = cursor_vpos;
1775
1776 if (debug_end_pos)
1777 {
1778 val = *compute_motion (start, 0, lmargin, ZV,
1779 height, - (1 << (SHORTBITS - 1)),
1780 width, hscroll, pos_tab_offset (w, start), w);
1781 if (val.vpos != XFASTINT (w->window_end_vpos))
1782 abort ();
1783 if (XFASTINT (w->window_end_pos)
1784 != Z - val.bufpos)
1785 abort ();
1786 }
1787
1788 return 1;
1789 }
1790 \f
1791 /* Mark a section of BUF as modified, but only for the sake of redisplay.
1792 This is useful for recording changes to overlays.
1793
1794 We increment the buffer's modification timestamp and set the
1795 redisplay caches (windows_or_buffers_changed, beg_unchanged, etc)
1796 as if the region of text between START and END had been modified;
1797 the redisplay code will check this against the windows' timestamps,
1798 and redraw the appropriate area of the buffer.
1799
1800 However, if the buffer is unmodified, we bump the last-save
1801 timestamp as well, so that incrementing the timestamp doesn't fool
1802 Emacs into thinking that the buffer's text has been modified.
1803
1804 Tweaking the timestamps shouldn't hurt the first-modification
1805 timestamps recorded in the undo records; those values aren't
1806 written until just before a real text modification is made, so they
1807 will never catch the timestamp value just before this function gets
1808 called. */
1809
1810 void
1811 redisplay_region (buf, start, end)
1812 struct buffer *buf;
1813 int start, end;
1814 {
1815 if (start == end)
1816 return;
1817
1818 if (start > end)
1819 {
1820 int temp = start;
1821 start = end; end = temp;
1822 }
1823
1824 /* If this is a buffer not in the selected window,
1825 we must do other windows. */
1826 if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
1827 windows_or_buffers_changed = 1;
1828 /* If it's not current, we can't use beg_unchanged, end_unchanged for it. */
1829 else if (buf != current_buffer)
1830 windows_or_buffers_changed = 1;
1831 /* If multiple windows show this buffer, we must do other windows. */
1832 else if (buffer_shared > 1)
1833 windows_or_buffers_changed = 1;
1834 else
1835 {
1836 if (unchanged_modified == MODIFF)
1837 {
1838 beg_unchanged = start - BEG;
1839 end_unchanged = Z - end;
1840 }
1841 else
1842 {
1843 if (Z - end < end_unchanged)
1844 end_unchanged = Z - end;
1845 if (start - BEG < beg_unchanged)
1846 beg_unchanged = start - BEG;
1847 }
1848 }
1849
1850 /* Increment the buffer's time stamp, but also increment the save
1851 and autosave timestamps, so as not to screw up that timekeeping. */
1852 if (BUF_MODIFF (buf) == buf->save_modified)
1853 buf->save_modified++;
1854 if (BUF_MODIFF (buf) == buf->auto_save_modified)
1855 buf->auto_save_modified++;
1856
1857 BUF_MODIFF (buf) ++;
1858 }
1859
1860 \f
1861 /* Copy LEN glyphs starting address FROM to the rope TO.
1862 But don't actually copy the parts that would come in before S.
1863 Value is TO, advanced past the copied data.
1864 F is the frame we are displaying in. */
1865
1866 static GLYPH *
1867 copy_part_of_rope (f, to, s, from, len, face)
1868 FRAME_PTR f;
1869 register GLYPH *to; /* Copy to here. */
1870 register GLYPH *s; /* Starting point. */
1871 Lisp_Object *from; /* Data to copy. */
1872 int len;
1873 int face; /* Face to apply to glyphs which don't specify one. */
1874 {
1875 int n = len;
1876 register Lisp_Object *fp = from;
1877 /* These cache the results of the last call to compute_glyph_face. */
1878 int last_code = -1;
1879 int last_merged = 0;
1880
1881 #ifdef HAVE_X_WINDOWS
1882 if (! FRAME_TERMCAP_P (f))
1883 while (n--)
1884 {
1885 int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
1886 int facecode;
1887
1888 if (FAST_GLYPH_FACE (glyph) == 0)
1889 /* If GLYPH has no face code, use FACE. */
1890 facecode = face;
1891 else if (FAST_GLYPH_FACE (glyph) == last_code)
1892 /* If it's same as previous glyph, use same result. */
1893 facecode = last_merged;
1894 else
1895 {
1896 /* Merge this glyph's face and remember the result. */
1897 last_code = FAST_GLYPH_FACE (glyph);
1898 last_merged = facecode = compute_glyph_face (f, last_code, face);
1899 }
1900
1901 if (to >= s)
1902 *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
1903 ++to;
1904 ++fp;
1905 }
1906 else
1907 #endif
1908 while (n--)
1909 {
1910 if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
1911 ++to;
1912 ++fp;
1913 }
1914 return to;
1915 }
1916
1917 /* Correct a glyph by replacing its specified user-level face code
1918 with a displayable computed face code. */
1919
1920 static GLYPH
1921 fix_glyph (f, glyph, cface)
1922 FRAME_PTR f;
1923 GLYPH glyph;
1924 int cface;
1925 {
1926 #ifdef HAVE_X_WINDOWS
1927 if (! FRAME_TERMCAP_P (f))
1928 {
1929 if (FAST_GLYPH_FACE (glyph) != 0)
1930 cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
1931 glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
1932 }
1933 #endif
1934 return glyph;
1935 }
1936 \f
1937 /* Display one line of window w, starting at position START in W's buffer.
1938 Display starting at horizontal position HPOS, which is normally zero
1939 or negative. A negative value causes output up to hpos = 0 to be discarded.
1940 This is done for negative hscroll, or when this is a continuation line
1941 and the continuation occurred in the middle of a multi-column character.
1942
1943 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
1944
1945 Display on position VPOS on the frame. (origin 0).
1946
1947 Returns a STRUCT POSITION giving character to start next line with
1948 and where to display it, including a zero or negative hpos.
1949 The vpos field is not really a vpos; it is 1 unless the line is continued */
1950
1951 struct position val_display_text_line;
1952
1953 static struct position *
1954 display_text_line (w, start, vpos, hpos, taboffset)
1955 struct window *w;
1956 int start;
1957 int vpos;
1958 int hpos;
1959 int taboffset;
1960 {
1961 register int pos = start;
1962 register int c;
1963 register GLYPH *p1;
1964 int end;
1965 register int pause;
1966 register unsigned char *p;
1967 GLYPH *endp;
1968 register GLYPH *leftmargin;
1969 register GLYPH *p1prev = 0;
1970 register GLYPH *p1start;
1971 int *charstart;
1972 FRAME_PTR f = XFRAME (w->frame);
1973 int tab_width = XINT (current_buffer->tab_width);
1974 int ctl_arrow = !NILP (current_buffer->ctl_arrow);
1975 int width = window_internal_width (w) - 1;
1976 struct position val;
1977 int lastpos;
1978 int invis;
1979 int hscroll = XINT (w->hscroll);
1980 int truncate = (hscroll
1981 || (truncate_partial_width_windows
1982 && XFASTINT (w->width) < FRAME_WIDTH (f))
1983 || !NILP (current_buffer->truncate_lines));
1984
1985 /* 1 if we should highlight the region. */
1986 int highlight_region
1987 = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
1988 int region_beg, region_end;
1989
1990 int selective
1991 = XTYPE (current_buffer->selective_display) == Lisp_Int
1992 ? XINT (current_buffer->selective_display)
1993 : !NILP (current_buffer->selective_display) ? -1 : 0;
1994 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
1995 register struct Lisp_Vector *dp = window_display_table (w);
1996
1997 Lisp_Object default_invis_vector[3];
1998 /* Nonzero means display something where there are invisible lines.
1999 The precise value is the number of glyphs to display. */
2000 int selective_rlen
2001 = (selective && dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
2002 ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
2003 : selective && !NILP (current_buffer->selective_display_ellipses)
2004 ? 3 : 0);
2005 /* This is the sequence of Lisp objects to display
2006 when there are invisible lines. */
2007 Lisp_Object *invis_vector_contents
2008 = (dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
2009 ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
2010 : default_invis_vector);
2011
2012 GLYPH truncator = (dp == 0 || XTYPE (DISP_TRUNC_GLYPH (dp)) != Lisp_Int
2013 ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
2014 GLYPH continuer = (dp == 0 || XTYPE (DISP_CONTINUE_GLYPH (dp)) != Lisp_Int
2015 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
2016
2017 /* The next buffer location at which the face should change, due
2018 to overlays or text property changes. */
2019 int next_face_change;
2020
2021 #ifdef USE_TEXT_PROPERTIES
2022 /* The next location where the `invisible' property changes */
2023 int next_invisible;
2024 #endif
2025
2026 /* The face we're currently using. */
2027 int current_face = 0;
2028 int i;
2029
2030 XFASTINT (default_invis_vector[2]) = '.';
2031 default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
2032
2033 hpos += XFASTINT (w->left);
2034 get_display_line (f, vpos, XFASTINT (w->left));
2035 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
2036
2037 /* Show where to highlight the region. */
2038 if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
2039 /* Maybe highlight only in selected window. */
2040 && (highlight_nonselected_windows
2041 || w == XWINDOW (selected_window)))
2042 {
2043 region_beg = marker_position (current_buffer->mark);
2044 if (PT < region_beg)
2045 {
2046 region_end = region_beg;
2047 region_beg = PT;
2048 }
2049 else
2050 region_end = PT;
2051 w->region_showing = Qt;
2052 }
2053 else
2054 region_beg = region_end = -1;
2055
2056 if (MINI_WINDOW_P (w) && start == 1
2057 && vpos == XFASTINT (w->top))
2058 {
2059 if (! NILP (minibuf_prompt))
2060 {
2061 minibuf_prompt_width
2062 = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
2063 XSTRING (minibuf_prompt)->size, hpos,
2064 (!truncate ? continuer : truncator),
2065 1, -1, -1)
2066 - hpos);
2067 hpos += minibuf_prompt_width;
2068 }
2069 else
2070 minibuf_prompt_width = 0;
2071 }
2072
2073 desired_glyphs->bufp[vpos] = pos;
2074 p1 = desired_glyphs->glyphs[vpos] + hpos;
2075 p1start = p1;
2076 charstart = desired_glyphs->charstarts[vpos] + hpos;
2077 /* In case we don't ever write anything into it... */
2078 desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
2079 end = ZV;
2080 leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
2081 endp = leftmargin + width;
2082
2083 /* Arrange the overlays nicely for our purposes. Usually, we call
2084 display_text_line on only one line at a time, in which case this
2085 can't really hurt too much, or we call it on lines which appear
2086 one after another in the buffer, in which case all calls to
2087 recenter_overlay_lists but the first will be pretty cheap. */
2088 recenter_overlay_lists (current_buffer, pos);
2089
2090 /* Loop generating characters.
2091 Stop at end of buffer, before newline,
2092 if reach or pass continuation column,
2093 or at face change. */
2094 pause = pos;
2095 next_face_change = pos;
2096 #ifdef USE_TEXT_PROPERTIES
2097 next_invisible = pos;
2098 #endif
2099 while (1)
2100 {
2101 /* Record which glyph starts a character,
2102 and the character position of that character. */
2103 if (p1 >= leftmargin)
2104 charstart[p1 - p1start] = pos;
2105
2106 if (p1 >= endp)
2107 break;
2108
2109 p1prev = p1;
2110 if (pos >= pause)
2111 {
2112 /* Did we hit the end of the visible region of the buffer?
2113 Stop here. */
2114 if (pos >= end)
2115 break;
2116
2117 /* Did we reach point? Record the cursor location. */
2118 if (pos == PT && cursor_vpos < 0)
2119 {
2120 cursor_vpos = vpos;
2121 cursor_hpos = p1 - leftmargin;
2122 }
2123
2124 #ifdef USE_TEXT_PROPERTIES
2125 /* if the `invisible' property is set to t, we can skip to
2126 the next property change */
2127 while (pos == next_invisible && pos < end)
2128 {
2129 Lisp_Object position, limit, endpos, prop, ww;
2130 XFASTINT (position) = pos;
2131 XSET (ww, Lisp_Window, w);
2132 prop = Fget_char_property (position, Qinvisible, ww);
2133 /* This is just an estimate to give reasonable
2134 performance; nothing should go wrong if it is too small. */
2135 limit = Fnext_overlay_change (position);
2136 if (XFASTINT (limit) > pos + 50)
2137 XFASTINT (limit) = pos + 50;
2138 endpos = Fnext_single_property_change (position, Qinvisible,
2139 Fcurrent_buffer (), limit);
2140 if (INTEGERP (endpos))
2141 next_invisible = XINT (endpos);
2142 else
2143 next_invisible = end;
2144 if (! NILP (prop))
2145 {
2146 if (pos < PT && next_invisible >= PT)
2147 {
2148 cursor_vpos = vpos;
2149 cursor_hpos = p1 - leftmargin;
2150 }
2151 pos = next_invisible;
2152 }
2153 }
2154 if (pos >= end)
2155 break;
2156 #endif
2157
2158 #ifdef HAVE_X_WINDOWS
2159 /* Did we hit a face change? Figure out what face we should
2160 use now. We also hit this the first time through the
2161 loop, to see what face we should start with. */
2162 if (pos >= next_face_change && FRAME_X_P (f))
2163 current_face = compute_char_face (f, w, pos,
2164 region_beg, region_end,
2165 &next_face_change, pos + 50, 0);
2166 #endif
2167
2168 pause = end;
2169
2170 #ifdef USE_TEXT_PROPERTIES
2171 if (pos < next_invisible && next_invisible < pause)
2172 pause = next_invisible;
2173 #endif
2174 if (pos < next_face_change && next_face_change < pause)
2175 pause = next_face_change;
2176
2177 /* Wouldn't you hate to read the next line to someone over
2178 the phone? */
2179 if (pos < PT && PT < pause)
2180 pause = PT;
2181 if (pos < GPT && GPT < pause)
2182 pause = GPT;
2183
2184 p = &FETCH_CHAR (pos);
2185 }
2186 c = *p++;
2187 if (c >= 040 && c < 0177
2188 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
2189 {
2190 if (p1 >= leftmargin)
2191 *p1 = MAKE_GLYPH (f, c, current_face);
2192 p1++;
2193 }
2194 else if (c == '\n')
2195 {
2196 invis = 0;
2197 while (pos + 1 < end
2198 && selective > 0
2199 && indented_beyond_p (pos + 1, selective))
2200 {
2201 invis = 1;
2202 pos = find_next_newline (pos + 1, 1);
2203 if (FETCH_CHAR (pos - 1) == '\n')
2204 pos--;
2205 }
2206 if (invis && selective_rlen > 0 && p1 >= leftmargin)
2207 {
2208 p1 += selective_rlen;
2209 if (p1 - leftmargin > width)
2210 p1 = endp;
2211 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2212 (p1 - p1prev), current_face);
2213 }
2214 #ifdef HAVE_X_WINDOWS
2215 /* Draw the face of the newline character as extending all the
2216 way to the end of the frame line. */
2217 if (current_face)
2218 {
2219 if (p1 < leftmargin)
2220 p1 = leftmargin;
2221 while (p1 < endp)
2222 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2223 }
2224 #endif
2225 break;
2226 }
2227 else if (c == '\t')
2228 {
2229 do
2230 {
2231 if (p1 >= leftmargin && p1 < endp)
2232 *p1 = MAKE_GLYPH (f, ' ', current_face);
2233 p1++;
2234 }
2235 while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
2236 % tab_width);
2237 }
2238 else if (c == Ctl ('M') && selective == -1)
2239 {
2240 pos = find_next_newline (pos, 1);
2241 if (FETCH_CHAR (pos - 1) == '\n')
2242 pos--;
2243 if (selective_rlen > 0)
2244 {
2245 p1 += selective_rlen;
2246 if (p1 - leftmargin > width)
2247 p1 = endp;
2248 copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
2249 (p1 - p1prev), current_face);
2250 }
2251 #ifdef HAVE_X_WINDOWS
2252 /* Draw the face of the newline character as extending all the
2253 way to the end of the frame line. */
2254 if (current_face)
2255 {
2256 if (p1 < leftmargin)
2257 p1 = leftmargin;
2258 while (p1 < endp)
2259 *p1++ = FAST_MAKE_GLYPH (' ', current_face);
2260 }
2261 #endif
2262 break;
2263 }
2264 else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
2265 {
2266 p1 = copy_part_of_rope (f, p1, leftmargin,
2267 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
2268 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
2269 current_face);
2270 }
2271 else if (c < 0200 && ctl_arrow)
2272 {
2273 if (p1 >= leftmargin)
2274 *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
2275 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
2276 current_face);
2277 p1++;
2278 if (p1 >= leftmargin && p1 < endp)
2279 *p1 = MAKE_GLYPH (f, c ^ 0100, current_face);
2280 p1++;
2281 }
2282 else
2283 {
2284 if (p1 >= leftmargin)
2285 *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
2286 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
2287 current_face);
2288 p1++;
2289 if (p1 >= leftmargin && p1 < endp)
2290 *p1 = MAKE_GLYPH (f, (c >> 6) + '0', current_face);
2291 p1++;
2292 if (p1 >= leftmargin && p1 < endp)
2293 *p1 = MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face);
2294 p1++;
2295 if (p1 >= leftmargin && p1 < endp)
2296 *p1 = MAKE_GLYPH (f, (7 & c) + '0', current_face);
2297 p1++;
2298 }
2299
2300 /* Do nothing here for a char that's entirely off the left edge. */
2301 if (p1 >= leftmargin)
2302 {
2303 /* For all the glyphs occupied by this character, except for the
2304 first, store -1 in charstarts. */
2305 if (p1 != p1prev)
2306 {
2307 int *p2x = &charstart[p1prev - p1start];
2308 int *p2 = &charstart[p1 - p1start];
2309
2310 /* The window's left column should always
2311 contain a character position.
2312 And don't clobber anything to the left of that. */
2313 if (p1prev < leftmargin)
2314 {
2315 p2x = charstart + (leftmargin - p1start);
2316 *p2x = pos;
2317 }
2318
2319 /* This loop skips over the char p2x initially points to. */
2320 while (++p2x < p2)
2321 *p2x = -1;
2322 }
2323 }
2324
2325 pos++;
2326 }
2327
2328 val.hpos = - XINT (w->hscroll);
2329 if (val.hpos)
2330 val.hpos++;
2331
2332 val.vpos = 1;
2333
2334 lastpos = pos;
2335
2336 /* Store 0 in this charstart line for the positions where
2337 there is no character. But do leave what was recorded
2338 for the character that ended the line. */
2339 /* Add 1 in the endtest to compensate for the fact that ENDP was
2340 made from WIDTH, which is 1 less than the window's actual
2341 internal width. */
2342 i = p1 - p1start + 1;
2343 if (p1 < leftmargin)
2344 i += leftmargin - p1;
2345 for (; i < endp - p1start + 1; i++)
2346 charstart[i] = 0;
2347
2348 /* Handle continuation in middle of a character */
2349 /* by backing up over it */
2350 if (p1 > endp)
2351 {
2352 /* Don't back up if we never actually displayed any text.
2353 This occurs when the minibuffer prompt takes up the whole line. */
2354 if (p1prev)
2355 {
2356 /* Start the next line with that same character */
2357 pos--;
2358 /* but at negative hpos, to skip the columns output on this line. */
2359 val.hpos += p1prev - endp;
2360 }
2361
2362 /* Keep in this line everything up to the continuation column. */
2363 p1 = endp;
2364 }
2365
2366 /* Finish deciding which character to start the next line on,
2367 and what hpos to start it at.
2368 Also set `lastpos' to the last position which counts as "on this line"
2369 for cursor-positioning. */
2370
2371 if (pos < ZV)
2372 {
2373 if (FETCH_CHAR (pos) == '\n')
2374 {
2375 /* If stopped due to a newline, start next line after it */
2376 pos++;
2377 /* Check again for hidden lines, in case the newline occurred exactly
2378 at the right margin. */
2379 while (pos < ZV && selective > 0
2380 && indented_beyond_p (pos, selective))
2381 pos = find_next_newline (pos, 1);
2382 }
2383 else
2384 /* Stopped due to right margin of window */
2385 {
2386 if (truncate)
2387 {
2388 *p1++ = fix_glyph (f, truncator, 0);
2389 /* Truncating => start next line after next newline,
2390 and point is on this line if it is before the newline,
2391 and skip none of first char of next line */
2392 do
2393 pos = find_next_newline (pos, 1);
2394 while (pos < ZV && selective > 0
2395 && indented_beyond_p (pos, selective));
2396 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
2397
2398 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n');
2399 }
2400 else
2401 {
2402 *p1++ = fix_glyph (f, continuer, 0);
2403 val.vpos = 0;
2404 lastpos--;
2405 }
2406 }
2407 }
2408
2409 /* If point is at eol or in invisible text at eol,
2410 record its frame location now. */
2411
2412 if (start <= PT && PT <= lastpos && cursor_vpos < 0)
2413 {
2414 cursor_vpos = vpos;
2415 cursor_hpos = p1 - leftmargin;
2416 }
2417
2418 if (cursor_vpos == vpos)
2419 {
2420 if (cursor_hpos < 0) cursor_hpos = 0;
2421 if (cursor_hpos > width) cursor_hpos = width;
2422 cursor_hpos += XFASTINT (w->left);
2423 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
2424 {
2425 FRAME_CURSOR_Y (f) = cursor_vpos;
2426 FRAME_CURSOR_X (f) = cursor_hpos;
2427
2428 if (w == XWINDOW (selected_window))
2429 {
2430 /* Line is not continued and did not start
2431 in middle of character */
2432 if ((hpos - XFASTINT (w->left)
2433 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
2434 && val.vpos)
2435 {
2436 this_line_bufpos = start;
2437 this_line_buffer = current_buffer;
2438 this_line_vpos = cursor_vpos;
2439 this_line_start_hpos = hpos;
2440 this_line_endpos = Z - lastpos;
2441 }
2442 else
2443 this_line_bufpos = 0;
2444 }
2445 }
2446 }
2447
2448 /* If hscroll and line not empty, insert truncation-at-left marker */
2449 if (hscroll && lastpos != start)
2450 {
2451 *leftmargin = fix_glyph (f, truncator, 0);
2452 if (p1 <= leftmargin)
2453 p1 = leftmargin + 1;
2454 }
2455
2456 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f))
2457 {
2458 endp++;
2459 if (p1 < leftmargin) p1 = leftmargin;
2460 while (p1 < endp) *p1++ = SPACEGLYPH;
2461
2462 /* Don't draw vertical bars if we're using scroll bars. They're
2463 covered up by the scroll bars, and it's distracting to see
2464 them when the scroll bar windows are flickering around to be
2465 reconfigured. */
2466 *p1++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
2467 ? ' ' : '|');
2468 }
2469 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
2470 p1 - desired_glyphs->glyphs[vpos]);
2471 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
2472
2473 /* If the start of this line is the overlay arrow-position,
2474 then put the arrow string into the display-line. */
2475
2476 if (XTYPE (Voverlay_arrow_position) == Lisp_Marker
2477 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
2478 && start == marker_position (Voverlay_arrow_position)
2479 && XTYPE (Voverlay_arrow_string) == Lisp_String
2480 && ! overlay_arrow_seen)
2481 {
2482 unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
2483 int i;
2484 int len = XSTRING (Voverlay_arrow_string)->size;
2485 int arrow_end;
2486
2487 if (len > width)
2488 len = width;
2489 for (i = 0; i < len; i++)
2490 leftmargin[i] = p[i];
2491
2492 /* Bug in SunOS 4.1.1 compiler requires this intermediate variable. */
2493 arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
2494 if (desired_glyphs->used[vpos] < arrow_end)
2495 desired_glyphs->used[vpos] = arrow_end;
2496
2497 overlay_arrow_seen = 1;
2498 }
2499
2500 val.bufpos = pos;
2501 val_display_text_line = val;
2502 return &val_display_text_line;
2503 }
2504 \f
2505 /* Redisplay the menu bar in the frame for window W. */
2506
2507 static void
2508 display_menu_bar (w)
2509 struct window *w;
2510 {
2511 Lisp_Object items, tail;
2512 register int vpos = 0;
2513 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2514 int maxendcol = FRAME_WIDTH (f);
2515 int hpos = 0;
2516 int i;
2517
2518 #ifndef USE_X_TOOLKIT
2519 if (FRAME_MENU_BAR_LINES (f) <= 0)
2520 return;
2521
2522 get_display_line (f, vpos, 0);
2523
2524 items = FRAME_MENU_BAR_ITEMS (f);
2525 for (i = 0; i < XVECTOR (items)->size; i += 3)
2526 {
2527 Lisp_Object pos, string;
2528 string = XVECTOR (items)->contents[i + 1];
2529 if (NILP (string))
2530 break;
2531
2532 XFASTINT (XVECTOR (items)->contents[i + 2]) = hpos;
2533
2534 if (hpos < maxendcol)
2535 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
2536 XSTRING (string)->data,
2537 XSTRING (string)->size,
2538 hpos, 0, 0, hpos, maxendcol);
2539 /* Put a gap of 3 spaces between items. */
2540 if (hpos < maxendcol)
2541 {
2542 int hpos1 = hpos + 3;
2543 hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
2544 min (hpos1, maxendcol), maxendcol);
2545 }
2546 }
2547
2548 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
2549 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2550
2551 /* Fill out the line with spaces. */
2552 if (maxendcol > hpos)
2553 hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
2554
2555 /* Clear the rest of the lines allocated to the menu bar. */
2556 vpos++;
2557 while (vpos < FRAME_MENU_BAR_LINES (f))
2558 get_display_line (f, vpos++, 0);
2559 #endif /* not USE_X_TOOLKIT */
2560 }
2561 \f
2562 /* Display the mode line for window w */
2563
2564 static void
2565 display_mode_line (w)
2566 struct window *w;
2567 {
2568 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
2569 register int left = XFASTINT (w->left);
2570 register int right = XFASTINT (w->width) + left;
2571 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2572
2573 line_number_displayed = 0;
2574
2575 get_display_line (f, vpos, left);
2576 display_mode_element (w, vpos, left, 0, right, right,
2577 current_buffer->mode_line_format);
2578 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
2579
2580 /* Make the mode line inverse video if the entire line
2581 is made of mode lines.
2582 I.e. if this window is full width,
2583 or if it is the child of a full width window
2584 (which implies that that window is split side-by-side
2585 and the rest of this line is mode lines of the sibling windows). */
2586 if (XFASTINT (w->width) == FRAME_WIDTH (f)
2587 || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
2588 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
2589 #ifdef HAVE_X_WINDOWS
2590 else if (! FRAME_TERMCAP_P (f))
2591 {
2592 /* For a partial width window, explicitly set face of each glyph. */
2593 int i;
2594 GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
2595 for (i = left; i < right; ++i)
2596 ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1);
2597 }
2598 #endif
2599 }
2600
2601 /* Contribute ELT to the mode line for window W.
2602 How it translates into text depends on its data type.
2603
2604 VPOS is the position of the mode line being displayed.
2605
2606 HPOS is the position (absolute on frame) where this element's text
2607 should start. The output is truncated automatically at the right
2608 edge of window W.
2609
2610 DEPTH is the depth in recursion. It is used to prevent
2611 infinite recursion here.
2612
2613 MINENDCOL is the hpos before which the element may not end.
2614 The element is padded at the right with spaces if nec
2615 to reach this column.
2616
2617 MAXENDCOL is the hpos past which this element may not extend.
2618 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
2619 (This is necessary to make nested padding and truncation work.)
2620
2621 Returns the hpos of the end of the text generated by ELT.
2622 The next element will receive that value as its HPOS arg,
2623 so as to concatenate the elements. */
2624
2625 static int
2626 display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2627 struct window *w;
2628 register int vpos, hpos;
2629 int depth;
2630 int minendcol;
2631 register int maxendcol;
2632 register Lisp_Object elt;
2633 {
2634 tail_recurse:
2635 if (depth > 10)
2636 goto invalid;
2637
2638 depth++;
2639
2640 #ifdef SWITCH_ENUM_BUG
2641 switch ((int) XTYPE (elt))
2642 #else
2643 switch (XTYPE (elt))
2644 #endif
2645 {
2646 case Lisp_String:
2647 {
2648 /* A string: output it and check for %-constructs within it. */
2649 register unsigned char c;
2650 register unsigned char *this = XSTRING (elt)->data;
2651
2652 while (hpos < maxendcol && *this)
2653 {
2654 unsigned char *last = this;
2655 while ((c = *this++) != '\0' && c != '%')
2656 ;
2657 if (this - 1 != last)
2658 {
2659 register int lim = --this - last + hpos;
2660 hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
2661 hpos, min (lim, maxendcol));
2662 }
2663 else /* c == '%' */
2664 {
2665 register int spec_width = 0;
2666
2667 /* We can't allow -ve args due to the "%-" construct */
2668 /* Argument specifies minwidth but not maxwidth
2669 (maxwidth can be specified by
2670 (<negative-number> . <stuff>) mode-line elements) */
2671
2672 while ((c = *this++) >= '0' && c <= '9')
2673 {
2674 spec_width = spec_width * 10 + (c - '0');
2675 }
2676
2677 spec_width += hpos;
2678 if (spec_width > maxendcol)
2679 spec_width = maxendcol;
2680
2681 if (c == 'M')
2682 hpos = display_mode_element (w, vpos, hpos, depth,
2683 spec_width, maxendcol,
2684 Vglobal_mode_string);
2685 else if (c != 0)
2686 hpos = display_string (w, vpos,
2687 decode_mode_spec (w, c,
2688 maxendcol - hpos),
2689 -1,
2690 hpos, 0, 1, spec_width, maxendcol);
2691 }
2692 }
2693 }
2694 break;
2695
2696 case Lisp_Symbol:
2697 /* A symbol: process the value of the symbol recursively
2698 as if it appeared here directly. Avoid error if symbol void.
2699 Special case: if value of symbol is a string, output the string
2700 literally. */
2701 {
2702 register Lisp_Object tem;
2703 tem = Fboundp (elt);
2704 if (!NILP (tem))
2705 {
2706 tem = Fsymbol_value (elt);
2707 /* If value is a string, output that string literally:
2708 don't check for % within it. */
2709 if (XTYPE (tem) == Lisp_String)
2710 hpos = display_string (w, vpos, XSTRING (tem)->data,
2711 XSTRING (tem)->size,
2712 hpos, 0, 1, minendcol, maxendcol);
2713 /* Give up right away for nil or t. */
2714 else if (!EQ (tem, elt))
2715 { elt = tem; goto tail_recurse; }
2716 }
2717 }
2718 break;
2719
2720 case Lisp_Cons:
2721 {
2722 register Lisp_Object car, tem;
2723
2724 /* A cons cell: three distinct cases.
2725 If first element is a string or a cons, process all the elements
2726 and effectively concatenate them.
2727 If first element is a negative number, truncate displaying cdr to
2728 at most that many characters. If positive, pad (with spaces)
2729 to at least that many characters.
2730 If first element is a symbol, process the cadr or caddr recursively
2731 according to whether the symbol's value is non-nil or nil. */
2732 car = XCONS (elt)->car;
2733 if (XTYPE (car) == Lisp_Symbol)
2734 {
2735 tem = Fboundp (car);
2736 elt = XCONS (elt)->cdr;
2737 if (XTYPE (elt) != Lisp_Cons)
2738 goto invalid;
2739 /* elt is now the cdr, and we know it is a cons cell.
2740 Use its car if CAR has a non-nil value. */
2741 if (!NILP (tem))
2742 {
2743 tem = Fsymbol_value (car);
2744 if (!NILP (tem))
2745 { elt = XCONS (elt)->car; goto tail_recurse; }
2746 }
2747 /* Symbol's value is nil (or symbol is unbound)
2748 Get the cddr of the original list
2749 and if possible find the caddr and use that. */
2750 elt = XCONS (elt)->cdr;
2751 if (NILP (elt))
2752 break;
2753 else if (XTYPE (elt) != Lisp_Cons)
2754 goto invalid;
2755 elt = XCONS (elt)->car;
2756 goto tail_recurse;
2757 }
2758 else if (XTYPE (car) == Lisp_Int)
2759 {
2760 register int lim = XINT (car);
2761 elt = XCONS (elt)->cdr;
2762 if (lim < 0)
2763 /* Negative int means reduce maximum width.
2764 DO NOT change MINENDCOL here!
2765 (20 -10 . foo) should truncate foo to 10 col
2766 and then pad to 20. */
2767 maxendcol = min (maxendcol, hpos - lim);
2768 else if (lim > 0)
2769 {
2770 /* Padding specified. Don't let it be more than
2771 current maximum. */
2772 lim += hpos;
2773 if (lim > maxendcol)
2774 lim = maxendcol;
2775 /* If that's more padding than already wanted, queue it.
2776 But don't reduce padding already specified even if
2777 that is beyond the current truncation point. */
2778 if (lim > minendcol)
2779 minendcol = lim;
2780 }
2781 goto tail_recurse;
2782 }
2783 else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons)
2784 {
2785 register int limit = 50;
2786 /* LIMIT is to protect against circular lists. */
2787 while (XTYPE (elt) == Lisp_Cons && --limit > 0
2788 && hpos < maxendcol)
2789 {
2790 hpos = display_mode_element (w, vpos, hpos, depth,
2791 hpos, maxendcol,
2792 XCONS (elt)->car);
2793 elt = XCONS (elt)->cdr;
2794 }
2795 }
2796 }
2797 break;
2798
2799 default:
2800 invalid:
2801 return (display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
2802 minendcol, maxendcol));
2803 }
2804
2805 end:
2806 if (minendcol > hpos)
2807 hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
2808 return hpos;
2809 }
2810 \f
2811 /* Return a string for the output of a mode line %-spec for window W,
2812 generated by character C and width MAXWIDTH. */
2813
2814 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
2815
2816 static char *
2817 decode_mode_spec (w, c, maxwidth)
2818 struct window *w;
2819 register char c;
2820 register int maxwidth;
2821 {
2822 Lisp_Object obj;
2823 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2824 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
2825
2826 obj = Qnil;
2827 if (maxwidth > FRAME_WIDTH (f))
2828 maxwidth = FRAME_WIDTH (f);
2829
2830 switch (c)
2831 {
2832 case 'b':
2833 obj = current_buffer->name;
2834 #if 0
2835 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
2836 {
2837 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
2838 decode_mode_spec_buf[maxwidth - 1] = '\\';
2839 decode_mode_spec_buf[maxwidth] = '\0';
2840 return decode_mode_spec_buf;
2841 }
2842 #endif
2843 break;
2844
2845 case 'f':
2846 obj = current_buffer->filename;
2847 #if 0
2848 if (NILP (obj))
2849 return "[none]";
2850 else if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth)
2851 {
2852 bcopy ("...", decode_mode_spec_buf, 3);
2853 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
2854 decode_mode_spec_buf + 3, maxwidth - 3);
2855 return decode_mode_spec_buf;
2856 }
2857 #endif
2858 break;
2859
2860 case 'l':
2861 {
2862 int startpos = marker_position (w->start);
2863 int line, linepos, topline;
2864 int nlines, junk;
2865 Lisp_Object tem;
2866 int height = XFASTINT (w->height);
2867
2868 /* If we decided that this buffer isn't suitable for line numbers,
2869 don't forget that too fast. */
2870 if (EQ (w->base_line_pos, w->buffer))
2871 return "??";
2872
2873 /* If the buffer is very big, don't waste time. */
2874 if (ZV - BEGV > line_number_display_limit)
2875 {
2876 w->base_line_pos = Qnil;
2877 w->base_line_number = Qnil;
2878 return "??";
2879 }
2880
2881 if (!NILP (w->base_line_number)
2882 && !NILP (w->base_line_pos)
2883 && XFASTINT (w->base_line_pos) <= marker_position (w->start))
2884 {
2885 line = XFASTINT (w->base_line_number);
2886 linepos = XFASTINT (w->base_line_pos);
2887 }
2888 else
2889 {
2890 line = 1;
2891 linepos = BEGV;
2892 }
2893
2894 /* Count lines from base line to window start position. */
2895 nlines = display_count_lines (linepos, startpos, startpos, &junk);
2896
2897 topline = nlines + line;
2898
2899 /* Determine a new base line, if the old one is too close
2900 or too far away, or if we did not have one.
2901 "Too close" means it's plausible a scroll-down would
2902 go back past it. */
2903 if (startpos == BEGV)
2904 {
2905 XFASTINT (w->base_line_number) = topline;
2906 XFASTINT (w->base_line_pos) = BEGV;
2907 }
2908 else if (nlines < height + 25 || nlines > height * 3 + 50
2909 || linepos == BEGV)
2910 {
2911 int limit = BEGV;
2912 int position;
2913 int distance = (height * 2 + 30) * 200;
2914
2915 if (startpos - distance > limit)
2916 limit = startpos - distance;
2917
2918 nlines = display_count_lines (startpos, limit,
2919 -(height * 2 + 30),
2920 &position);
2921 /* If we couldn't find the lines we wanted within
2922 200 chars per line,
2923 give up on line numbers for this window. */
2924 if (position == startpos - distance)
2925 {
2926 w->base_line_pos = w->buffer;
2927 w->base_line_number = Qnil;
2928 return "??";
2929 }
2930
2931 XFASTINT (w->base_line_number) = topline - nlines;
2932 XFASTINT (w->base_line_pos) = position;
2933 }
2934
2935 /* Now count lines from the start pos to point. */
2936 nlines = display_count_lines (startpos, PT, PT, &junk);
2937
2938 /* Record that we did display the line number. */
2939 line_number_displayed = 1;
2940
2941 /* Make the string to show. */
2942 sprintf (decode_mode_spec_buf, "%d", topline + nlines);
2943 return decode_mode_spec_buf;
2944 }
2945 break;
2946
2947 case 'm':
2948 obj = current_buffer->mode_name;
2949 break;
2950
2951 case 'n':
2952 if (BEGV > BEG || ZV < Z)
2953 return " Narrow";
2954 break;
2955
2956 case '*':
2957 if (!NILP (current_buffer->read_only))
2958 return "%";
2959 if (MODIFF > current_buffer->save_modified)
2960 return "*";
2961 return "-";
2962
2963 case '+':
2964 /* This differs from %* only for a modified read-only buffer. */
2965 if (MODIFF > current_buffer->save_modified)
2966 return "*";
2967 if (!NILP (current_buffer->read_only))
2968 return "%";
2969 return "-";
2970
2971 case 's':
2972 /* status of process */
2973 obj = Fget_buffer_process (Fcurrent_buffer ());
2974 if (NILP (obj))
2975 return "no process";
2976 #ifdef subprocesses
2977 obj = Fsymbol_name (Fprocess_status (obj));
2978 #endif
2979 break;
2980
2981 case 't': /* indicate TEXT or BINARY */
2982 #ifdef MSDOS
2983 return NILP (current_buffer->buffer_file_type) ? "T" : "B";
2984 #else /* not MSDOS */
2985 return "T";
2986 #endif /* not MSDOS */
2987
2988 case 'p':
2989 {
2990 int pos = marker_position (w->start);
2991 int total = ZV - BEGV;
2992
2993 if (XFASTINT (w->window_end_pos) <= Z - ZV)
2994 {
2995 if (pos <= BEGV)
2996 return "All";
2997 else
2998 return "Bottom";
2999 }
3000 else if (pos <= BEGV)
3001 return "Top";
3002 else
3003 {
3004 total = ((pos - BEGV) * 100 + total - 1) / total;
3005 /* We can't normally display a 3-digit number,
3006 so get us a 2-digit number that is close. */
3007 if (total == 100)
3008 total = 99;
3009 sprintf (decode_mode_spec_buf, "%2d%%", total);
3010 return decode_mode_spec_buf;
3011 }
3012 }
3013
3014 /* Display percentage of size above the bottom of the screen. */
3015 case 'P':
3016 {
3017 int toppos = marker_position (w->start);
3018 int botpos = Z - XFASTINT (w->window_end_pos);
3019 int total = ZV - BEGV;
3020
3021 if (botpos >= ZV)
3022 {
3023 if (toppos <= BEGV)
3024 return "All";
3025 else
3026 return "Bottom";
3027 }
3028 else
3029 {
3030 total = ((botpos - BEGV) * 100 + total - 1) / total;
3031 /* We can't normally display a 3-digit number,
3032 so get us a 2-digit number that is close. */
3033 if (total == 100)
3034 total = 99;
3035 if (toppos <= BEGV)
3036 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
3037 else
3038 sprintf (decode_mode_spec_buf, "%2d%%", total);
3039 return decode_mode_spec_buf;
3040 }
3041 }
3042
3043 case '%':
3044 return "%";
3045
3046 case '[':
3047 {
3048 int i;
3049 char *p;
3050
3051 if (command_loop_level > 5)
3052 return "[[[... ";
3053 p = decode_mode_spec_buf;
3054 for (i = 0; i < command_loop_level; i++)
3055 *p++ = '[';
3056 *p = 0;
3057 return decode_mode_spec_buf;
3058 }
3059
3060 case ']':
3061 {
3062 int i;
3063 char *p;
3064
3065 if (command_loop_level > 5)
3066 return " ...]]]";
3067 p = decode_mode_spec_buf;
3068 for (i = 0; i < command_loop_level; i++)
3069 *p++ = ']';
3070 *p = 0;
3071 return decode_mode_spec_buf;
3072 }
3073
3074 case '-':
3075 {
3076 register char *p;
3077 register int i;
3078
3079 if (maxwidth < sizeof (lots_of_dashes))
3080 return lots_of_dashes;
3081 else
3082 {
3083 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
3084 *p++ = '-';
3085 *p = '\0';
3086 }
3087 return decode_mode_spec_buf;
3088 }
3089 }
3090
3091 if (XTYPE (obj) == Lisp_String)
3092 return (char *) XSTRING (obj)->data;
3093 else
3094 return "";
3095 }
3096
3097 /* Count up to N lines starting from FROM.
3098 But don't go beyond LIMIT.
3099 Return the number of lines thus found (always positive).
3100 Store the position after what was found into *POS_PTR. */
3101
3102 static int
3103 display_count_lines (from, limit, n, pos_ptr)
3104 int from, limit, n;
3105 int *pos_ptr;
3106 {
3107 int oldbegv = BEGV;
3108 int oldzv = ZV;
3109 int shortage = 0;
3110
3111 if (limit < from)
3112 BEGV = limit;
3113 else
3114 ZV = limit;
3115
3116 *pos_ptr = scan_buffer ('\n', from, n, &shortage, 0);
3117
3118 ZV = oldzv;
3119 BEGV = oldbegv;
3120
3121 if (n < 0)
3122 /* When scanning backwards, scan_buffer stops *after* the last newline
3123 it finds, but does count it. Compensate for that. */
3124 return - n - shortage - (*pos_ptr != limit);
3125 return n - shortage;
3126 }
3127 \f
3128 /* Display STRING on one line of window W, starting at HPOS.
3129 Display at position VPOS. Caller should have done get_display_line.
3130 If VPOS == -1, display it as the current frame's title.
3131 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
3132
3133 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
3134
3135 MINCOL is the first column ok to end at. (Pad with spaces to this col.)
3136 MAXCOL is the last column ok to end at. Truncate here.
3137 -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
3138 Both count from the left edge of the frame, as does HPOS.
3139 The right edge of W is an implicit maximum.
3140 If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
3141
3142 OBEY_WINDOW_WIDTH says to put spaces or vertical bars
3143 at the place where the current window ends in this line
3144 and not display anything beyond there. Otherwise, only MAXCOL
3145 controls where to stop output.
3146
3147 Returns ending hpos. */
3148
3149 static int
3150 display_string (w, vpos, string, length, hpos, truncate,
3151 obey_window_width, mincol, maxcol)
3152 struct window *w;
3153 unsigned char *string;
3154 int length;
3155 int vpos, hpos;
3156 GLYPH truncate;
3157 int obey_window_width;
3158 int mincol, maxcol;
3159 {
3160 register int c;
3161 register GLYPH *p1;
3162 int hscroll = XINT (w->hscroll);
3163 int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
3164 register GLYPH *start;
3165 register GLYPH *end;
3166 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
3167 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
3168 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
3169 int window_width = XFASTINT (w->width);
3170
3171 /* Use the standard display table, not the window's display table.
3172 We don't want the mode line in rot13. */
3173 register struct Lisp_Vector *dp = 0;
3174 int i;
3175
3176 if (XTYPE (Vstandard_display_table) == Lisp_Vector
3177 && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
3178 dp = XVECTOR (Vstandard_display_table);
3179
3180 if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
3181
3182 p1 = p1start;
3183 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
3184
3185 if (obey_window_width)
3186 {
3187 end = start + window_width - (truncate != 0);
3188
3189 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f))
3190 {
3191 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3192 {
3193 int i;
3194
3195 for (i = 0; i < VERTICAL_SCROLL_BAR_WIDTH; i++)
3196 *end-- = ' ';
3197 }
3198 else
3199 *end-- = '|';
3200 }
3201 }
3202
3203 if (! obey_window_width
3204 || (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
3205 end = desired_glyphs->glyphs[vpos] + maxcol;
3206
3207 /* Store 0 in charstart for these columns. */
3208 for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
3209 desired_glyphs->charstarts[vpos][i] = 0;
3210
3211 if (maxcol >= 0 && mincol > maxcol)
3212 mincol = maxcol;
3213
3214 while (p1 < end)
3215 {
3216 if (length == 0)
3217 break;
3218 c = *string++;
3219 /* Specified length. */
3220 if (length >= 0)
3221 length--;
3222 /* Unspecified length (null-terminated string). */
3223 else if (c == 0)
3224 break;
3225
3226 if (c >= 040 && c < 0177
3227 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
3228 {
3229 if (p1 >= start)
3230 *p1 = c;
3231 p1++;
3232 }
3233 else if (c == '\t')
3234 {
3235 do
3236 {
3237 if (p1 >= start && p1 < end)
3238 *p1 = SPACEGLYPH;
3239 p1++;
3240 }
3241 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
3242 }
3243 else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
3244 {
3245 p1 = copy_part_of_rope (f, p1, start,
3246 XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
3247 XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
3248 0);
3249 }
3250 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
3251 {
3252 if (p1 >= start)
3253 *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
3254 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
3255 0);
3256 p1++;
3257 if (p1 >= start && p1 < end)
3258 *p1 = c ^ 0100;
3259 p1++;
3260 }
3261 else
3262 {
3263 if (p1 >= start)
3264 *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
3265 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
3266 0);
3267 p1++;
3268 if (p1 >= start && p1 < end)
3269 *p1 = (c >> 6) + '0';
3270 p1++;
3271 if (p1 >= start && p1 < end)
3272 *p1 = (7 & (c >> 3)) + '0';
3273 p1++;
3274 if (p1 >= start && p1 < end)
3275 *p1 = (7 & c) + '0';
3276 p1++;
3277 }
3278 }
3279
3280 if (c && length > 0)
3281 {
3282 p1 = end;
3283 if (truncate) *p1++ = fix_glyph (f, truncate, 0);
3284 }
3285 else if (mincol >= 0)
3286 {
3287 end = desired_glyphs->glyphs[vpos] + mincol;
3288 while (p1 < end)
3289 *p1++ = SPACEGLYPH;
3290 }
3291
3292 {
3293 register int len = p1 - desired_glyphs->glyphs[vpos];
3294
3295 if (len > desired_glyphs->used[vpos])
3296 desired_glyphs->used[vpos] = len;
3297 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
3298
3299 return len;
3300 }
3301 }
3302 \f
3303 void
3304 syms_of_xdisp ()
3305 {
3306 staticpro (&Qmenu_bar_update_hook);
3307 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
3308
3309 staticpro (&last_arrow_position);
3310 staticpro (&last_arrow_string);
3311 last_arrow_position = Qnil;
3312 last_arrow_string = Qnil;
3313
3314 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
3315 "String (or mode line construct) included (normally) in `mode-line-format'.");
3316 Vglobal_mode_string = Qnil;
3317
3318 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
3319 "Marker for where to display an arrow on top of the buffer text.\n\
3320 This must be the beginning of a line in order to work.\n\
3321 See also `overlay-arrow-string'.");
3322 Voverlay_arrow_position = Qnil;
3323
3324 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
3325 "String to display as an arrow. See also `overlay-arrow-position'.");
3326 Voverlay_arrow_string = Qnil;
3327
3328 DEFVAR_INT ("scroll-step", &scroll_step,
3329 "*The number of lines to try scrolling a window by when point moves out.\n\
3330 If that fails to bring point back on frame, point is centered instead.\n\
3331 If this is zero, point is always centered after it moves off frame.");
3332
3333 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
3334
3335 DEFVAR_BOOL ("truncate-partial-width-windows",
3336 &truncate_partial_width_windows,
3337 "*Non-nil means truncate lines in all windows less than full frame wide.");
3338 truncate_partial_width_windows = 1;
3339
3340 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
3341 "*Non-nil means use inverse video for the mode line.");
3342 mode_line_inverse_video = 1;
3343
3344 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
3345 "*Maximum buffer size for which line number should be displayed.");
3346 line_number_display_limit = 1000000;
3347
3348 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
3349 "*Non-nil means highlight region even in nonselected windows.");
3350 highlight_nonselected_windows = 1;
3351 }
3352
3353 /* initialize the window system */
3354 init_xdisp ()
3355 {
3356 Lisp_Object root_window;
3357 #ifndef COMPILER_REGISTER_BUG
3358 register
3359 #endif /* COMPILER_REGISTER_BUG */
3360 struct window *mini_w;
3361
3362 this_line_bufpos = 0;
3363
3364 mini_w = XWINDOW (minibuf_window);
3365 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
3366
3367 echo_area_glyphs = 0;
3368 previous_echo_glyphs = 0;
3369
3370 if (!noninteractive)
3371 {
3372 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
3373 XFASTINT (XWINDOW (root_window)->top) = 0;
3374 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
3375 XFASTINT (mini_w->top) = FRAME_HEIGHT (f) - 1;
3376 set_window_height (minibuf_window, 1, 0);
3377
3378 XFASTINT (XWINDOW (root_window)->width) = FRAME_WIDTH (f);
3379 XFASTINT (mini_w->width) = FRAME_WIDTH (f);
3380 }
3381 }