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