(pos_visible_p): Don't add `it.current_y' twice.
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
a0315a63 2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99, 2000
5f5c8ee5 3 Free Software Foundation, Inc.
a2889657
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
b1d1124b 9the Free Software Foundation; either version 2, or (at your option)
a2889657
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
a2889657 21
5f5c8ee5
GM
22/* New redisplay written by Gerd Moellmann <gerd@gnu.org>.
23
24 Redisplay.
25
26 Emacs separates the task of updating the display from code
27 modifying global state, e.g. buffer text. This way functions
28 operating on buffers don't also have to be concerned with updating
29 the display.
30
31 Updating the display is triggered by the Lisp interpreter when it
32 decides it's time to do it. This is done either automatically for
33 you as part of the interpreter's command loop or as the result of
34 calling Lisp functions like `sit-for'. The C function `redisplay'
35 in xdisp.c is the only entry into the inner redisplay code. (Or,
36 let's say almost---see the the description of direct update
37 operations, below.).
38
39 The following diagram shows how redisplay code is invoked. As you
40 can see, Lisp calls redisplay and vice versa. Under window systems
41 like X, some portions of the redisplay code are also called
42 asynchronously during mouse movement or expose events. It is very
43 important that these code parts do NOT use the C library (malloc,
44 free) because many C libraries under Unix are not reentrant. They
45 may also NOT call functions of the Lisp interpreter which could
46 change the interpreter's state. If you don't follow these rules,
47 you will encounter bugs which are very hard to explain.
48
49 (Direct functions, see below)
50 direct_output_for_insert,
51 direct_forward_char (dispnew.c)
52 +---------------------------------+
53 | |
54 | V
55 +--------------+ redisplay() +----------------+
56 | Lisp machine |---------------->| Redisplay code |<--+
57 +--------------+ (xdisp.c) +----------------+ |
58 ^ | |
59 +----------------------------------+ |
60 Don't use this path when called |
61 asynchronously! |
62 |
63 expose_window (asynchronous) |
64 |
65 X expose events -----+
66
67 What does redisplay? Obviously, it has to figure out somehow what
68 has been changed since the last time the display has been updated,
69 and to make these changes visible. Preferably it would do that in
70 a moderately intelligent way, i.e. fast.
71
72 Changes in buffer text can be deduced from window and buffer
73 structures, and from some global variables like `beg_unchanged' and
74 `end_unchanged'. The contents of the display are additionally
75 recorded in a `glyph matrix', a two-dimensional matrix of glyph
76 structures. Each row in such a matrix corresponds to a line on the
77 display, and each glyph in a row corresponds to a column displaying
78 a character, an image, or what else. This matrix is called the
79 `current glyph matrix' or `current matrix' in redisplay
80 terminology.
81
82 For buffer parts that have been changed since the last update, a
83 second glyph matrix is constructed, the so called `desired glyph
84 matrix' or short `desired matrix'. Current and desired matrix are
85 then compared to find a cheap way to update the display, e.g. by
86 reusing part of the display by scrolling lines.
87
88
89 Direct operations.
90
91 You will find a lot of of redisplay optimizations when you start
92 looking at the innards of redisplay. The overall goal of all these
93 optimizations is to make redisplay fast because it is done
94 frequently.
95
96 Two optimizations are not found in xdisp.c. These are the direct
97 operations mentioned above. As the name suggests they follow a
98 different principle than the rest of redisplay. Instead of
99 building a desired matrix and then comparing it with the current
100 display, they perform their actions directly on the display and on
101 the current matrix.
102
103 One direct operation updates the display after one character has
104 been entered. The other one moves the cursor by one position
105 forward or backward. You find these functions under the names
106 `direct_output_for_insert' and `direct_output_forward_char' in
107 dispnew.c.
108
109
110 Desired matrices.
111
112 Desired matrices are always built per Emacs window. The function
113 `display_line' is the central function to look at if you are
114 interested. It constructs one row in a desired matrix given an
115 iterator structure containing both a buffer position and a
116 description of the environment in which the text is to be
117 displayed. But this is too early, read on.
118
119 Characters and pixmaps displayed for a range of buffer text depend
120 on various settings of buffers and windows, on overlays and text
121 properties, on display tables, on selective display. The good news
122 is that all this hairy stuff is hidden behind a small set of
123 interface functions taking a iterator structure (struct it)
124 argument.
125
126 Iteration over things to be be displayed is then simple. It is
127 started by initializing an iterator with a call to init_iterator
128 (or init_string_iterator for that matter). Calls to
129 get_next_display_element fill the iterator structure with relevant
130 information about the next thing to display. Calls to
131 set_iterator_to_next move the iterator to the next thing.
132
133 Besides this, an iterator also contains information about the
134 display environment in which glyphs for display elements are to be
135 produced. It has fields for the width and height of the display,
136 the information whether long lines are truncated or continued, a
137 current X and Y position, and lots of other stuff you can better
138 see in dispextern.h.
139
140 Glyphs in a desired matrix are normally constructed in a loop
141 calling get_next_display_element and then produce_glyphs. The call
142 to produce_glyphs will fill the iterator structure with pixel
143 information about the element being displayed and at the same time
144 produce glyphs for it. If the display element fits on the line
145 being displayed, set_iterator_to_next is called next, otherwise the
146 glyphs produced are discarded.
147
148
149 Frame matrices.
150
151 That just couldn't be all, could it? What about terminal types not
152 supporting operations on sub-windows of the screen? To update the
153 display on such a terminal, window-based glyph matrices are not
154 well suited. To be able to reuse part of the display (scrolling
155 lines up and down), we must instead have a view of the whole
156 screen. This is what `frame matrices' are for. They are a trick.
157
158 Frames on terminals like above have a glyph pool. Windows on such
159 a frame sub-allocate their glyph memory from their frame's glyph
160 pool. The frame itself is given its own glyph matrices. By
161 coincidence---or maybe something else---rows in window glyph
162 matrices are slices of corresponding rows in frame matrices. Thus
163 writing to window matrices implicitly updates a frame matrix which
164 provides us with the view of the whole screen that we originally
165 wanted to have without having to move many bytes around. To be
166 honest, there is a little bit more done, but not much more. If you
167 plan to extend that code, take a look at dispnew.c. The function
168 build_frame_matrix is a good starting point. */
a2889657 169
18160b98 170#include <config.h>
a2889657 171#include <stdio.h>
a2889657 172#include "lisp.h"
546a4f00 173#include "keyboard.h"
44fa5b1e 174#include "frame.h"
a2889657
JB
175#include "window.h"
176#include "termchar.h"
177#include "dispextern.h"
178#include "buffer.h"
1c9241f5 179#include "charset.h"
a2889657
JB
180#include "indent.h"
181#include "commands.h"
182#include "macros.h"
183#include "disptab.h"
30c566e4 184#include "termhooks.h"
b0a0fbda 185#include "intervals.h"
1c9241f5
KH
186#include "coding.h"
187#include "process.h"
dfcf069d 188#include "region-cache.h"
0ef75e87 189#include "fontset.h"
dfcf069d 190
6d55d620 191#ifdef HAVE_X_WINDOWS
dfcf069d
AS
192#include "xterm.h"
193#endif
a75dfea0
AI
194#ifdef WINDOWSNT
195#include "w32term.h"
196#endif
1a578e9b
AC
197#ifdef macintosh
198#include "macterm.h"
199#endif
a2889657 200
5f5c8ee5
GM
201#define min(a, b) ((a) < (b) ? (a) : (b))
202#define max(a, b) ((a) > (b) ? (a) : (b))
203
204#define INFINITY 10000000
205
1a578e9b 206#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
2e621225 207extern void set_frame_menubar P_ ((struct frame *f, int, int));
cd6dfed6 208extern int pending_menu_activation;
76412d64
RS
209#endif
210
a2889657
JB
211extern int interrupt_input;
212extern int command_loop_level;
213
b6436d4e
RS
214extern int minibuffer_auto_raise;
215
c4628384
RS
216extern Lisp_Object Qface;
217
399164b4
KH
218extern Lisp_Object Voverriding_local_map;
219extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 220extern Lisp_Object Qmenu_item;
399164b4 221
d46fb96a 222Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 223Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 224Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 225Lisp_Object Qinhibit_point_motion_hooks;
9499d71b 226Lisp_Object QCeval, Qwhen, QCfile, QCdata;
5f5c8ee5
GM
227Lisp_Object Qfontified;
228
229/* Functions called to fontify regions of text. */
230
231Lisp_Object Vfontification_functions;
232Lisp_Object Qfontification_functions;
233
e037b9ec 234/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
235 over them. */
236
e037b9ec 237int auto_raise_tool_bar_buttons_p;
5f5c8ee5 238
e037b9ec 239/* Margin around tool bar buttons in pixels. */
5f5c8ee5 240
e037b9ec 241int tool_bar_button_margin;
5f5c8ee5 242
e037b9ec 243/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 244
e037b9ec 245int tool_bar_button_relief;
5f5c8ee5 246
e037b9ec 247/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
248 items are visible, and no blank lines remain. */
249
e037b9ec 250int auto_resize_tool_bars_p;
399164b4 251
735c094c
KH
252/* Non-nil means don't actually do any redisplay. */
253
254Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
255
5f5c8ee5
GM
256/* Names of text properties relevant for redisplay. */
257
a7e27ef7
DL
258Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
259extern Lisp_Object Qface, Qinvisible, Qimage, Qwidth;
5f5c8ee5
GM
260
261/* Symbols used in text property values. */
262
263Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
a7e27ef7 264Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
f3751a65 265Lisp_Object Qmargin;
a7e27ef7 266extern Lisp_Object Qheight;
5f5c8ee5 267
8f897821 268/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 269
8f897821 270Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5
GM
271
272/* Name of the face used to highlight trailing whitespace. */
273
274Lisp_Object Qtrailing_whitespace;
275
276/* The symbol `image' which is the car of the lists used to represent
277 images in Lisp. */
278
279Lisp_Object Qimage;
280
281/* Non-zero means print newline to stdout before next mini-buffer
282 message. */
a2889657
JB
283
284int noninteractive_need_newline;
285
5f5c8ee5 286/* Non-zero means print newline to message log before next message. */
f88eb0b6 287
3c6595e0 288static int message_log_need_newline;
f88eb0b6 289
5f5c8ee5
GM
290\f
291/* The buffer position of the first character appearing entirely or
292 partially on the line of the selected window which contains the
293 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
294 redisplay optimization in redisplay_internal. */
a2889657 295
5f5c8ee5 296static struct text_pos this_line_start_pos;
a2889657 297
5f5c8ee5
GM
298/* Number of characters past the end of the line above, including the
299 terminating newline. */
300
301static struct text_pos this_line_end_pos;
302
303/* The vertical positions and the height of this line. */
a2889657 304
a2889657 305static int this_line_vpos;
5f5c8ee5
GM
306static int this_line_y;
307static int this_line_pixel_height;
308
309/* X position at which this display line starts. Usually zero;
310 negative if first character is partially visible. */
311
312static int this_line_start_x;
a2889657 313
5f5c8ee5 314/* Buffer that this_line_.* variables are referring to. */
a2889657 315
a2889657
JB
316static struct buffer *this_line_buffer;
317
5f5c8ee5
GM
318/* Nonzero means truncate lines in all windows less wide than the
319 frame. */
a2889657 320
a2889657
JB
321int truncate_partial_width_windows;
322
7bbe686f 323/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 324
7bbe686f 325int unibyte_display_via_language_environment;
5f5c8ee5
GM
326
327/* Nonzero means we have more than one non-mini-buffer-only frame.
328 Not guaranteed to be accurate except while parsing
329 frame-title-format. */
7bbe686f 330
d39b6696
KH
331int multiple_frames;
332
a2889657
JB
333Lisp_Object Vglobal_mode_string;
334
335/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 336
a2889657
JB
337Lisp_Object Voverlay_arrow_position;
338
5f5c8ee5
GM
339/* String to display for the arrow. Only used on terminal frames. */
340
a2889657
JB
341Lisp_Object Voverlay_arrow_string;
342
5f5c8ee5
GM
343/* Values of those variables at last redisplay. However, if
344 Voverlay_arrow_position is a marker, last_arrow_position is its
345 numerical position. */
346
d45de95b
RS
347static Lisp_Object last_arrow_position, last_arrow_string;
348
5f5c8ee5
GM
349/* Like mode-line-format, but for the title bar on a visible frame. */
350
d39b6696
KH
351Lisp_Object Vframe_title_format;
352
5f5c8ee5
GM
353/* Like mode-line-format, but for the title bar on an iconified frame. */
354
d39b6696
KH
355Lisp_Object Vicon_title_format;
356
08b610e4
RS
357/* List of functions to call when a window's size changes. These
358 functions get one arg, a frame on which one or more windows' sizes
359 have changed. */
5f5c8ee5 360
08b610e4
RS
361static Lisp_Object Vwindow_size_change_functions;
362
0bca8940 363Lisp_Object Qmenu_bar_update_hook, Vmenu_bar_update_hook;
cf074754 364
a2889657 365/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 366
5f5c8ee5 367static int overlay_arrow_seen;
ca26e1c8 368
fba9ce76 369/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 370
5f5c8ee5
GM
371int highlight_nonselected_windows;
372
373/* If cursor motion alone moves point off frame, try scrolling this
374 many lines up or down if that will bring it back. */
375
14510fee 376static int scroll_step;
a2889657 377
5f5c8ee5
GM
378/* Non-0 means scroll just far enough to bring point back on the
379 screen, when appropriate. */
380
0789adb2
RS
381static int scroll_conservatively;
382
5f5c8ee5
GM
383/* Recenter the window whenever point gets within this many lines of
384 the top or bottom of the window. This value is translated into a
385 pixel value by multiplying it with CANON_Y_UNIT, which means that
386 there is really a fixed pixel height scroll margin. */
387
9afd2168
RS
388int scroll_margin;
389
5f5c8ee5
GM
390/* Number of windows showing the buffer of the selected window (or
391 another buffer with the same base buffer). keyboard.c refers to
392 this. */
a2889657 393
a2889657
JB
394int buffer_shared;
395
5f5c8ee5 396/* Vector containing glyphs for an ellipsis `...'. */
a2889657 397
5f5c8ee5 398static Lisp_Object default_invis_vector[3];
a2889657 399
5f5c8ee5 400/* Nonzero means display mode line highlighted. */
a2889657 401
a2889657
JB
402int mode_line_inverse_video;
403
5f5c8ee5
GM
404/* Prompt to display in front of the mini-buffer contents. */
405
8c5b6a0a 406Lisp_Object minibuf_prompt;
a2889657 407
5f5c8ee5
GM
408/* Width of current mini-buffer prompt. Only set after display_line
409 of the line that contains the prompt. */
410
a2889657 411int minibuf_prompt_width;
5f5c8ee5
GM
412int minibuf_prompt_pixel_width;
413
5f5c8ee5
GM
414/* This is the window where the echo area message was displayed. It
415 is always a mini-buffer window, but it may not be the same window
416 currently active as a mini-buffer. */
417
73af359d
RS
418Lisp_Object echo_area_window;
419
c6e89d6c
GM
420/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
421 pushes the current message and the value of
422 message_enable_multibyte on the stack, the function restore_message
423 pops the stack and displays MESSAGE again. */
424
425Lisp_Object Vmessage_stack;
426
a3788d53
RS
427/* Nonzero means multibyte characters were enabled when the echo area
428 message was specified. */
5f5c8ee5 429
a3788d53
RS
430int message_enable_multibyte;
431
5f5c8ee5
GM
432/* True if we should redraw the mode lines on the next redisplay. */
433
a2889657
JB
434int update_mode_lines;
435
5f5c8ee5
GM
436/* Nonzero if window sizes or contents have changed since last
437 redisplay that finished */
438
a2889657
JB
439int windows_or_buffers_changed;
440
5f5c8ee5
GM
441/* Nonzero after display_mode_line if %l was used and it displayed a
442 line number. */
443
aa6d10fa
RS
444int line_number_displayed;
445
446/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 447
090703f4 448Lisp_Object Vline_number_display_limit;
5992c4f7 449
5d121aec
KH
450/* line width to consider when repostioning for line number display */
451
452static int line_number_display_limit_width;
453
5f5c8ee5
GM
454/* Number of lines to keep in the message log buffer. t means
455 infinite. nil means don't log at all. */
456
5992c4f7 457Lisp_Object Vmessage_log_max;
d45de95b 458
6a94510a
GM
459/* The name of the *Messages* buffer, a string. */
460
461static Lisp_Object Vmessages_buffer_name;
462
c6e89d6c
GM
463/* Current, index 0, and last displayed echo area message. Either
464 buffers from echo_buffers, or nil to indicate no message. */
465
466Lisp_Object echo_area_buffer[2];
467
468/* The buffers referenced from echo_area_buffer. */
469
470static Lisp_Object echo_buffer[2];
471
472/* A vector saved used in with_area_buffer to reduce consing. */
473
474static Lisp_Object Vwith_echo_area_save_vector;
475
476/* Non-zero means display_echo_area should display the last echo area
477 message again. Set by redisplay_preserve_echo_area. */
478
479static int display_last_displayed_message_p;
480
481/* Nonzero if echo area is being used by print; zero if being used by
482 message. */
483
484int message_buf_print;
485
9142dd5b
GM
486/* Maximum height for resizing mini-windows. Either a float
487 specifying a fraction of the available height, or an integer
488 specifying a number of lines. */
c6e89d6c 489
ad4f174e
GM
490Lisp_Object Vmax_mini_window_height;
491
492/* Non-zero means messages should be displayed with truncated
493 lines instead of being continued. */
494
495int message_truncate_lines;
496Lisp_Object Qmessage_truncate_lines;
c6e89d6c 497
d6d26ed3
GM
498/* Non-zero means we want a hollow cursor in windows that are not
499 selected. Zero means there's no cursor in such windows. */
500
501int cursor_in_non_selected_windows;
502
5f5c8ee5
GM
503/* A scratch glyph row with contents used for generating truncation
504 glyphs. Also used in direct_output_for_insert. */
12adba34 505
5f5c8ee5
GM
506#define MAX_SCRATCH_GLYPHS 100
507struct glyph_row scratch_glyph_row;
508static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 509
5f5c8ee5
GM
510/* Ascent and height of the last line processed by move_it_to. */
511
512static int last_max_ascent, last_height;
513
21fdfb65
GM
514/* Non-zero if there's a help-echo in the echo area. */
515
516int help_echo_showing_p;
517
5f5c8ee5
GM
518/* The maximum distance to look ahead for text properties. Values
519 that are too small let us call compute_char_face and similar
520 functions too often which is expensive. Values that are too large
521 let us call compute_char_face and alike too often because we
522 might not be interested in text properties that far away. */
523
524#define TEXT_PROP_DISTANCE_LIMIT 100
525
47589c8c
GM
526#if GLYPH_DEBUG
527
5f5c8ee5
GM
528/* Non-zero means print traces of redisplay if compiled with
529 GLYPH_DEBUG != 0. */
530
5f5c8ee5 531int trace_redisplay_p;
47589c8c 532
546a4f00 533#endif /* GLYPH_DEBUG */
47589c8c 534
546a4f00
AI
535#ifdef DEBUG_TRACE_MOVE
536/* Non-zero means trace with TRACE_MOVE to stderr. */
47589c8c
GM
537int trace_move;
538
47589c8c
GM
539#define TRACE_MOVE(x) if (trace_move) fprintf x; else (void) 0
540#else
91c3f500 541#define TRACE_MOVE(x) (void) 0
5f5c8ee5 542#endif
546a4f00 543
d475bcb8
GM
544/* Non-zero means automatically scroll windows horizontally to make
545 point visible. */
546
547int automatic_hscrolling_p;
548
e00daaa0
GM
549/* A list of symbols, one for each supported image type. */
550
551Lisp_Object Vimage_types;
552
5f5c8ee5
GM
553/* Value returned from text property handlers (see below). */
554
555enum prop_handled
3c6595e0 556{
5f5c8ee5
GM
557 HANDLED_NORMALLY,
558 HANDLED_RECOMPUTE_PROPS,
559 HANDLED_OVERLAY_STRING_CONSUMED,
560 HANDLED_RETURN
561};
3c6595e0 562
5f5c8ee5
GM
563/* A description of text properties that redisplay is interested
564 in. */
3c6595e0 565
5f5c8ee5
GM
566struct props
567{
568 /* The name of the property. */
569 Lisp_Object *name;
90adcf20 570
5f5c8ee5
GM
571 /* A unique index for the property. */
572 enum prop_idx idx;
573
574 /* A handler function called to set up iterator IT from the property
575 at IT's current position. Value is used to steer handle_stop. */
576 enum prop_handled (*handler) P_ ((struct it *it));
577};
578
579static enum prop_handled handle_face_prop P_ ((struct it *));
580static enum prop_handled handle_invisible_prop P_ ((struct it *));
581static enum prop_handled handle_display_prop P_ ((struct it *));
260a86a0 582static enum prop_handled handle_composition_prop P_ ((struct it *));
5f5c8ee5
GM
583static enum prop_handled handle_overlay_change P_ ((struct it *));
584static enum prop_handled handle_fontified_prop P_ ((struct it *));
585
586/* Properties handled by iterators. */
587
588static struct props it_props[] =
5992c4f7 589{
5f5c8ee5
GM
590 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
591 /* Handle `face' before `display' because some sub-properties of
592 `display' need to know the face. */
593 {&Qface, FACE_PROP_IDX, handle_face_prop},
594 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
595 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
260a86a0 596 {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
5f5c8ee5
GM
597 {NULL, 0, NULL}
598};
5992c4f7 599
5f5c8ee5
GM
600/* Value is the position described by X. If X is a marker, value is
601 the marker_position of X. Otherwise, value is X. */
12adba34 602
5f5c8ee5 603#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 604
5f5c8ee5 605/* Enumeration returned by some move_it_.* functions internally. */
12adba34 606
5f5c8ee5
GM
607enum move_it_result
608{
609 /* Not used. Undefined value. */
610 MOVE_UNDEFINED,
bab29e15 611
5f5c8ee5
GM
612 /* Move ended at the requested buffer position or ZV. */
613 MOVE_POS_MATCH_OR_ZV,
bab29e15 614
5f5c8ee5
GM
615 /* Move ended at the requested X pixel position. */
616 MOVE_X_REACHED,
12adba34 617
5f5c8ee5
GM
618 /* Move within a line ended at the end of a line that must be
619 continued. */
620 MOVE_LINE_CONTINUED,
621
622 /* Move within a line ended at the end of a line that would
623 be displayed truncated. */
624 MOVE_LINE_TRUNCATED,
ff6c30e5 625
5f5c8ee5
GM
626 /* Move within a line ended at a line end. */
627 MOVE_NEWLINE_OR_CR
628};
12adba34 629
ff6c30e5 630
5f5c8ee5
GM
631\f
632/* Function prototypes. */
633
cafafe0b 634static int cursor_row_p P_ ((struct window *, struct glyph_row *));
715e84c9 635static int redisplay_mode_lines P_ ((Lisp_Object, int));
2e621225
GM
636static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
637static int invisible_text_between_p P_ ((struct it *, int, int));
638static int next_element_from_ellipsis P_ ((struct it *));
639static void pint2str P_ ((char *, int, int));
640static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
641 struct text_pos));
642static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
643static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
644static void store_frame_title_char P_ ((char));
645static int store_frame_title P_ ((unsigned char *, int, int));
646static void x_consider_frame_title P_ ((Lisp_Object));
647static void handle_stop P_ ((struct it *));
648static int tool_bar_lines_needed P_ ((struct frame *));
06568bbf 649static int single_display_prop_intangible_p P_ ((Lisp_Object));
5bcfeb49 650static void ensure_echo_area_buffers P_ ((void));
e037b9ec
GM
651static struct glyph_row *row_containing_pos P_ ((struct window *, int,
652 struct glyph_row *,
653 struct glyph_row *));
c6e89d6c
GM
654static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
655static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
23a96c77 656static int with_echo_area_buffer P_ ((struct window *, int,
23dd2d97
KR
657 int (*) (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT),
658 EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 659static void clear_garbaged_frames P_ ((void));
23dd2d97
KR
660static int current_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
661static int truncate_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
662static int set_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 663static int display_echo_area P_ ((struct window *));
23dd2d97
KR
664static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
665static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
28514cd9 666static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
4fdb80f2 667static int string_char_and_length P_ ((unsigned char *, int, int *));
5f5c8ee5
GM
668static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
669 struct text_pos));
670static int compute_window_start_on_continuation_line P_ ((struct window *));
116d6f5c 671static Lisp_Object safe_eval_handler P_ ((Lisp_Object));
5f5c8ee5
GM
672static void insert_left_trunc_glyphs P_ ((struct it *));
673static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
674static void extend_face_to_end_of_line P_ ((struct it *));
80c6cb1f 675static int append_space P_ ((struct it *, int));
5f5c8ee5
GM
676static void make_cursor_line_fully_visible P_ ((struct window *));
677static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
47589c8c 678static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
5f5c8ee5
GM
679static int trailing_whitespace_p P_ ((int));
680static int message_log_check_duplicate P_ ((int, int, int, int));
681int invisible_p P_ ((Lisp_Object, Lisp_Object));
682int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
683static void push_it P_ ((struct it *));
684static void pop_it P_ ((struct it *));
685static void sync_frame_with_window_matrix_rows P_ ((struct window *));
686static void redisplay_internal P_ ((int));
c6e89d6c 687static int echo_area_display P_ ((int));
5f5c8ee5
GM
688static void redisplay_windows P_ ((Lisp_Object));
689static void redisplay_window P_ ((Lisp_Object, int));
690static void update_menu_bar P_ ((struct frame *, int));
691static int try_window_reusing_current_matrix P_ ((struct window *));
692static int try_window_id P_ ((struct window *));
693static int display_line P_ ((struct it *));
715e84c9 694static int display_mode_lines P_ ((struct window *));
5f5c8ee5
GM
695static void display_mode_line P_ ((struct window *, enum face_id,
696 Lisp_Object));
697static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
68c45bf0 698static char *decode_mode_spec P_ ((struct window *, int, int, int));
5f5c8ee5
GM
699static void display_menu_bar P_ ((struct window *));
700static int display_count_lines P_ ((int, int, int, int, int *));
701static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
702 int, int, struct it *, int, int, int, int));
703static void compute_line_metrics P_ ((struct it *));
704static void run_redisplay_end_trigger_hook P_ ((struct it *));
705static int get_overlay_strings P_ ((struct it *));
706static void next_overlay_string P_ ((struct it *));
5f5c8ee5
GM
707static void reseat P_ ((struct it *, struct text_pos, int));
708static void reseat_1 P_ ((struct it *, struct text_pos, int));
709static void back_to_previous_visible_line_start P_ ((struct it *));
710static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 711static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
712static int next_element_from_display_vector P_ ((struct it *));
713static int next_element_from_string P_ ((struct it *));
714static int next_element_from_c_string P_ ((struct it *));
715static int next_element_from_buffer P_ ((struct it *));
260a86a0 716static int next_element_from_composition P_ ((struct it *));
5f5c8ee5
GM
717static int next_element_from_image P_ ((struct it *));
718static int next_element_from_stretch P_ ((struct it *));
719static void load_overlay_strings P_ ((struct it *));
720static void init_from_display_pos P_ ((struct it *, struct window *,
721 struct display_pos *));
722static void reseat_to_string P_ ((struct it *, unsigned char *,
723 Lisp_Object, int, int, int, int));
5f5c8ee5
GM
724static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
725 int, int, int));
726void move_it_vertically_backward P_ ((struct it *, int));
727static void init_to_row_start P_ ((struct it *, struct window *,
728 struct glyph_row *));
729static void init_to_row_end P_ ((struct it *, struct window *,
730 struct glyph_row *));
731static void back_to_previous_line_start P_ ((struct it *));
cafafe0b 732static int forward_to_next_line_start P_ ((struct it *, int *));
5f5c8ee5
GM
733static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
734 Lisp_Object, int));
735static struct text_pos string_pos P_ ((int, Lisp_Object));
736static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
737static int number_of_chars P_ ((unsigned char *, int));
738static void compute_stop_pos P_ ((struct it *));
739static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
740 Lisp_Object));
741static int face_before_or_after_it_pos P_ ((struct it *, int));
742static int next_overlay_change P_ ((int));
743static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
744 Lisp_Object, struct text_pos *));
745
746#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
747#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 748
5f5c8ee5 749#ifdef HAVE_WINDOW_SYSTEM
12adba34 750
e037b9ec
GM
751static void update_tool_bar P_ ((struct frame *, int));
752static void build_desired_tool_bar_string P_ ((struct frame *f));
753static int redisplay_tool_bar P_ ((struct frame *));
754static void display_tool_bar_line P_ ((struct it *));
12adba34 755
5f5c8ee5 756#endif /* HAVE_WINDOW_SYSTEM */
12adba34 757
5f5c8ee5
GM
758\f
759/***********************************************************************
760 Window display dimensions
761 ***********************************************************************/
12adba34 762
5f5c8ee5
GM
763/* Return the window-relative maximum y + 1 for glyph rows displaying
764 text in window W. This is the height of W minus the height of a
765 mode line, if any. */
766
767INLINE int
768window_text_bottom_y (w)
769 struct window *w;
770{
771 struct frame *f = XFRAME (w->frame);
772 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
1a578e9b 773
5f5c8ee5
GM
774 if (WINDOW_WANTS_MODELINE_P (w))
775 height -= CURRENT_MODE_LINE_HEIGHT (w);
776 return height;
f88eb0b6
KH
777}
778
f82aff7c 779
5f5c8ee5
GM
780/* Return the pixel width of display area AREA of window W. AREA < 0
781 means return the total width of W, not including bitmap areas to
782 the left and right of the window. */
ff6c30e5 783
5f5c8ee5
GM
784INLINE int
785window_box_width (w, area)
786 struct window *w;
787 int area;
788{
789 struct frame *f = XFRAME (w->frame);
790 int width = XFASTINT (w->width);
791
792 if (!w->pseudo_window_p)
ff6c30e5 793 {
050d82d7 794 width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FLAGS_AREA_COLS (f);
5f5c8ee5
GM
795
796 if (area == TEXT_AREA)
797 {
798 if (INTEGERP (w->left_margin_width))
799 width -= XFASTINT (w->left_margin_width);
800 if (INTEGERP (w->right_margin_width))
801 width -= XFASTINT (w->right_margin_width);
802 }
803 else if (area == LEFT_MARGIN_AREA)
804 width = (INTEGERP (w->left_margin_width)
805 ? XFASTINT (w->left_margin_width) : 0);
806 else if (area == RIGHT_MARGIN_AREA)
807 width = (INTEGERP (w->right_margin_width)
808 ? XFASTINT (w->right_margin_width) : 0);
ff6c30e5 809 }
5f5c8ee5
GM
810
811 return width * CANON_X_UNIT (f);
ff6c30e5 812}
1adc55de 813
1adc55de 814
5f5c8ee5
GM
815/* Return the pixel height of the display area of window W, not
816 including mode lines of W, if any.. */
f88eb0b6 817
5f5c8ee5
GM
818INLINE int
819window_box_height (w)
820 struct window *w;
f88eb0b6 821{
5f5c8ee5
GM
822 struct frame *f = XFRAME (w->frame);
823 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
7ecd4937
GM
824
825 xassert (height >= 0);
5f5c8ee5
GM
826
827 if (WINDOW_WANTS_MODELINE_P (w))
828 height -= CURRENT_MODE_LINE_HEIGHT (w);
829
045dee35
GM
830 if (WINDOW_WANTS_HEADER_LINE_P (w))
831 height -= CURRENT_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
832
833 return height;
5992c4f7
KH
834}
835
836
5f5c8ee5
GM
837/* Return the frame-relative coordinate of the left edge of display
838 area AREA of window W. AREA < 0 means return the left edge of the
839 whole window, to the right of any bitmap area at the left side of
840 W. */
5992c4f7 841
5f5c8ee5
GM
842INLINE int
843window_box_left (w, area)
844 struct window *w;
845 int area;
90adcf20 846{
5f5c8ee5
GM
847 struct frame *f = XFRAME (w->frame);
848 int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
a3788d53 849
5f5c8ee5 850 if (!w->pseudo_window_p)
90adcf20 851 {
5f5c8ee5 852 x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
050d82d7 853 + FRAME_LEFT_FLAGS_AREA_WIDTH (f));
5f5c8ee5
GM
854
855 if (area == TEXT_AREA)
856 x += window_box_width (w, LEFT_MARGIN_AREA);
857 else if (area == RIGHT_MARGIN_AREA)
858 x += (window_box_width (w, LEFT_MARGIN_AREA)
859 + window_box_width (w, TEXT_AREA));
90adcf20 860 }
73af359d 861
5f5c8ee5
GM
862 return x;
863}
90adcf20 864
b6436d4e 865
5f5c8ee5
GM
866/* Return the frame-relative coordinate of the right edge of display
867 area AREA of window W. AREA < 0 means return the left edge of the
868 whole window, to the left of any bitmap area at the right side of
869 W. */
ded34426 870
5f5c8ee5
GM
871INLINE int
872window_box_right (w, area)
873 struct window *w;
874 int area;
875{
876 return window_box_left (w, area) + window_box_width (w, area);
877}
878
879
880/* Get the bounding box of the display area AREA of window W, without
881 mode lines, in frame-relative coordinates. AREA < 0 means the
882 whole window, not including bitmap areas to the left and right of
883 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
884 coordinates of the upper-left corner of the box. Return in
885 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
886
887INLINE void
888window_box (w, area, box_x, box_y, box_width, box_height)
889 struct window *w;
890 int area;
891 int *box_x, *box_y, *box_width, *box_height;
892{
893 struct frame *f = XFRAME (w->frame);
894
895 *box_width = window_box_width (w, area);
896 *box_height = window_box_height (w);
897 *box_x = window_box_left (w, area);
898 *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
899 + XFASTINT (w->top) * CANON_Y_UNIT (f));
045dee35
GM
900 if (WINDOW_WANTS_HEADER_LINE_P (w))
901 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
ded34426 902}
1adc55de 903
1adc55de 904
5f5c8ee5
GM
905/* Get the bounding box of the display area AREA of window W, without
906 mode lines. AREA < 0 means the whole window, not including bitmap
907 areas to the left and right of the window. Return in *TOP_LEFT_X
908 and TOP_LEFT_Y the frame-relative pixel coordinates of the
909 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
910 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
911 box. */
ded34426 912
5f5c8ee5
GM
913INLINE void
914window_box_edges (w, area, top_left_x, top_left_y,
915 bottom_right_x, bottom_right_y)
916 struct window *w;
917 int area;
918 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 919{
5f5c8ee5
GM
920 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
921 bottom_right_y);
922 *bottom_right_x += *top_left_x;
923 *bottom_right_y += *top_left_y;
48ae5f0a
KH
924}
925
5f5c8ee5
GM
926
927\f
928/***********************************************************************
929 Utilities
930 ***********************************************************************/
931
3a641a69
GM
932/* Return 1 if position CHARPOS is visible in window W.
933 Set *FULLY to 1 if POS is visible and the line containing
934 POS is fully visible. */
935
936int
937pos_visible_p (w, charpos, fully)
938 struct window *w;
939 int charpos, *fully;
940{
941 struct it it;
942 struct text_pos top;
943 int visible_p, bottom_y;
944
945 *fully = visible_p = 0;
946 SET_TEXT_POS_FROM_MARKER (top, w->start);
947 start_display (&it, w, top);
948
949 move_it_to (&it, charpos, 0, it.last_visible_y, -1,
950 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
951
952 if (IT_CHARPOS (it) == charpos)
953 {
954 int line_height;
955
956 if (it.max_ascent == 0 && it.max_descent == 0)
d5789b65 957 line_height = last_height;
3a641a69 958 else
d5789b65 959 line_height = it.max_ascent + it.max_descent;
3a641a69
GM
960
961 *fully = it.current_y + line_height <= it.last_visible_y;
962 visible_p = 1;
963 }
964 else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
965 {
966 move_it_by_lines (&it, 1, 0);
967 if (charpos < IT_CHARPOS (it))
968 {
969 visible_p = 1;
970 *fully = 0;
971 }
972 }
973
974 return visible_p;
975}
976
977
4fdb80f2
GM
978/* Return the next character from STR which is MAXLEN bytes long.
979 Return in *LEN the length of the character. This is like
980 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
9ab8560d 981 we find one, we return a `?', but with the length of the invalid
4fdb80f2
GM
982 character. */
983
984static INLINE int
7a5b8a93 985string_char_and_length (str, maxlen, len)
4fdb80f2 986 unsigned char *str;
7a5b8a93 987 int maxlen, *len;
4fdb80f2
GM
988{
989 int c;
990
991 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
992 if (!CHAR_VALID_P (c, 1))
993 /* We may not change the length here because other places in Emacs
9ab8560d 994 don't use this function, i.e. they silently accept invalid
4fdb80f2
GM
995 characters. */
996 c = '?';
997
998 return c;
999}
1000
1001
1002
5f5c8ee5
GM
1003/* Given a position POS containing a valid character and byte position
1004 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
1005
1006static struct text_pos
1007string_pos_nchars_ahead (pos, string, nchars)
1008 struct text_pos pos;
1009 Lisp_Object string;
1010 int nchars;
0b1005ef 1011{
5f5c8ee5
GM
1012 xassert (STRINGP (string) && nchars >= 0);
1013
1014 if (STRING_MULTIBYTE (string))
1015 {
1016 int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos);
1017 unsigned char *p = XSTRING (string)->data + BYTEPOS (pos);
1018 int len;
1019
1020 while (nchars--)
1021 {
4fdb80f2 1022 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1023 p += len, rest -= len;
1024 xassert (rest >= 0);
1025 CHARPOS (pos) += 1;
1026 BYTEPOS (pos) += len;
1027 }
1028 }
1029 else
1030 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
1031
1032 return pos;
0a9dc68b
RS
1033}
1034
0a9dc68b 1035
5f5c8ee5
GM
1036/* Value is the text position, i.e. character and byte position,
1037 for character position CHARPOS in STRING. */
1038
1039static INLINE struct text_pos
1040string_pos (charpos, string)
1041 int charpos;
0a9dc68b 1042 Lisp_Object string;
0a9dc68b 1043{
5f5c8ee5
GM
1044 struct text_pos pos;
1045 xassert (STRINGP (string));
1046 xassert (charpos >= 0);
1047 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
1048 return pos;
1049}
1050
1051
1052/* Value is a text position, i.e. character and byte position, for
1053 character position CHARPOS in C string S. MULTIBYTE_P non-zero
1054 means recognize multibyte characters. */
1055
1056static struct text_pos
1057c_string_pos (charpos, s, multibyte_p)
1058 int charpos;
1059 unsigned char *s;
1060 int multibyte_p;
1061{
1062 struct text_pos pos;
1063
1064 xassert (s != NULL);
1065 xassert (charpos >= 0);
1066
1067 if (multibyte_p)
0a9dc68b 1068 {
5f5c8ee5
GM
1069 int rest = strlen (s), len;
1070
1071 SET_TEXT_POS (pos, 0, 0);
1072 while (charpos--)
0a9dc68b 1073 {
4fdb80f2 1074 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
1075 s += len, rest -= len;
1076 xassert (rest >= 0);
1077 CHARPOS (pos) += 1;
1078 BYTEPOS (pos) += len;
0a9dc68b
RS
1079 }
1080 }
5f5c8ee5
GM
1081 else
1082 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 1083
5f5c8ee5
GM
1084 return pos;
1085}
0a9dc68b 1086
0a9dc68b 1087
5f5c8ee5
GM
1088/* Value is the number of characters in C string S. MULTIBYTE_P
1089 non-zero means recognize multibyte characters. */
0a9dc68b 1090
5f5c8ee5
GM
1091static int
1092number_of_chars (s, multibyte_p)
1093 unsigned char *s;
1094 int multibyte_p;
1095{
1096 int nchars;
1097
1098 if (multibyte_p)
1099 {
1100 int rest = strlen (s), len;
1101 unsigned char *p = (unsigned char *) s;
0a9dc68b 1102
5f5c8ee5
GM
1103 for (nchars = 0; rest > 0; ++nchars)
1104 {
4fdb80f2 1105 string_char_and_length (p, rest, &len);
5f5c8ee5 1106 rest -= len, p += len;
0a9dc68b
RS
1107 }
1108 }
5f5c8ee5
GM
1109 else
1110 nchars = strlen (s);
1111
1112 return nchars;
0b1005ef
KH
1113}
1114
5f5c8ee5
GM
1115
1116/* Compute byte position NEWPOS->bytepos corresponding to
1117 NEWPOS->charpos. POS is a known position in string STRING.
1118 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1119
5f5c8ee5
GM
1120static void
1121compute_string_pos (newpos, pos, string)
1122 struct text_pos *newpos, pos;
1123 Lisp_Object string;
76412d64 1124{
5f5c8ee5
GM
1125 xassert (STRINGP (string));
1126 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
1127
1128 if (STRING_MULTIBYTE (string))
6fc556fd
KR
1129 *newpos = string_pos_nchars_ahead (pos, string,
1130 CHARPOS (*newpos) - CHARPOS (pos));
5f5c8ee5
GM
1131 else
1132 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1133}
1134
9c74a0dd 1135
5f5c8ee5
GM
1136\f
1137/***********************************************************************
1138 Lisp form evaluation
1139 ***********************************************************************/
1140
116d6f5c 1141/* Error handler for safe_eval and safe_call. */
5f5c8ee5
GM
1142
1143static Lisp_Object
116d6f5c 1144safe_eval_handler (arg)
5f5c8ee5
GM
1145 Lisp_Object arg;
1146{
1147 return Qnil;
1148}
1149
1150
1151/* Evaluate SEXPR and return the result, or nil if something went
1152 wrong. */
1153
71e5b1b8 1154Lisp_Object
116d6f5c 1155safe_eval (sexpr)
5f5c8ee5
GM
1156 Lisp_Object sexpr;
1157{
1158 int count = specpdl_ptr - specpdl;
0d8b31c0 1159 struct gcpro gcpro1;
5f5c8ee5 1160 Lisp_Object val;
0d8b31c0
GM
1161
1162 GCPRO1 (sexpr);
5f5c8ee5 1163 specbind (Qinhibit_redisplay, Qt);
116d6f5c 1164 val = internal_condition_case_1 (Feval, sexpr, Qerror, safe_eval_handler);
0d8b31c0
GM
1165 UNGCPRO;
1166 return unbind_to (count, val);
1167}
1168
1169
1170/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
1171 Return the result, or nil if something went wrong. */
1172
1173Lisp_Object
116d6f5c 1174safe_call (nargs, args)
0d8b31c0
GM
1175 int nargs;
1176 Lisp_Object *args;
1177{
1178 int count = specpdl_ptr - specpdl;
1179 Lisp_Object val;
1180 struct gcpro gcpro1;
1181
1182 GCPRO1 (args[0]);
1183 gcpro1.nvars = nargs;
1184 specbind (Qinhibit_redisplay, Qt);
1185 val = internal_condition_case_2 (Ffuncall, nargs, args, Qerror,
116d6f5c 1186 safe_eval_handler);
0d8b31c0 1187 UNGCPRO;
5f5c8ee5
GM
1188 return unbind_to (count, val);
1189}
1190
1191
116d6f5c
GM
1192/* Call function FN with one argument ARG.
1193 Return the result, or nil if something went wrong. */
1194
1195Lisp_Object
1196safe_call1 (fn, arg)
1197 Lisp_Object fn, arg;
1198{
1199 Lisp_Object args[2];
1200 args[0] = fn;
1201 args[1] = arg;
1202 return safe_call (2, args);
1203}
1204
1205
5f5c8ee5
GM
1206\f
1207/***********************************************************************
1208 Debugging
1209 ***********************************************************************/
1210
1211#if 0
1212
1213/* Define CHECK_IT to perform sanity checks on iterators.
1214 This is for debugging. It is too slow to do unconditionally. */
1215
1216static void
1217check_it (it)
1218 struct it *it;
1219{
1220 if (it->method == next_element_from_string)
a2889657 1221 {
5f5c8ee5
GM
1222 xassert (STRINGP (it->string));
1223 xassert (IT_STRING_CHARPOS (*it) >= 0);
1224 }
1225 else if (it->method == next_element_from_buffer)
1226 {
1227 /* Check that character and byte positions agree. */
1228 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1229 }
73af359d 1230
5f5c8ee5
GM
1231 if (it->dpvec)
1232 xassert (it->current.dpvec_index >= 0);
1233 else
1234 xassert (it->current.dpvec_index < 0);
1235}
1f40cad2 1236
5f5c8ee5
GM
1237#define CHECK_IT(IT) check_it ((IT))
1238
1239#else /* not 0 */
1240
1241#define CHECK_IT(IT) (void) 0
1242
1243#endif /* not 0 */
1244
1245
1246#if GLYPH_DEBUG
1247
1248/* Check that the window end of window W is what we expect it
1249 to be---the last row in the current matrix displaying text. */
1250
1251static void
1252check_window_end (w)
1253 struct window *w;
1254{
1255 if (!MINI_WINDOW_P (w)
1256 && !NILP (w->window_end_valid))
1257 {
1258 struct glyph_row *row;
1259 xassert ((row = MATRIX_ROW (w->current_matrix,
1260 XFASTINT (w->window_end_vpos)),
1261 !row->enabled_p
1262 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1263 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1264 }
1265}
1266
1267#define CHECK_WINDOW_END(W) check_window_end ((W))
1268
1269#else /* not GLYPH_DEBUG */
1270
1271#define CHECK_WINDOW_END(W) (void) 0
1272
1273#endif /* not GLYPH_DEBUG */
1274
1275
1276\f
1277/***********************************************************************
1278 Iterator initialization
1279 ***********************************************************************/
1280
1281/* Initialize IT for displaying current_buffer in window W, starting
1282 at character position CHARPOS. CHARPOS < 0 means that no buffer
1283 position is specified which is useful when the iterator is assigned
1284 a position later. BYTEPOS is the byte position corresponding to
1285 CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS.
1286
1287 If ROW is not null, calls to produce_glyphs with IT as parameter
1288 will produce glyphs in that row.
1289
1290 BASE_FACE_ID is the id of a base face to use. It must be one of
1291 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or
045dee35 1292 HEADER_LINE_FACE_ID for displaying mode lines, or TOOL_BAR_FACE_ID for
e037b9ec 1293 displaying the tool-bar.
5f5c8ee5
GM
1294
1295 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or
045dee35 1296 HEADER_LINE_FACE_ID, the iterator will be initialized to use the
5f5c8ee5
GM
1297 corresponding mode line glyph row of the desired matrix of W. */
1298
1299void
1300init_iterator (it, w, charpos, bytepos, row, base_face_id)
1301 struct it *it;
1302 struct window *w;
1303 int charpos, bytepos;
1304 struct glyph_row *row;
1305 enum face_id base_face_id;
1306{
1307 int highlight_region_p;
5f5c8ee5
GM
1308
1309 /* Some precondition checks. */
1310 xassert (w != NULL && it != NULL);
5f5c8ee5
GM
1311 xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
1312
1313 /* If face attributes have been changed since the last redisplay,
1314 free realized faces now because they depend on face definitions
1315 that might have changed. */
1316 if (face_change_count)
1317 {
1318 face_change_count = 0;
1319 free_all_realized_faces (Qnil);
1320 }
1321
1322 /* Use one of the mode line rows of W's desired matrix if
1323 appropriate. */
1324 if (row == NULL)
1325 {
1326 if (base_face_id == MODE_LINE_FACE_ID)
1327 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
1328 else if (base_face_id == HEADER_LINE_FACE_ID)
1329 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5
GM
1330 }
1331
1332 /* Clear IT. */
1333 bzero (it, sizeof *it);
1334 it->current.overlay_string_index = -1;
1335 it->current.dpvec_index = -1;
5f5c8ee5
GM
1336 it->base_face_id = base_face_id;
1337
1338 /* The window in which we iterate over current_buffer: */
1339 XSETWINDOW (it->window, w);
1340 it->w = w;
1341 it->f = XFRAME (w->frame);
1342
d475bcb8
GM
1343 /* Extra space between lines (on window systems only). */
1344 if (base_face_id == DEFAULT_FACE_ID
1345 && FRAME_WINDOW_P (it->f))
1346 {
1347 if (NATNUMP (current_buffer->extra_line_spacing))
1348 it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
1349 else if (it->f->extra_line_spacing > 0)
1350 it->extra_line_spacing = it->f->extra_line_spacing;
1351 }
1352
5f5c8ee5
GM
1353 /* If realized faces have been removed, e.g. because of face
1354 attribute changes of named faces, recompute them. */
1355 if (FRAME_FACE_CACHE (it->f)->used == 0)
1356 recompute_basic_faces (it->f);
1357
5f5c8ee5
GM
1358 /* Current value of the `space-width', and 'height' properties. */
1359 it->space_width = Qnil;
1360 it->font_height = Qnil;
1361
1362 /* Are control characters displayed as `^C'? */
1363 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
1364
1365 /* -1 means everything between a CR and the following line end
1366 is invisible. >0 means lines indented more than this value are
1367 invisible. */
1368 it->selective = (INTEGERP (current_buffer->selective_display)
1369 ? XFASTINT (current_buffer->selective_display)
1370 : (!NILP (current_buffer->selective_display)
1371 ? -1 : 0));
1372 it->selective_display_ellipsis_p
1373 = !NILP (current_buffer->selective_display_ellipses);
1374
1375 /* Display table to use. */
1376 it->dp = window_display_table (w);
1377
1378 /* Are multibyte characters enabled in current_buffer? */
1379 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1380
1381 /* Non-zero if we should highlight the region. */
1382 highlight_region_p
1383 = (!NILP (Vtransient_mark_mode)
1384 && !NILP (current_buffer->mark_active)
1385 && XMARKER (current_buffer->mark)->buffer != 0);
1386
1387 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
1388 start and end of a visible region in window IT->w. Set both to
1389 -1 to indicate no region. */
1390 if (highlight_region_p
1391 /* Maybe highlight only in selected window. */
1392 && (/* Either show region everywhere. */
1393 highlight_nonselected_windows
1394 /* Or show region in the selected window. */
1395 || w == XWINDOW (selected_window)
1396 /* Or show the region if we are in the mini-buffer and W is
1397 the window the mini-buffer refers to. */
1398 || (MINI_WINDOW_P (XWINDOW (selected_window))
1399 && w == XWINDOW (Vminibuf_scroll_window))))
1400 {
1401 int charpos = marker_position (current_buffer->mark);
1402 it->region_beg_charpos = min (PT, charpos);
1403 it->region_end_charpos = max (PT, charpos);
1404 }
1405 else
1406 it->region_beg_charpos = it->region_end_charpos = -1;
1407
1408 /* Get the position at which the redisplay_end_trigger hook should
1409 be run, if it is to be run at all. */
1410 if (MARKERP (w->redisplay_end_trigger)
1411 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
1412 it->redisplay_end_trigger_charpos
1413 = marker_position (w->redisplay_end_trigger);
1414 else if (INTEGERP (w->redisplay_end_trigger))
1415 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
1416
1417 /* Correct bogus values of tab_width. */
1418 it->tab_width = XINT (current_buffer->tab_width);
1419 if (it->tab_width <= 0 || it->tab_width > 1000)
1420 it->tab_width = 8;
1421
1422 /* Are lines in the display truncated? */
1423 it->truncate_lines_p
1424 = (base_face_id != DEFAULT_FACE_ID
1425 || XINT (it->w->hscroll)
1426 || (truncate_partial_width_windows
1427 && !WINDOW_FULL_WIDTH_P (it->w))
1428 || !NILP (current_buffer->truncate_lines));
1429
1430 /* Get dimensions of truncation and continuation glyphs. These are
1431 displayed as bitmaps under X, so we don't need them for such
1432 frames. */
1433 if (!FRAME_WINDOW_P (it->f))
1434 {
1435 if (it->truncate_lines_p)
1436 {
1437 /* We will need the truncation glyph. */
1438 xassert (it->glyph_row == NULL);
1439 produce_special_glyphs (it, IT_TRUNCATION);
1440 it->truncation_pixel_width = it->pixel_width;
1441 }
1442 else
1443 {
1444 /* We will need the continuation glyph. */
1445 xassert (it->glyph_row == NULL);
1446 produce_special_glyphs (it, IT_CONTINUATION);
1447 it->continuation_pixel_width = it->pixel_width;
1448 }
1449
1450 /* Reset these values to zero becaue the produce_special_glyphs
1451 above has changed them. */
1452 it->pixel_width = it->ascent = it->descent = 0;
312246d1 1453 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
1454 }
1455
1456 /* Set this after getting the dimensions of truncation and
1457 continuation glyphs, so that we don't produce glyphs when calling
1458 produce_special_glyphs, above. */
1459 it->glyph_row = row;
1460 it->area = TEXT_AREA;
1461
1462 /* Get the dimensions of the display area. The display area
1463 consists of the visible window area plus a horizontally scrolled
1464 part to the left of the window. All x-values are relative to the
1465 start of this total display area. */
1466 if (base_face_id != DEFAULT_FACE_ID)
1467 {
1468 /* Mode lines, menu bar in terminal frames. */
1469 it->first_visible_x = 0;
1470 it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
1471 }
1472 else
1473 {
1474 it->first_visible_x
1475 = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
1476 it->last_visible_x = (it->first_visible_x
1477 + window_box_width (w, TEXT_AREA));
1478
1479 /* If we truncate lines, leave room for the truncator glyph(s) at
1480 the right margin. Otherwise, leave room for the continuation
1481 glyph(s). Truncation and continuation glyphs are not inserted
1482 for window-based redisplay. */
1483 if (!FRAME_WINDOW_P (it->f))
1484 {
1485 if (it->truncate_lines_p)
1486 it->last_visible_x -= it->truncation_pixel_width;
1487 else
1488 it->last_visible_x -= it->continuation_pixel_width;
1489 }
1490
045dee35
GM
1491 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
1492 it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
1493 }
1494
1495 /* Leave room for a border glyph. */
1496 if (!FRAME_WINDOW_P (it->f)
1497 && !WINDOW_RIGHTMOST_P (it->w))
1498 it->last_visible_x -= 1;
1499
1500 it->last_visible_y = window_text_bottom_y (w);
1501
1502 /* For mode lines and alike, arrange for the first glyph having a
1503 left box line if the face specifies a box. */
1504 if (base_face_id != DEFAULT_FACE_ID)
1505 {
1506 struct face *face;
1507
1508 it->face_id = base_face_id;
1509
1510 /* If we have a boxed mode line, make the first character appear
1511 with a left box line. */
1512 face = FACE_FROM_ID (it->f, base_face_id);
1513 if (face->box != FACE_NO_BOX)
1514 it->start_of_box_run_p = 1;
1515 }
1516
1517 /* If a buffer position was specified, set the iterator there,
1518 getting overlays and face properties from that position. */
1519 if (charpos > 0)
1520 {
1521 it->end_charpos = ZV;
1522 it->face_id = -1;
1523 IT_CHARPOS (*it) = charpos;
1524
1525 /* Compute byte position if not specified. */
1526 if (bytepos <= 0)
1527 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
1528 else
1529 IT_BYTEPOS (*it) = bytepos;
1530
1531 /* Compute faces etc. */
1532 reseat (it, it->current.pos, 1);
1533 }
1534
1535 CHECK_IT (it);
1536}
1537
1538
1539/* Initialize IT for the display of window W with window start POS. */
1540
1541void
1542start_display (it, w, pos)
1543 struct it *it;
1544 struct window *w;
1545 struct text_pos pos;
1546{
1547 int start_at_line_beg_p;
1548 struct glyph_row *row;
045dee35 1549 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
1550 int first_y;
1551
1552 row = w->desired_matrix->rows + first_vpos;
1553 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
1554 first_y = it->current_y;
1555
1556 /* If window start is not at a line start, move back to the line
1557 start. This makes sure that we take continuation lines into
1558 account. */
1559 start_at_line_beg_p = (CHARPOS (pos) == BEGV
1560 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
1561 if (!start_at_line_beg_p)
1562 reseat_at_previous_visible_line_start (it);
1563
5f5c8ee5
GM
1564 /* If window start is not at a line start, skip forward to POS to
1565 get the correct continuation_lines_width and current_x. */
1566 if (!start_at_line_beg_p)
1567 {
1568 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
1569
1570 /* If lines are continued, this line may end in the middle of a
1571 multi-glyph character (e.g. a control character displayed as
1572 \003, or in the middle of an overlay string). In this case
1573 move_it_to above will not have taken us to the start of
1574 the continuation line but to the end of the continued line. */
b28cb6ed 1575 if (!it->truncate_lines_p)
5f5c8ee5 1576 {
b28cb6ed 1577 if (it->current_x > 0)
5f5c8ee5 1578 {
b28cb6ed
GM
1579 if (it->current.dpvec_index >= 0
1580 || it->current.overlay_string_index >= 0)
1581 {
cafafe0b 1582 set_iterator_to_next (it, 1);
b28cb6ed
GM
1583 move_it_in_display_line_to (it, -1, -1, 0);
1584 }
1585
1586 it->continuation_lines_width += it->current_x;
5f5c8ee5 1587 }
b28cb6ed
GM
1588
1589 /* We're starting a new display line, not affected by the
1590 height of the continued line, so clear the appropriate
1591 fields in the iterator structure. */
1592 it->max_ascent = it->max_descent = 0;
1593 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5
GM
1594 }
1595
1596 it->current_y = first_y;
1597 it->vpos = 0;
1598 it->current_x = it->hpos = 0;
1599 }
1600
1601#if 0 /* Don't assert the following because start_display is sometimes
1602 called intentionally with a window start that is not at a
1603 line start. Please leave this code in as a comment. */
1604
1605 /* Window start should be on a line start, now. */
1606 xassert (it->continuation_lines_width
1607 || IT_CHARPOS (it) == BEGV
1608 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
1609#endif /* 0 */
1610}
1611
1612
1613/* Initialize IT for stepping through current_buffer in window W,
1614 starting at position POS that includes overlay string and display
1615 vector/ control character translation position information. */
1616
1617static void
1618init_from_display_pos (it, w, pos)
1619 struct it *it;
1620 struct window *w;
1621 struct display_pos *pos;
1622{
1623 /* Keep in mind: the call to reseat in init_iterator skips invisible
1624 text, so we might end up at a position different from POS. This
1625 is only a problem when POS is a row start after a newline and an
1626 overlay starts there with an after-string, and the overlay has an
1627 invisible property. Since we don't skip invisible text in
1628 display_line and elsewhere immediately after consuming the
1629 newline before the row start, such a POS will not be in a string,
1630 but the call to init_iterator below will move us to the
1631 after-string. */
1632 init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos),
1633 NULL, DEFAULT_FACE_ID);
1634
1635 /* If position is within an overlay string, set up IT to
1636 the right overlay string. */
1637 if (pos->overlay_string_index >= 0)
1638 {
1639 int relative_index;
1640
1641 /* We already have the first chunk of overlay strings in
1642 IT->overlay_strings. Load more until the one for
1643 pos->overlay_string_index is in IT->overlay_strings. */
1644 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
1645 {
1646 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
1647 it->current.overlay_string_index = 0;
1648 while (n--)
1649 {
1650 load_overlay_strings (it);
1651 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
1652 }
1653 }
1654
1655 it->current.overlay_string_index = pos->overlay_string_index;
1656 relative_index = (it->current.overlay_string_index
1657 % OVERLAY_STRING_CHUNK_SIZE);
1658 it->string = it->overlay_strings[relative_index];
cafafe0b 1659 xassert (STRINGP (it->string));
5f5c8ee5
GM
1660 it->current.string_pos = pos->string_pos;
1661 it->method = next_element_from_string;
1662 }
1663 else if (CHARPOS (pos->string_pos) >= 0)
1664 {
1665 /* Recorded position is not in an overlay string, but in another
1666 string. This can only be a string from a `display' property.
1667 IT should already be filled with that string. */
1668 it->current.string_pos = pos->string_pos;
1669 xassert (STRINGP (it->string));
1670 }
1671
1672 /* Restore position in display vector translations or control
1673 character translations. */
1674 if (pos->dpvec_index >= 0)
1675 {
1676 /* This fills IT->dpvec. */
1677 get_next_display_element (it);
1678 xassert (it->dpvec && it->current.dpvec_index == 0);
1679 it->current.dpvec_index = pos->dpvec_index;
1680 }
1681
1682 CHECK_IT (it);
1683}
1684
1685
1686/* Initialize IT for stepping through current_buffer in window W
1687 starting at ROW->start. */
1688
1689static void
1690init_to_row_start (it, w, row)
1691 struct it *it;
1692 struct window *w;
1693 struct glyph_row *row;
1694{
1695 init_from_display_pos (it, w, &row->start);
1696 it->continuation_lines_width = row->continuation_lines_width;
1697 CHECK_IT (it);
1698}
1699
1700
1701/* Initialize IT for stepping through current_buffer in window W
1702 starting in the line following ROW, i.e. starting at ROW->end. */
1703
1704static void
1705init_to_row_end (it, w, row)
1706 struct it *it;
1707 struct window *w;
1708 struct glyph_row *row;
1709{
1710 init_from_display_pos (it, w, &row->end);
1711
1712 if (row->continued_p)
1713 it->continuation_lines_width = (row->continuation_lines_width
1714 + row->pixel_width);
1715 CHECK_IT (it);
1716}
1717
1718
1719
1720\f
1721/***********************************************************************
1722 Text properties
1723 ***********************************************************************/
1724
1725/* Called when IT reaches IT->stop_charpos. Handle text property and
1726 overlay changes. Set IT->stop_charpos to the next position where
1727 to stop. */
1728
1729static void
1730handle_stop (it)
1731 struct it *it;
1732{
1733 enum prop_handled handled;
1734 int handle_overlay_change_p = 1;
1735 struct props *p;
1736
1737 it->dpvec = NULL;
1738 it->current.dpvec_index = -1;
1739
1740 do
1741 {
1742 handled = HANDLED_NORMALLY;
1743
1744 /* Call text property handlers. */
1745 for (p = it_props; p->handler; ++p)
1746 {
1747 handled = p->handler (it);
2970b9be 1748
5f5c8ee5
GM
1749 if (handled == HANDLED_RECOMPUTE_PROPS)
1750 break;
1751 else if (handled == HANDLED_RETURN)
1752 return;
1753 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
1754 handle_overlay_change_p = 0;
1755 }
1756
1757 if (handled != HANDLED_RECOMPUTE_PROPS)
1758 {
1759 /* Don't check for overlay strings below when set to deliver
1760 characters from a display vector. */
1761 if (it->method == next_element_from_display_vector)
1762 handle_overlay_change_p = 0;
1763
1764 /* Handle overlay changes. */
1765 if (handle_overlay_change_p)
1766 handled = handle_overlay_change (it);
1767
1768 /* Determine where to stop next. */
1769 if (handled == HANDLED_NORMALLY)
1770 compute_stop_pos (it);
1771 }
1772 }
1773 while (handled == HANDLED_RECOMPUTE_PROPS);
1774}
1775
1776
1777/* Compute IT->stop_charpos from text property and overlay change
1778 information for IT's current position. */
1779
1780static void
1781compute_stop_pos (it)
1782 struct it *it;
1783{
1784 register INTERVAL iv, next_iv;
1785 Lisp_Object object, limit, position;
1786
1787 /* If nowhere else, stop at the end. */
1788 it->stop_charpos = it->end_charpos;
1789
1790 if (STRINGP (it->string))
1791 {
1792 /* Strings are usually short, so don't limit the search for
1793 properties. */
1794 object = it->string;
1795 limit = Qnil;
1796 XSETFASTINT (position, IT_STRING_CHARPOS (*it));
1797 }
1798 else
1799 {
1800 int charpos;
1801
1802 /* If next overlay change is in front of the current stop pos
1803 (which is IT->end_charpos), stop there. Note: value of
1804 next_overlay_change is point-max if no overlay change
1805 follows. */
1806 charpos = next_overlay_change (IT_CHARPOS (*it));
1807 if (charpos < it->stop_charpos)
1808 it->stop_charpos = charpos;
1809
1810 /* If showing the region, we have to stop at the region
1811 start or end because the face might change there. */
1812 if (it->region_beg_charpos > 0)
1813 {
1814 if (IT_CHARPOS (*it) < it->region_beg_charpos)
1815 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
1816 else if (IT_CHARPOS (*it) < it->region_end_charpos)
1817 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
1818 }
1819
1820 /* Set up variables for computing the stop position from text
1821 property changes. */
1822 XSETBUFFER (object, current_buffer);
1823 XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
1824 XSETFASTINT (position, IT_CHARPOS (*it));
1825
1826 }
1827
1828 /* Get the interval containing IT's position. Value is a null
1829 interval if there isn't such an interval. */
1830 iv = validate_interval_range (object, &position, &position, 0);
1831 if (!NULL_INTERVAL_P (iv))
1832 {
1833 Lisp_Object values_here[LAST_PROP_IDX];
1834 struct props *p;
1835
1836 /* Get properties here. */
1837 for (p = it_props; p->handler; ++p)
1838 values_here[p->idx] = textget (iv->plist, *p->name);
1839
1840 /* Look for an interval following iv that has different
1841 properties. */
1842 for (next_iv = next_interval (iv);
1843 (!NULL_INTERVAL_P (next_iv)
1844 && (NILP (limit)
1845 || XFASTINT (limit) > next_iv->position));
1846 next_iv = next_interval (next_iv))
1847 {
1848 for (p = it_props; p->handler; ++p)
1849 {
1850 Lisp_Object new_value;
1851
1852 new_value = textget (next_iv->plist, *p->name);
1853 if (!EQ (values_here[p->idx], new_value))
1854 break;
1855 }
1856
1857 if (p->handler)
1858 break;
1859 }
1860
1861 if (!NULL_INTERVAL_P (next_iv))
1862 {
1863 if (INTEGERP (limit)
1864 && next_iv->position >= XFASTINT (limit))
1865 /* No text property change up to limit. */
1866 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
1867 else
1868 /* Text properties change in next_iv. */
1869 it->stop_charpos = min (it->stop_charpos, next_iv->position);
1870 }
1871 }
1872
1873 xassert (STRINGP (it->string)
1874 || (it->stop_charpos >= BEGV
1875 && it->stop_charpos >= IT_CHARPOS (*it)));
1876}
1877
1878
1879/* Return the position of the next overlay change after POS in
1880 current_buffer. Value is point-max if no overlay change
1881 follows. This is like `next-overlay-change' but doesn't use
1882 xmalloc. */
1883
1884static int
1885next_overlay_change (pos)
1886 int pos;
1887{
1888 int noverlays;
1889 int endpos;
1890 Lisp_Object *overlays;
1891 int len;
1892 int i;
1893
1894 /* Get all overlays at the given position. */
1895 len = 10;
1896 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 1897 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
1898 if (noverlays > len)
1899 {
1900 len = noverlays;
1901 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 1902 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
1903 }
1904
1905 /* If any of these overlays ends before endpos,
1906 use its ending point instead. */
1907 for (i = 0; i < noverlays; ++i)
1908 {
1909 Lisp_Object oend;
1910 int oendpos;
1911
1912 oend = OVERLAY_END (overlays[i]);
1913 oendpos = OVERLAY_POSITION (oend);
1914 endpos = min (endpos, oendpos);
1915 }
1916
1917 return endpos;
1918}
1919
1920
1921\f
1922/***********************************************************************
1923 Fontification
1924 ***********************************************************************/
1925
1926/* Handle changes in the `fontified' property of the current buffer by
1927 calling hook functions from Qfontification_functions to fontify
1928 regions of text. */
1929
1930static enum prop_handled
1931handle_fontified_prop (it)
1932 struct it *it;
1933{
1934 Lisp_Object prop, pos;
1935 enum prop_handled handled = HANDLED_NORMALLY;
1936
1937 /* Get the value of the `fontified' property at IT's current buffer
1938 position. (The `fontified' property doesn't have a special
1939 meaning in strings.) If the value is nil, call functions from
1940 Qfontification_functions. */
1941 if (!STRINGP (it->string)
1942 && it->s == NULL
1943 && !NILP (Vfontification_functions)
085536c2 1944 && !NILP (Vrun_hooks)
5f5c8ee5
GM
1945 && (pos = make_number (IT_CHARPOS (*it)),
1946 prop = Fget_char_property (pos, Qfontified, Qnil),
1947 NILP (prop)))
1948 {
085536c2
GM
1949 int count = specpdl_ptr - specpdl;
1950 Lisp_Object val;
1951
1952 val = Vfontification_functions;
1953 specbind (Qfontification_functions, Qnil);
1954 specbind (Qafter_change_functions, Qnil);
1955
1956 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
116d6f5c 1957 safe_call1 (val, pos);
085536c2
GM
1958 else
1959 {
1960 Lisp_Object globals, fn;
1961 struct gcpro gcpro1, gcpro2;
5f5c8ee5 1962
085536c2
GM
1963 globals = Qnil;
1964 GCPRO2 (val, globals);
1965
1966 for (; CONSP (val); val = XCDR (val))
1967 {
1968 fn = XCAR (val);
1969
1970 if (EQ (fn, Qt))
1971 {
1972 /* A value of t indicates this hook has a local
1973 binding; it means to run the global binding too.
1974 In a global value, t should not occur. If it
1975 does, we must ignore it to avoid an endless
1976 loop. */
1977 for (globals = Fdefault_value (Qfontification_functions);
1978 CONSP (globals);
1979 globals = XCDR (globals))
1980 {
1981 fn = XCAR (globals);
1982 if (!EQ (fn, Qt))
116d6f5c 1983 safe_call1 (fn, pos);
085536c2
GM
1984 }
1985 }
1986 else
116d6f5c 1987 safe_call1 (fn, pos);
085536c2
GM
1988 }
1989
1990 UNGCPRO;
1991 }
1992
1993 unbind_to (count, Qnil);
5f5c8ee5
GM
1994
1995 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
1996 something. This avoids an endless loop if they failed to
1997 fontify the text for which reason ever. */
1998 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
1999 handled = HANDLED_RECOMPUTE_PROPS;
2000 }
2001
2002 return handled;
2003}
2004
2005
2006\f
2007/***********************************************************************
2008 Faces
2009 ***********************************************************************/
2010
2011/* Set up iterator IT from face properties at its current position.
2012 Called from handle_stop. */
2013
2014static enum prop_handled
2015handle_face_prop (it)
2016 struct it *it;
2017{
2018 int new_face_id, next_stop;
2019
2020 if (!STRINGP (it->string))
2021 {
2022 new_face_id
2023 = face_at_buffer_position (it->w,
2024 IT_CHARPOS (*it),
2025 it->region_beg_charpos,
2026 it->region_end_charpos,
2027 &next_stop,
2028 (IT_CHARPOS (*it)
2029 + TEXT_PROP_DISTANCE_LIMIT),
2030 0);
2031
2032 /* Is this a start of a run of characters with box face?
2033 Caveat: this can be called for a freshly initialized
2034 iterator; face_id is -1 is this case. We know that the new
2035 face will not change until limit, i.e. if the new face has a
2036 box, all characters up to limit will have one. But, as
2037 usual, we don't know whether limit is really the end. */
2038 if (new_face_id != it->face_id)
2039 {
2040 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2041
2042 /* If new face has a box but old face has not, this is
2043 the start of a run of characters with box, i.e. it has
2044 a shadow on the left side. The value of face_id of the
2045 iterator will be -1 if this is the initial call that gets
2046 the face. In this case, we have to look in front of IT's
2047 position and see whether there is a face != new_face_id. */
2048 it->start_of_box_run_p
2049 = (new_face->box != FACE_NO_BOX
2050 && (it->face_id >= 0
2051 || IT_CHARPOS (*it) == BEG
2052 || new_face_id != face_before_it_pos (it)));
2053 it->face_box_p = new_face->box != FACE_NO_BOX;
2054 }
2055 }
2056 else
2057 {
2058 new_face_id
2059 = face_at_string_position (it->w,
2060 it->string,
2061 IT_STRING_CHARPOS (*it),
2062 (it->current.overlay_string_index >= 0
2063 ? IT_CHARPOS (*it)
2064 : 0),
2065 it->region_beg_charpos,
2066 it->region_end_charpos,
2067 &next_stop,
2068 it->base_face_id);
2069
2070#if 0 /* This shouldn't be neccessary. Let's check it. */
2071 /* If IT is used to display a mode line we would really like to
2072 use the mode line face instead of the frame's default face. */
2073 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
2074 && new_face_id == DEFAULT_FACE_ID)
2075 new_face_id = MODE_LINE_FACE_ID;
2076#endif
2077
2078 /* Is this a start of a run of characters with box? Caveat:
2079 this can be called for a freshly allocated iterator; face_id
2080 is -1 is this case. We know that the new face will not
2081 change until the next check pos, i.e. if the new face has a
2082 box, all characters up to that position will have a
2083 box. But, as usual, we don't know whether that position
2084 is really the end. */
2085 if (new_face_id != it->face_id)
2086 {
2087 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2088 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
2089
2090 /* If new face has a box but old face hasn't, this is the
2091 start of a run of characters with box, i.e. it has a
2092 shadow on the left side. */
2093 it->start_of_box_run_p
2094 = new_face->box && (old_face == NULL || !old_face->box);
2095 it->face_box_p = new_face->box != FACE_NO_BOX;
2096 }
2097 }
2098
2099 it->face_id = new_face_id;
5f5c8ee5
GM
2100 return HANDLED_NORMALLY;
2101}
2102
2103
2104/* Compute the face one character before or after the current position
2105 of IT. BEFORE_P non-zero means get the face in front of IT's
2106 position. Value is the id of the face. */
2107
2108static int
2109face_before_or_after_it_pos (it, before_p)
2110 struct it *it;
2111 int before_p;
2112{
2113 int face_id, limit;
2114 int next_check_charpos;
2115 struct text_pos pos;
2116
2117 xassert (it->s == NULL);
2118
2119 if (STRINGP (it->string))
2120 {
2121 /* No face change past the end of the string (for the case
2122 we are padding with spaces). No face change before the
2123 string start. */
2124 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size
2125 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
2126 return it->face_id;
2127
2128 /* Set pos to the position before or after IT's current position. */
2129 if (before_p)
2130 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
2131 else
260a86a0
KH
2132 /* For composition, we must check the character after the
2133 composition. */
2134 pos = (it->what == IT_COMPOSITION
2135 ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
2136 : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
5f5c8ee5
GM
2137
2138 /* Get the face for ASCII, or unibyte. */
2139 face_id
2140 = face_at_string_position (it->w,
2141 it->string,
2142 CHARPOS (pos),
2143 (it->current.overlay_string_index >= 0
2144 ? IT_CHARPOS (*it)
2145 : 0),
2146 it->region_beg_charpos,
2147 it->region_end_charpos,
2148 &next_check_charpos,
2149 it->base_face_id);
2150
2151 /* Correct the face for charsets different from ASCII. Do it
2152 for the multibyte case only. The face returned above is
2153 suitable for unibyte text if IT->string is unibyte. */
2154 if (STRING_MULTIBYTE (it->string))
2155 {
2156 unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
2157 int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
980806b6
KH
2158 int c, len;
2159 struct face *face = FACE_FROM_ID (it->f, face_id);
5f5c8ee5 2160
4fdb80f2 2161 c = string_char_and_length (p, rest, &len);
980806b6 2162 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2163 }
2164 }
2165 else
2166 {
70851746
GM
2167 if ((IT_CHARPOS (*it) >= ZV && !before_p)
2168 || (IT_CHARPOS (*it) <= BEGV && before_p))
2169 return it->face_id;
2170
5f5c8ee5
GM
2171 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
2172 pos = it->current.pos;
2173
2174 if (before_p)
c1005d06 2175 DEC_TEXT_POS (pos, it->multibyte_p);
5f5c8ee5 2176 else
260a86a0
KH
2177 {
2178 if (it->what == IT_COMPOSITION)
2179 /* For composition, we must check the position after the
2180 composition. */
2181 pos.charpos += it->cmp_len, pos.bytepos += it->len;
2182 else
c1005d06 2183 INC_TEXT_POS (pos, it->multibyte_p);
260a86a0 2184 }
5f5c8ee5
GM
2185 /* Determine face for CHARSET_ASCII, or unibyte. */
2186 face_id = face_at_buffer_position (it->w,
2187 CHARPOS (pos),
2188 it->region_beg_charpos,
2189 it->region_end_charpos,
2190 &next_check_charpos,
2191 limit, 0);
2192
2193 /* Correct the face for charsets different from ASCII. Do it
2194 for the multibyte case only. The face returned above is
2195 suitable for unibyte text if current_buffer is unibyte. */
2196 if (it->multibyte_p)
2197 {
980806b6
KH
2198 int c = FETCH_MULTIBYTE_CHAR (CHARPOS (pos));
2199 struct face *face = FACE_FROM_ID (it->f, face_id);
2200 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2201 }
2202 }
2203
2204 return face_id;
2205}
2206
2207
2208\f
2209/***********************************************************************
2210 Invisible text
2211 ***********************************************************************/
2212
2213/* Set up iterator IT from invisible properties at its current
2214 position. Called from handle_stop. */
2215
2216static enum prop_handled
2217handle_invisible_prop (it)
2218 struct it *it;
2219{
2220 enum prop_handled handled = HANDLED_NORMALLY;
2221
2222 if (STRINGP (it->string))
2223 {
2224 extern Lisp_Object Qinvisible;
2225 Lisp_Object prop, end_charpos, limit, charpos;
2226
2227 /* Get the value of the invisible text property at the
2228 current position. Value will be nil if there is no such
2229 property. */
2230 XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
2231 prop = Fget_text_property (charpos, Qinvisible, it->string);
2232
eadc0bf8
GM
2233 if (!NILP (prop)
2234 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
2235 {
2236 handled = HANDLED_RECOMPUTE_PROPS;
2237
2238 /* Get the position at which the next change of the
2239 invisible text property can be found in IT->string.
2240 Value will be nil if the property value is the same for
2241 all the rest of IT->string. */
2242 XSETINT (limit, XSTRING (it->string)->size);
2243 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2244 it->string, limit);
2245
2246 /* Text at current position is invisible. The next
2247 change in the property is at position end_charpos.
2248 Move IT's current position to that position. */
2249 if (INTEGERP (end_charpos)
2250 && XFASTINT (end_charpos) < XFASTINT (limit))
2251 {
2252 struct text_pos old;
2253 old = it->current.string_pos;
2254 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
2255 compute_string_pos (&it->current.string_pos, old, it->string);
2256 }
2257 else
2258 {
2259 /* The rest of the string is invisible. If this is an
2260 overlay string, proceed with the next overlay string
2261 or whatever comes and return a character from there. */
2262 if (it->current.overlay_string_index >= 0)
2263 {
2264 next_overlay_string (it);
2265 /* Don't check for overlay strings when we just
2266 finished processing them. */
2267 handled = HANDLED_OVERLAY_STRING_CONSUMED;
2268 }
2269 else
2270 {
2271 struct Lisp_String *s = XSTRING (it->string);
2272 IT_STRING_CHARPOS (*it) = s->size;
2273 IT_STRING_BYTEPOS (*it) = STRING_BYTES (s);
2274 }
2275 }
2276 }
2277 }
2278 else
2279 {
2280 int visible_p, newpos, next_stop;
2281 Lisp_Object pos, prop;
2282
2283 /* First of all, is there invisible text at this position? */
2284 XSETFASTINT (pos, IT_CHARPOS (*it));
2285 prop = Fget_char_property (pos, Qinvisible, it->window);
2286
2287 /* If we are on invisible text, skip over it. */
eadc0bf8
GM
2288 if (TEXT_PROP_MEANS_INVISIBLE (prop)
2289 && IT_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
2290 {
2291 /* Record whether we have to display an ellipsis for the
2292 invisible text. */
2293 int display_ellipsis_p
2294 = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
2295
2296 handled = HANDLED_RECOMPUTE_PROPS;
2297
2298 /* Loop skipping over invisible text. The loop is left at
2299 ZV or with IT on the first char being visible again. */
2300 do
2301 {
2302 /* Try to skip some invisible text. Return value is the
2303 position reached which can be equal to IT's position
2304 if there is nothing invisible here. This skips both
2305 over invisible text properties and overlays with
2306 invisible property. */
2307 newpos = skip_invisible (IT_CHARPOS (*it),
2308 &next_stop, ZV, it->window);
2309
2310 /* If we skipped nothing at all we weren't at invisible
2311 text in the first place. If everything to the end of
2312 the buffer was skipped, end the loop. */
2313 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
2314 visible_p = 1;
2315 else
2316 {
2317 /* We skipped some characters but not necessarily
2318 all there are. Check if we ended up on visible
2319 text. Fget_char_property returns the property of
2320 the char before the given position, i.e. if we
2321 get visible_p = 1, this means that the char at
2322 newpos is visible. */
2323 XSETFASTINT (pos, newpos);
2324 prop = Fget_char_property (pos, Qinvisible, it->window);
2325 visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
2326 }
2327
2328 /* If we ended up on invisible text, proceed to
2329 skip starting with next_stop. */
2330 if (!visible_p)
2331 IT_CHARPOS (*it) = next_stop;
2332 }
2333 while (!visible_p);
2334
2335 /* The position newpos is now either ZV or on visible text. */
2336 IT_CHARPOS (*it) = newpos;
2337 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2338
2339 /* Maybe return `...' next for the end of the invisible text. */
2340 if (display_ellipsis_p)
2341 {
2342 if (it->dp
2343 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
2344 {
2345 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
2346 it->dpvec = v->contents;
2347 it->dpend = v->contents + v->size;
2348 }
2349 else
2350 {
2351 /* Default `...'. */
2352 it->dpvec = default_invis_vector;
2353 it->dpend = default_invis_vector + 3;
2354 }
2355
2356 /* The ellipsis display does not replace the display of
2357 the character at the new position. Indicate this by
2358 setting IT->dpvec_char_len to zero. */
2359 it->dpvec_char_len = 0;
2360
2361 it->current.dpvec_index = 0;
2362 it->method = next_element_from_display_vector;
2363 }
2364 }
2365 }
2366
2367 return handled;
2368}
2369
2370
2371\f
2372/***********************************************************************
2373 'display' property
2374 ***********************************************************************/
2375
2376/* Set up iterator IT from `display' property at its current position.
2377 Called from handle_stop. */
2378
2379static enum prop_handled
2380handle_display_prop (it)
2381 struct it *it;
2382{
2383 Lisp_Object prop, object;
2384 struct text_pos *position;
2385 int space_or_image_found_p;
2386
2387 if (STRINGP (it->string))
2388 {
2389 object = it->string;
2390 position = &it->current.string_pos;
2391 }
2392 else
2393 {
2394 object = Qnil;
2395 position = &it->current.pos;
2396 }
2397
2398 /* Reset those iterator values set from display property values. */
2399 it->font_height = Qnil;
2400 it->space_width = Qnil;
2401 it->voffset = 0;
2402
2403 /* We don't support recursive `display' properties, i.e. string
2404 values that have a string `display' property, that have a string
2405 `display' property etc. */
2406 if (!it->string_from_display_prop_p)
2407 it->area = TEXT_AREA;
2408
2409 prop = Fget_char_property (make_number (position->charpos),
2410 Qdisplay, object);
2411 if (NILP (prop))
2412 return HANDLED_NORMALLY;
2413
2414 space_or_image_found_p = 0;
f3751a65
GM
2415 if (CONSP (prop)
2416 && CONSP (XCAR (prop))
2417 && !EQ (Qmargin, XCAR (XCAR (prop))))
5f5c8ee5 2418 {
f3751a65 2419 /* A list of sub-properties. */
5f5c8ee5
GM
2420 while (CONSP (prop))
2421 {
2422 if (handle_single_display_prop (it, XCAR (prop), object, position))
2423 space_or_image_found_p = 1;
2424 prop = XCDR (prop);
2425 }
2426 }
2427 else if (VECTORP (prop))
2428 {
2429 int i;
2430 for (i = 0; i < XVECTOR (prop)->size; ++i)
2431 if (handle_single_display_prop (it, XVECTOR (prop)->contents[i],
2432 object, position))
2433 space_or_image_found_p = 1;
2434 }
2435 else
2436 {
2437 if (handle_single_display_prop (it, prop, object, position))
2438 space_or_image_found_p = 1;
2439 }
2440
2441 return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY;
2442}
2443
2444
6c577098 2445/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
2446 at START_POS in OBJECT. */
2447
2448static struct text_pos
2449display_prop_end (it, object, start_pos)
2450 struct it *it;
2451 Lisp_Object object;
2452 struct text_pos start_pos;
2453{
2454 Lisp_Object end;
2455 struct text_pos end_pos;
5f5c8ee5 2456
016b5642
MB
2457 end = Fnext_single_char_property_change (make_number (CHARPOS (start_pos)),
2458 Qdisplay, object, Qnil);
6c577098
GM
2459 CHARPOS (end_pos) = XFASTINT (end);
2460 if (STRINGP (object))
5f5c8ee5
GM
2461 compute_string_pos (&end_pos, start_pos, it->string);
2462 else
6c577098 2463 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
2464
2465 return end_pos;
2466}
2467
2468
2469/* Set up IT from a single `display' sub-property value PROP. OBJECT
2470 is the object in which the `display' property was found. *POSITION
2471 is the position at which it was found.
2472
2473 If PROP is a `space' or `image' sub-property, set *POSITION to the
2474 end position of the `display' property.
2475
2476 Value is non-zero if a `space' or `image' property value was found. */
2477
2478static int
2479handle_single_display_prop (it, prop, object, position)
2480 struct it *it;
2481 Lisp_Object prop;
2482 Lisp_Object object;
2483 struct text_pos *position;
2484{
2485 Lisp_Object value;
2486 int space_or_image_found_p = 0;
5f5c8ee5
GM
2487 Lisp_Object form;
2488
d3acf96b 2489 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
5a4c88c4 2490 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 2491 form = Qt;
d3acf96b 2492 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
2493 {
2494 prop = XCDR (prop);
2495 if (!CONSP (prop))
2496 return 0;
2497 form = XCAR (prop);
2498 prop = XCDR (prop);
5f5c8ee5
GM
2499 }
2500
2501 if (!NILP (form) && !EQ (form, Qt))
2502 {
2503 struct gcpro gcpro1;
2504 struct text_pos end_pos, pt;
2505
5f5c8ee5 2506 GCPRO1 (form);
c7aca1ad 2507 end_pos = display_prop_end (it, object, *position);
5f5c8ee5
GM
2508
2509 /* Temporarily set point to the end position, and then evaluate
2510 the form. This makes `(eolp)' work as FORM. */
c7aca1ad
GM
2511 if (BUFFERP (object))
2512 {
2513 CHARPOS (pt) = PT;
2514 BYTEPOS (pt) = PT_BYTE;
2515 TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
2516 }
2517
116d6f5c 2518 form = safe_eval (form);
c7aca1ad
GM
2519
2520 if (BUFFERP (object))
2521 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
5f5c8ee5
GM
2522 UNGCPRO;
2523 }
2524
2525 if (NILP (form))
2526 return 0;
2527
2528 if (CONSP (prop)
2529 && EQ (XCAR (prop), Qheight)
2530 && CONSP (XCDR (prop)))
2531 {
2532 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2533 return 0;
2534
2535 /* `(height HEIGHT)'. */
2536 it->font_height = XCAR (XCDR (prop));
2537 if (!NILP (it->font_height))
2538 {
2539 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2540 int new_height = -1;
2541
2542 if (CONSP (it->font_height)
2543 && (EQ (XCAR (it->font_height), Qplus)
2544 || EQ (XCAR (it->font_height), Qminus))
2545 && CONSP (XCDR (it->font_height))
2546 && INTEGERP (XCAR (XCDR (it->font_height))))
2547 {
2548 /* `(+ N)' or `(- N)' where N is an integer. */
2549 int steps = XINT (XCAR (XCDR (it->font_height)));
2550 if (EQ (XCAR (it->font_height), Qplus))
2551 steps = - steps;
2552 it->face_id = smaller_face (it->f, it->face_id, steps);
2553 }
0d8b31c0 2554 else if (FUNCTIONP (it->font_height))
5f5c8ee5
GM
2555 {
2556 /* Call function with current height as argument.
2557 Value is the new height. */
116d6f5c
GM
2558 Lisp_Object height;
2559 height = safe_call1 (it->font_height,
2560 face->lface[LFACE_HEIGHT_INDEX]);
5f5c8ee5
GM
2561 if (NUMBERP (height))
2562 new_height = XFLOATINT (height);
5f5c8ee5
GM
2563 }
2564 else if (NUMBERP (it->font_height))
2565 {
2566 /* Value is a multiple of the canonical char height. */
2567 struct face *face;
2568
2569 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
2570 new_height = (XFLOATINT (it->font_height)
2571 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
2572 }
2573 else
2574 {
2575 /* Evaluate IT->font_height with `height' bound to the
2576 current specified height to get the new height. */
2577 Lisp_Object value;
2578 int count = specpdl_ptr - specpdl;
2579
2580 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
116d6f5c 2581 value = safe_eval (it->font_height);
5f5c8ee5
GM
2582 unbind_to (count, Qnil);
2583
2584 if (NUMBERP (value))
2585 new_height = XFLOATINT (value);
2586 }
2587
2588 if (new_height > 0)
2589 it->face_id = face_with_height (it->f, it->face_id, new_height);
2590 }
2591 }
2592 else if (CONSP (prop)
2593 && EQ (XCAR (prop), Qspace_width)
2594 && CONSP (XCDR (prop)))
2595 {
2596 /* `(space_width WIDTH)'. */
2597 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2598 return 0;
2599
2600 value = XCAR (XCDR (prop));
2601 if (NUMBERP (value) && XFLOATINT (value) > 0)
2602 it->space_width = value;
2603 }
2604 else if (CONSP (prop)
2605 && EQ (XCAR (prop), Qraise)
2606 && CONSP (XCDR (prop)))
2607 {
5f5c8ee5
GM
2608 /* `(raise FACTOR)'. */
2609 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2610 return 0;
2611
fb3842a8 2612#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
2613 value = XCAR (XCDR (prop));
2614 if (NUMBERP (value))
2615 {
2616 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2617 it->voffset = - (XFLOATINT (value)
1ab3e082 2618 * (FONT_HEIGHT (face->font)));
5f5c8ee5
GM
2619 }
2620#endif /* HAVE_WINDOW_SYSTEM */
2621 }
2622 else if (!it->string_from_display_prop_p)
2623 {
f3751a65
GM
2624 /* `((margin left-margin) VALUE)' or `((margin right-margin)
2625 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
2626 Lisp_Object location, value;
2627 struct text_pos start_pos;
2628 int valid_p;
2629
2630 /* Characters having this form of property are not displayed, so
2631 we have to find the end of the property. */
5f5c8ee5
GM
2632 start_pos = *position;
2633 *position = display_prop_end (it, object, start_pos);
15e26c76 2634 value = Qnil;
5f5c8ee5
GM
2635
2636 /* Let's stop at the new position and assume that all
2637 text properties change there. */
2638 it->stop_charpos = position->charpos;
2639
f3751a65
GM
2640 location = Qunbound;
2641 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 2642 {
f3751a65
GM
2643 Lisp_Object tem;
2644
5f5c8ee5 2645 value = XCDR (prop);
f3751a65
GM
2646 if (CONSP (value))
2647 value = XCAR (value);
2648
2649 tem = XCAR (prop);
2650 if (EQ (XCAR (tem), Qmargin)
2651 && (tem = XCDR (tem),
2652 tem = CONSP (tem) ? XCAR (tem) : Qnil,
2653 (NILP (tem)
2654 || EQ (tem, Qleft_margin)
2655 || EQ (tem, Qright_margin))))
2656 location = tem;
5f5c8ee5 2657 }
f3751a65
GM
2658
2659 if (EQ (location, Qunbound))
5f5c8ee5
GM
2660 {
2661 location = Qnil;
2662 value = prop;
2663 }
2664
2665#ifdef HAVE_WINDOW_SYSTEM
fb3842a8 2666 if (FRAME_TERMCAP_P (it->f))
5f5c8ee5
GM
2667 valid_p = STRINGP (value);
2668 else
2669 valid_p = (STRINGP (value)
2670 || (CONSP (value) && EQ (XCAR (value), Qspace))
2671 || valid_image_p (value));
2672#else /* not HAVE_WINDOW_SYSTEM */
2673 valid_p = STRINGP (value);
2674#endif /* not HAVE_WINDOW_SYSTEM */
2675
2676 if ((EQ (location, Qleft_margin)
2677 || EQ (location, Qright_margin)
2678 || NILP (location))
2679 && valid_p)
2680 {
a21a3943
GM
2681 space_or_image_found_p = 1;
2682
5f5c8ee5
GM
2683 /* Save current settings of IT so that we can restore them
2684 when we are finished with the glyph property value. */
2685 push_it (it);
2686
2687 if (NILP (location))
2688 it->area = TEXT_AREA;
2689 else if (EQ (location, Qleft_margin))
2690 it->area = LEFT_MARGIN_AREA;
2691 else
2692 it->area = RIGHT_MARGIN_AREA;
2693
2694 if (STRINGP (value))
2695 {
2696 it->string = value;
2697 it->multibyte_p = STRING_MULTIBYTE (it->string);
2698 it->current.overlay_string_index = -1;
2699 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2700 it->end_charpos = it->string_nchars
2701 = XSTRING (it->string)->size;
2702 it->method = next_element_from_string;
2703 it->stop_charpos = 0;
2704 it->string_from_display_prop_p = 1;
2705 }
2706 else if (CONSP (value) && EQ (XCAR (value), Qspace))
2707 {
2708 it->method = next_element_from_stretch;
2709 it->object = value;
2710 it->current.pos = it->position = start_pos;
2711 }
2712#ifdef HAVE_WINDOW_SYSTEM
2713 else
2714 {
2715 it->what = IT_IMAGE;
2716 it->image_id = lookup_image (it->f, value);
2717 it->position = start_pos;
2718 it->object = NILP (object) ? it->w->buffer : object;
2719 it->method = next_element_from_image;
2720
02513cdd 2721 /* Say that we haven't consumed the characters with
5f5c8ee5
GM
2722 `display' property yet. The call to pop_it in
2723 set_iterator_to_next will clean this up. */
2724 *position = start_pos;
2725 }
2726#endif /* HAVE_WINDOW_SYSTEM */
2727 }
a21a3943
GM
2728 else
2729 /* Invalid property or property not supported. Restore
2730 the position to what it was before. */
2731 *position = start_pos;
5f5c8ee5
GM
2732 }
2733
2734 return space_or_image_found_p;
2735}
2736
2737
06568bbf
GM
2738/* Check if PROP is a display sub-property value whose text should be
2739 treated as intangible. */
2740
2741static int
2742single_display_prop_intangible_p (prop)
2743 Lisp_Object prop;
2744{
2745 /* Skip over `when FORM'. */
2746 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
2747 {
2748 prop = XCDR (prop);
2749 if (!CONSP (prop))
2750 return 0;
2751 prop = XCDR (prop);
2752 }
2753
2754 if (!CONSP (prop))
2755 return 0;
2756
2757 /* Skip over `margin LOCATION'. If LOCATION is in the margins,
2758 we don't need to treat text as intangible. */
2759 if (EQ (XCAR (prop), Qmargin))
2760 {
2761 prop = XCDR (prop);
2762 if (!CONSP (prop))
2763 return 0;
2764
2765 prop = XCDR (prop);
2766 if (!CONSP (prop)
2767 || EQ (XCAR (prop), Qleft_margin)
2768 || EQ (XCAR (prop), Qright_margin))
2769 return 0;
2770 }
2771
2772 return CONSP (prop) && EQ (XCAR (prop), Qimage);
2773}
2774
2775
2776/* Check if PROP is a display property value whose text should be
2777 treated as intangible. */
2778
2779int
2780display_prop_intangible_p (prop)
2781 Lisp_Object prop;
2782{
2783 if (CONSP (prop)
2784 && CONSP (XCAR (prop))
2785 && !EQ (Qmargin, XCAR (XCAR (prop))))
2786 {
2787 /* A list of sub-properties. */
2788 while (CONSP (prop))
2789 {
2790 if (single_display_prop_intangible_p (XCAR (prop)))
2791 return 1;
2792 prop = XCDR (prop);
2793 }
2794 }
2795 else if (VECTORP (prop))
2796 {
2797 /* A vector of sub-properties. */
2798 int i;
2799 for (i = 0; i < XVECTOR (prop)->size; ++i)
2800 if (single_display_prop_intangible_p (XVECTOR (prop)->contents[i]))
2801 return 1;
2802 }
2803 else
2804 return single_display_prop_intangible_p (prop);
2805
2806 return 0;
2807}
2808
5f5c8ee5 2809\f
260a86a0
KH
2810/***********************************************************************
2811 `composition' property
2812 ***********************************************************************/
2813
2814/* Set up iterator IT from `composition' property at its current
2815 position. Called from handle_stop. */
2816
2817static enum prop_handled
2818handle_composition_prop (it)
2819 struct it *it;
2820{
2821 Lisp_Object prop, string;
2822 int pos, pos_byte, end;
2823 enum prop_handled handled = HANDLED_NORMALLY;
2824
2825 if (STRINGP (it->string))
2826 {
2827 pos = IT_STRING_CHARPOS (*it);
2828 pos_byte = IT_STRING_BYTEPOS (*it);
2829 string = it->string;
2830 }
2831 else
2832 {
2833 pos = IT_CHARPOS (*it);
2834 pos_byte = IT_BYTEPOS (*it);
2835 string = Qnil;
2836 }
2837
2838 /* If there's a valid composition and point is not inside of the
2839 composition (in the case that the composition is from the current
2840 buffer), draw a glyph composed from the composition components. */
2841 if (find_composition (pos, -1, &pos, &end, &prop, string)
2842 && COMPOSITION_VALID_P (pos, end, prop)
2843 && (STRINGP (it->string) || (PT <= pos || PT >= end)))
2844 {
2845 int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
2846
2847 if (id >= 0)
2848 {
2849 it->method = next_element_from_composition;
2850 it->cmp_id = id;
2851 it->cmp_len = COMPOSITION_LENGTH (prop);
2852 /* For a terminal, draw only the first character of the
2853 components. */
2854 it->c = COMPOSITION_GLYPH (composition_table[id], 0);
2855 it->len = (STRINGP (it->string)
2856 ? string_char_to_byte (it->string, end)
2857 : CHAR_TO_BYTE (end)) - pos_byte;
2858 it->stop_charpos = end;
2859 handled = HANDLED_RETURN;
2860 }
2861 }
2862
2863 return handled;
2864}
2865
2866
2867\f
5f5c8ee5
GM
2868/***********************************************************************
2869 Overlay strings
2870 ***********************************************************************/
2871
2872/* The following structure is used to record overlay strings for
2873 later sorting in load_overlay_strings. */
2874
2875struct overlay_entry
2876{
2970b9be 2877 Lisp_Object overlay;
5f5c8ee5
GM
2878 Lisp_Object string;
2879 int priority;
2880 int after_string_p;
2881};
2882
2883
2884/* Set up iterator IT from overlay strings at its current position.
2885 Called from handle_stop. */
2886
2887static enum prop_handled
2888handle_overlay_change (it)
2889 struct it *it;
2890{
2970b9be
GM
2891 if (!STRINGP (it->string) && get_overlay_strings (it))
2892 return HANDLED_RECOMPUTE_PROPS;
5f5c8ee5 2893 else
2970b9be 2894 return HANDLED_NORMALLY;
5f5c8ee5
GM
2895}
2896
2897
2898/* Set up the next overlay string for delivery by IT, if there is an
2899 overlay string to deliver. Called by set_iterator_to_next when the
2900 end of the current overlay string is reached. If there are more
2901 overlay strings to display, IT->string and
2902 IT->current.overlay_string_index are set appropriately here.
2903 Otherwise IT->string is set to nil. */
2904
2905static void
2906next_overlay_string (it)
2907 struct it *it;
2908{
2909 ++it->current.overlay_string_index;
2910 if (it->current.overlay_string_index == it->n_overlay_strings)
2911 {
2912 /* No more overlay strings. Restore IT's settings to what
2913 they were before overlay strings were processed, and
2914 continue to deliver from current_buffer. */
2915 pop_it (it);
2916 xassert (it->stop_charpos >= BEGV
2917 && it->stop_charpos <= it->end_charpos);
2918 it->string = Qnil;
2919 it->current.overlay_string_index = -1;
2920 SET_TEXT_POS (it->current.string_pos, -1, -1);
2921 it->n_overlay_strings = 0;
2922 it->method = next_element_from_buffer;
2970b9be
GM
2923
2924 /* If we're at the end of the buffer, record that we have
2925 processed the overlay strings there already, so that
2926 next_element_from_buffer doesn't try it again. */
2927 if (IT_CHARPOS (*it) >= it->end_charpos)
2928 it->overlay_strings_at_end_processed_p = 1;
5f5c8ee5
GM
2929 }
2930 else
2931 {
2932 /* There are more overlay strings to process. If
2933 IT->current.overlay_string_index has advanced to a position
2934 where we must load IT->overlay_strings with more strings, do
2935 it. */
2936 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2937
2938 if (it->current.overlay_string_index && i == 0)
2939 load_overlay_strings (it);
2940
2941 /* Initialize IT to deliver display elements from the overlay
2942 string. */
2943 it->string = it->overlay_strings[i];
2944 it->multibyte_p = STRING_MULTIBYTE (it->string);
2945 SET_TEXT_POS (it->current.string_pos, 0, 0);
2946 it->method = next_element_from_string;
2947 it->stop_charpos = 0;
2948 }
2949
2950 CHECK_IT (it);
2951}
2952
2953
2954/* Compare two overlay_entry structures E1 and E2. Used as a
2955 comparison function for qsort in load_overlay_strings. Overlay
2956 strings for the same position are sorted so that
2957
2970b9be
GM
2958 1. All after-strings come in front of before-strings, except
2959 when they come from the same overlay.
5f5c8ee5
GM
2960
2961 2. Within after-strings, strings are sorted so that overlay strings
2962 from overlays with higher priorities come first.
2963
2964 2. Within before-strings, strings are sorted so that overlay
2965 strings from overlays with higher priorities come last.
2966
2967 Value is analogous to strcmp. */
2968
2969
2970static int
2971compare_overlay_entries (e1, e2)
2972 void *e1, *e2;
2973{
2974 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
2975 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
2976 int result;
2977
2978 if (entry1->after_string_p != entry2->after_string_p)
2970b9be
GM
2979 {
2980 /* Let after-strings appear in front of before-strings if
2981 they come from different overlays. */
2982 if (EQ (entry1->overlay, entry2->overlay))
2983 result = entry1->after_string_p ? 1 : -1;
2984 else
2985 result = entry1->after_string_p ? -1 : 1;
2986 }
5f5c8ee5
GM
2987 else if (entry1->after_string_p)
2988 /* After-strings sorted in order of decreasing priority. */
2989 result = entry2->priority - entry1->priority;
2990 else
2991 /* Before-strings sorted in order of increasing priority. */
2992 result = entry1->priority - entry2->priority;
2993
2994 return result;
2995}
2996
2997
2998/* Load the vector IT->overlay_strings with overlay strings from IT's
2999 current buffer position. Set IT->n_overlays to the total number of
3000 overlay strings found.
3001
3002 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
3003 a time. On entry into load_overlay_strings,
3004 IT->current.overlay_string_index gives the number of overlay
3005 strings that have already been loaded by previous calls to this
3006 function.
3007
2970b9be
GM
3008 IT->add_overlay_start contains an additional overlay start
3009 position to consider for taking overlay strings from, if non-zero.
3010 This position comes into play when the overlay has an `invisible'
3011 property, and both before and after-strings. When we've skipped to
3012 the end of the overlay, because of its `invisible' property, we
3013 nevertheless want its before-string to appear.
3014 IT->add_overlay_start will contain the overlay start position
3015 in this case.
3016
5f5c8ee5
GM
3017 Overlay strings are sorted so that after-string strings come in
3018 front of before-string strings. Within before and after-strings,
3019 strings are sorted by overlay priority. See also function
3020 compare_overlay_entries. */
3021
3022static void
3023load_overlay_strings (it)
3024 struct it *it;
3025{
3026 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
cafafe0b 3027 Lisp_Object ov, overlay, window, str, invisible;
5f5c8ee5
GM
3028 int start, end;
3029 int size = 20;
cafafe0b 3030 int n = 0, i, j, invis_p;
5f5c8ee5
GM
3031 struct overlay_entry *entries
3032 = (struct overlay_entry *) alloca (size * sizeof *entries);
cafafe0b 3033 int charpos = IT_CHARPOS (*it);
5f5c8ee5
GM
3034
3035 /* Append the overlay string STRING of overlay OVERLAY to vector
3036 `entries' which has size `size' and currently contains `n'
3037 elements. AFTER_P non-zero means STRING is an after-string of
3038 OVERLAY. */
3039#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
3040 do \
3041 { \
3042 Lisp_Object priority; \
3043 \
3044 if (n == size) \
3045 { \
3046 int new_size = 2 * size; \
3047 struct overlay_entry *old = entries; \
3048 entries = \
3049 (struct overlay_entry *) alloca (new_size \
3050 * sizeof *entries); \
3051 bcopy (old, entries, size * sizeof *entries); \
3052 size = new_size; \
3053 } \
3054 \
3055 entries[n].string = (STRING); \
2970b9be 3056 entries[n].overlay = (OVERLAY); \
5f5c8ee5 3057 priority = Foverlay_get ((OVERLAY), Qpriority); \
2970b9be 3058 entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0; \
5f5c8ee5
GM
3059 entries[n].after_string_p = (AFTER_P); \
3060 ++n; \
3061 } \
3062 while (0)
3063
3064 /* Process overlay before the overlay center. */
2970b9be 3065 for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
5f5c8ee5 3066 {
9472f927 3067 overlay = XCAR (ov);
5f5c8ee5
GM
3068 xassert (OVERLAYP (overlay));
3069 start = OVERLAY_POSITION (OVERLAY_START (overlay));
3070 end = OVERLAY_POSITION (OVERLAY_END (overlay));
3071
cafafe0b 3072 if (end < charpos)
5f5c8ee5
GM
3073 break;
3074
3075 /* Skip this overlay if it doesn't start or end at IT's current
3076 position. */
cafafe0b 3077 if (end != charpos && start != charpos)
5f5c8ee5
GM
3078 continue;
3079
3080 /* Skip this overlay if it doesn't apply to IT->w. */
3081 window = Foverlay_get (overlay, Qwindow);
3082 if (WINDOWP (window) && XWINDOW (window) != it->w)
3083 continue;
3084
cafafe0b
GM
3085 /* If the text ``under'' the overlay is invisible, both before-
3086 and after-strings from this overlay are visible; start and
3087 end position are indistinguishable. */
3088 invisible = Foverlay_get (overlay, Qinvisible);
3089 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
3090
5f5c8ee5 3091 /* If overlay has a non-empty before-string, record it. */
cafafe0b 3092 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5
GM
3093 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
3094 && XSTRING (str)->size)
3095 RECORD_OVERLAY_STRING (overlay, str, 0);
3096
3097 /* If overlay has a non-empty after-string, record it. */
cafafe0b 3098 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5
GM
3099 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
3100 && XSTRING (str)->size)
3101 RECORD_OVERLAY_STRING (overlay, str, 1);
3102 }
3103
3104 /* Process overlays after the overlay center. */
2970b9be 3105 for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
5f5c8ee5 3106 {
9472f927 3107 overlay = XCAR (ov);
5f5c8ee5
GM
3108 xassert (OVERLAYP (overlay));
3109 start = OVERLAY_POSITION (OVERLAY_START (overlay));
3110 end = OVERLAY_POSITION (OVERLAY_END (overlay));
3111
cafafe0b 3112 if (start > charpos)
5f5c8ee5
GM
3113 break;
3114
3115 /* Skip this overlay if it doesn't start or end at IT's current
3116 position. */
cafafe0b 3117 if (end != charpos && start != charpos)
5f5c8ee5
GM
3118 continue;
3119
3120 /* Skip this overlay if it doesn't apply to IT->w. */
3121 window = Foverlay_get (overlay, Qwindow);
3122 if (WINDOWP (window) && XWINDOW (window) != it->w)
3123 continue;
3124
cafafe0b
GM
3125 /* If the text ``under'' the overlay is invisible, it has a zero
3126 dimension, and both before- and after-strings apply. */
3127 invisible = Foverlay_get (overlay, Qinvisible);
3128 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
3129
5f5c8ee5 3130 /* If overlay has a non-empty before-string, record it. */
cafafe0b 3131 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5
GM
3132 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
3133 && XSTRING (str)->size)
3134 RECORD_OVERLAY_STRING (overlay, str, 0);
3135
3136 /* If overlay has a non-empty after-string, record it. */
cafafe0b 3137 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5
GM
3138 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
3139 && XSTRING (str)->size)
3140 RECORD_OVERLAY_STRING (overlay, str, 1);
3141 }
3142
3143#undef RECORD_OVERLAY_STRING
3144
3145 /* Sort entries. */
cafafe0b 3146 if (n > 1)
2970b9be 3147 qsort (entries, n, sizeof *entries, compare_overlay_entries);
5f5c8ee5
GM
3148
3149 /* Record the total number of strings to process. */
3150 it->n_overlay_strings = n;
3151
3152 /* IT->current.overlay_string_index is the number of overlay strings
3153 that have already been consumed by IT. Copy some of the
3154 remaining overlay strings to IT->overlay_strings. */
3155 i = 0;
3156 j = it->current.overlay_string_index;
3157 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
3158 it->overlay_strings[i++] = entries[j++].string;
2970b9be 3159
5f5c8ee5
GM
3160 CHECK_IT (it);
3161}
3162
3163
3164/* Get the first chunk of overlay strings at IT's current buffer
3165 position. Value is non-zero if at least one overlay string was
3166 found. */
3167
3168static int
3169get_overlay_strings (it)
3170 struct it *it;
3171{
3172 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
3173 process. This fills IT->overlay_strings with strings, and sets
3174 IT->n_overlay_strings to the total number of strings to process.
3175 IT->pos.overlay_string_index has to be set temporarily to zero
3176 because load_overlay_strings needs this; it must be set to -1
3177 when no overlay strings are found because a zero value would
3178 indicate a position in the first overlay string. */
3179 it->current.overlay_string_index = 0;
3180 load_overlay_strings (it);
3181
3182 /* If we found overlay strings, set up IT to deliver display
3183 elements from the first one. Otherwise set up IT to deliver
3184 from current_buffer. */
3185 if (it->n_overlay_strings)
3186 {
3187 /* Make sure we know settings in current_buffer, so that we can
3188 restore meaningful values when we're done with the overlay
3189 strings. */
3190 compute_stop_pos (it);
3191 xassert (it->face_id >= 0);
3192
3193 /* Save IT's settings. They are restored after all overlay
3194 strings have been processed. */
3195 xassert (it->sp == 0);
3196 push_it (it);
3197
3198 /* Set up IT to deliver display elements from the first overlay
3199 string. */
3200 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
3201 it->stop_charpos = 0;
3202 it->string = it->overlay_strings[0];
3203 it->multibyte_p = STRING_MULTIBYTE (it->string);
3204 xassert (STRINGP (it->string));
3205 it->method = next_element_from_string;
3206 }
3207 else
3208 {
3209 it->string = Qnil;
3210 it->current.overlay_string_index = -1;
3211 it->method = next_element_from_buffer;
3212 }
3213
3214 CHECK_IT (it);
3215
3216 /* Value is non-zero if we found at least one overlay string. */
3217 return STRINGP (it->string);
3218}
3219
3220
3221\f
3222/***********************************************************************
3223 Saving and restoring state
3224 ***********************************************************************/
3225
3226/* Save current settings of IT on IT->stack. Called, for example,
3227 before setting up IT for an overlay string, to be able to restore
3228 IT's settings to what they were after the overlay string has been
3229 processed. */
3230
3231static void
3232push_it (it)
3233 struct it *it;
3234{
3235 struct iterator_stack_entry *p;
3236
3237 xassert (it->sp < 2);
3238 p = it->stack + it->sp;
3239
3240 p->stop_charpos = it->stop_charpos;
3241 xassert (it->face_id >= 0);
3242 p->face_id = it->face_id;
3243 p->string = it->string;
3244 p->pos = it->current;
3245 p->end_charpos = it->end_charpos;
3246 p->string_nchars = it->string_nchars;
3247 p->area = it->area;
3248 p->multibyte_p = it->multibyte_p;
3249 p->space_width = it->space_width;
3250 p->font_height = it->font_height;
3251 p->voffset = it->voffset;
3252 p->string_from_display_prop_p = it->string_from_display_prop_p;
3253 ++it->sp;
3254}
3255
3256
3257/* Restore IT's settings from IT->stack. Called, for example, when no
3258 more overlay strings must be processed, and we return to delivering
3259 display elements from a buffer, or when the end of a string from a
3260 `display' property is reached and we return to delivering display
3261 elements from an overlay string, or from a buffer. */
3262
3263static void
3264pop_it (it)
3265 struct it *it;
3266{
3267 struct iterator_stack_entry *p;
3268
3269 xassert (it->sp > 0);
3270 --it->sp;
3271 p = it->stack + it->sp;
3272 it->stop_charpos = p->stop_charpos;
3273 it->face_id = p->face_id;
3274 it->string = p->string;
3275 it->current = p->pos;
3276 it->end_charpos = p->end_charpos;
3277 it->string_nchars = p->string_nchars;
3278 it->area = p->area;
3279 it->multibyte_p = p->multibyte_p;
3280 it->space_width = p->space_width;
3281 it->font_height = p->font_height;
3282 it->voffset = p->voffset;
3283 it->string_from_display_prop_p = p->string_from_display_prop_p;
3284}
3285
3286
3287\f
3288/***********************************************************************
3289 Moving over lines
3290 ***********************************************************************/
3291
3292/* Set IT's current position to the previous line start. */
3293
3294static void
3295back_to_previous_line_start (it)
3296 struct it *it;
3297{
3298 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
3299 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3300}
3301
3302
cafafe0b
GM
3303/* Move IT to the next line start.
3304
3305 Value is non-zero if a newline was found. Set *SKIPPED_P to 1 if
3306 we skipped over part of the text (as opposed to moving the iterator
3307 continuously over the text). Otherwise, don't change the value
3308 of *SKIPPED_P.
3309
3310 Newlines may come from buffer text, overlay strings, or strings
3311 displayed via the `display' property. That's the reason we can't
3312 simply use find_next_newline_no_quit. */
5f5c8ee5 3313
cafafe0b
GM
3314static int
3315forward_to_next_line_start (it, skipped_p)
5f5c8ee5 3316 struct it *it;
cafafe0b 3317 int *skipped_p;
5f5c8ee5 3318{
54918e2b 3319 int old_selective, newline_found_p, n;
cafafe0b
GM
3320 const int MAX_NEWLINE_DISTANCE = 500;
3321
54918e2b
GM
3322 /* Don't handle selective display in the following. It's (a)
3323 unnecessary and (b) leads to an infinite recursion because
3324 next_element_from_ellipsis indirectly calls this function. */
3325 old_selective = it->selective;
3326 it->selective = 0;
3327
cafafe0b
GM
3328 /* Scan for a newline within MAX_NEWLINE_DISTANCE display elements
3329 from buffer text. */
3330 n = newline_found_p = 0;
3331 while (n < MAX_NEWLINE_DISTANCE
3332 && get_next_display_element (it)
3333 && !newline_found_p)
3334 {
3335 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
3336 set_iterator_to_next (it, 0);
3337 if (!STRINGP (it->string))
3338 ++n;
3339 }
3340
3341 /* If we didn't find a newline near enough, see if we can use a
3342 short-cut. */
3343 if (!newline_found_p && n == MAX_NEWLINE_DISTANCE)
3344 {
3345 int start = IT_CHARPOS (*it);
3346 int limit = find_next_newline_no_quit (start, 1);
3347 Lisp_Object pos;
3348
3349 xassert (!STRINGP (it->string));
3350
3351 /* If there isn't any `display' property in sight, and no
3352 overlays, we can just use the position of the newline in
3353 buffer text. */
3354 if (it->stop_charpos >= limit
3355 || ((pos = Fnext_single_property_change (make_number (start),
3356 Qdisplay,
3357 Qnil, make_number (limit)),
3358 NILP (pos))
3359 && next_overlay_change (start) == ZV))
3360 {
3361 IT_CHARPOS (*it) = limit;
3362 IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
3363 *skipped_p = newline_found_p = 1;
3364 }
3365 else
3366 {
3367 while (get_next_display_element (it)
3368 && !newline_found_p)
3369 {
3370 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
3371 set_iterator_to_next (it, 0);
3372 }
3373 }
3374 }
3375
54918e2b 3376 it->selective = old_selective;
cafafe0b 3377 return newline_found_p;
5f5c8ee5
GM
3378}
3379
3380
3381/* Set IT's current position to the previous visible line start. Skip
3382 invisible text that is so either due to text properties or due to
3383 selective display. Caution: this does not change IT->current_x and
3384 IT->hpos. */
3385
3386static void
3387back_to_previous_visible_line_start (it)
3388 struct it *it;
3389{
3390 int visible_p = 0;
3391
3392 /* Go back one newline if not on BEGV already. */
3393 if (IT_CHARPOS (*it) > BEGV)
3394 back_to_previous_line_start (it);
3395
3396 /* Move over lines that are invisible because of selective display
3397 or text properties. */
3398 while (IT_CHARPOS (*it) > BEGV
3399 && !visible_p)
3400 {
3401 visible_p = 1;
3402
3403 /* If selective > 0, then lines indented more than that values
3404 are invisible. */
3405 if (it->selective > 0
3406 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3407 it->selective))
3408 visible_p = 0;
5f5c8ee5
GM
3409 else
3410 {
3411 Lisp_Object prop;
3412
6fc556fd
KR
3413 prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
3414 Qinvisible, it->window);
5f5c8ee5
GM
3415 if (TEXT_PROP_MEANS_INVISIBLE (prop))
3416 visible_p = 0;
3417 }
5f5c8ee5
GM
3418
3419 /* Back one more newline if the current one is invisible. */
3420 if (!visible_p)
3421 back_to_previous_line_start (it);
3422 }
3423
3424 xassert (IT_CHARPOS (*it) >= BEGV);
3425 xassert (IT_CHARPOS (*it) == BEGV
3426 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3427 CHECK_IT (it);
3428}
3429
3430
3431/* Reseat iterator IT at the previous visible line start. Skip
3432 invisible text that is so either due to text properties or due to
3433 selective display. At the end, update IT's overlay information,
3434 face information etc. */
3435
3436static void
3437reseat_at_previous_visible_line_start (it)
3438 struct it *it;
3439{
3440 back_to_previous_visible_line_start (it);
3441 reseat (it, it->current.pos, 1);
3442 CHECK_IT (it);
3443}
3444
3445
3446/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
3447 buffer. ON_NEWLINE_P non-zero means position IT on the newline
3448 preceding the line start. Skip over invisible text that is so
3449 because of selective display. Compute faces, overlays etc at the
3450 new position. Note that this function does not skip over text that
3451 is invisible because of text properties. */
5f5c8ee5
GM
3452
3453static void
312246d1 3454reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 3455 struct it *it;
312246d1 3456 int on_newline_p;
5f5c8ee5 3457{
cafafe0b
GM
3458 int newline_found_p, skipped_p = 0;
3459
3460 newline_found_p = forward_to_next_line_start (it, &skipped_p);
3461
3462 /* Skip over lines that are invisible because they are indented
3463 more than the value of IT->selective. */
3464 if (it->selective > 0)
3465 while (IT_CHARPOS (*it) < ZV
3466 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3467 it->selective))
3468 newline_found_p = forward_to_next_line_start (it, &skipped_p);
3469
3470 /* Position on the newline if that's what's requested. */
3471 if (on_newline_p && newline_found_p)
5f5c8ee5 3472 {
cafafe0b 3473 if (STRINGP (it->string))
5f5c8ee5 3474 {
cafafe0b
GM
3475 if (IT_STRING_CHARPOS (*it) > 0)
3476 {
3477 --IT_STRING_CHARPOS (*it);
3478 --IT_STRING_BYTEPOS (*it);
3479 }
5f5c8ee5 3480 }
cafafe0b 3481 else if (IT_CHARPOS (*it) > BEGV)
312246d1
GM
3482 {
3483 --IT_CHARPOS (*it);
cafafe0b
GM
3484 --IT_BYTEPOS (*it);
3485 reseat (it, it->current.pos, 0);
312246d1 3486 }
5f5c8ee5 3487 }
cafafe0b
GM
3488 else if (skipped_p)
3489 reseat (it, it->current.pos, 0);
5f5c8ee5
GM
3490
3491 CHECK_IT (it);
3492}
3493
3494
3495\f
3496/***********************************************************************
3497 Changing an iterator's position
3498***********************************************************************/
3499
3500/* Change IT's current position to POS in current_buffer. If FORCE_P
3501 is non-zero, always check for text properties at the new position.
3502 Otherwise, text properties are only looked up if POS >=
3503 IT->check_charpos of a property. */
3504
3505static void
3506reseat (it, pos, force_p)
3507 struct it *it;
3508 struct text_pos pos;
3509 int force_p;
3510{
3511 int original_pos = IT_CHARPOS (*it);
3512
3513 reseat_1 (it, pos, 0);
3514
3515 /* Determine where to check text properties. Avoid doing it
3516 where possible because text property lookup is very expensive. */
3517 if (force_p
3518 || CHARPOS (pos) > it->stop_charpos
3519 || CHARPOS (pos) < original_pos)
3520 handle_stop (it);
3521
3522 CHECK_IT (it);
3523}
3524
3525
3526/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
3527 IT->stop_pos to POS, also. */
3528
3529static void
3530reseat_1 (it, pos, set_stop_p)
3531 struct it *it;
3532 struct text_pos pos;
3533 int set_stop_p;
3534{
3535 /* Don't call this function when scanning a C string. */
3536 xassert (it->s == NULL);
3537
3538 /* POS must be a reasonable value. */
3539 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
3540
3541 it->current.pos = it->position = pos;
3542 XSETBUFFER (it->object, current_buffer);
3543 it->dpvec = NULL;
3544 it->current.dpvec_index = -1;
3545 it->current.overlay_string_index = -1;
3546 IT_STRING_CHARPOS (*it) = -1;
3547 IT_STRING_BYTEPOS (*it) = -1;
3548 it->string = Qnil;
3549 it->method = next_element_from_buffer;
3550 it->sp = 0;
3551
3552 if (set_stop_p)
3553 it->stop_charpos = CHARPOS (pos);
3554}
3555
3556
3557/* Set up IT for displaying a string, starting at CHARPOS in window W.
3558 If S is non-null, it is a C string to iterate over. Otherwise,
3559 STRING gives a Lisp string to iterate over.
3560
3561 If PRECISION > 0, don't return more then PRECISION number of
3562 characters from the string.
3563
3564 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
3565 characters have been returned. FIELD_WIDTH < 0 means an infinite
3566 field width.
3567
3568 MULTIBYTE = 0 means disable processing of multibyte characters,
3569 MULTIBYTE > 0 means enable it,
3570 MULTIBYTE < 0 means use IT->multibyte_p.
3571
3572 IT must be initialized via a prior call to init_iterator before
3573 calling this function. */
3574
3575static void
3576reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
3577 struct it *it;
3578 unsigned char *s;
3579 Lisp_Object string;
3580 int charpos;
3581 int precision, field_width, multibyte;
3582{
3583 /* No region in strings. */
3584 it->region_beg_charpos = it->region_end_charpos = -1;
3585
3586 /* No text property checks performed by default, but see below. */
3587 it->stop_charpos = -1;
3588
3589 /* Set iterator position and end position. */
3590 bzero (&it->current, sizeof it->current);
3591 it->current.overlay_string_index = -1;
3592 it->current.dpvec_index = -1;
5f5c8ee5
GM
3593 xassert (charpos >= 0);
3594
3595 /* Use the setting of MULTIBYTE if specified. */
3596 if (multibyte >= 0)
3597 it->multibyte_p = multibyte > 0;
3598
3599 if (s == NULL)
3600 {
3601 xassert (STRINGP (string));
3602 it->string = string;
3603 it->s = NULL;
3604 it->end_charpos = it->string_nchars = XSTRING (string)->size;
3605 it->method = next_element_from_string;
3606 it->current.string_pos = string_pos (charpos, string);
3607 }
3608 else
3609 {
3610 it->s = s;
3611 it->string = Qnil;
3612
3613 /* Note that we use IT->current.pos, not it->current.string_pos,
3614 for displaying C strings. */
3615 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3616 if (it->multibyte_p)
3617 {
3618 it->current.pos = c_string_pos (charpos, s, 1);
3619 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
3620 }
3621 else
3622 {
3623 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
3624 it->end_charpos = it->string_nchars = strlen (s);
3625 }
3626
3627 it->method = next_element_from_c_string;
3628 }
3629
3630 /* PRECISION > 0 means don't return more than PRECISION characters
3631 from the string. */
3632 if (precision > 0 && it->end_charpos - charpos > precision)
3633 it->end_charpos = it->string_nchars = charpos + precision;
3634
3635 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
3636 characters have been returned. FIELD_WIDTH == 0 means don't pad,
3637 FIELD_WIDTH < 0 means infinite field width. This is useful for
3638 padding with `-' at the end of a mode line. */
3639 if (field_width < 0)
3640 field_width = INFINITY;
3641 if (field_width > it->end_charpos - charpos)
3642 it->end_charpos = charpos + field_width;
3643
3644 /* Use the standard display table for displaying strings. */
3645 if (DISP_TABLE_P (Vstandard_display_table))
3646 it->dp = XCHAR_TABLE (Vstandard_display_table);
3647
3648 it->stop_charpos = charpos;
3649 CHECK_IT (it);
3650}
3651
3652
3653\f
3654/***********************************************************************
3655 Iteration
3656 ***********************************************************************/
3657
3658/* Load IT's display element fields with information about the next
3659 display element from the current position of IT. Value is zero if
3660 end of buffer (or C string) is reached. */
3661
3662int
3663get_next_display_element (it)
3664 struct it *it;
3665{
3666 /* Non-zero means that we found an display element. Zero means that
3667 we hit the end of what we iterate over. Performance note: the
3668 function pointer `method' used here turns out to be faster than
3669 using a sequence of if-statements. */
3670 int success_p = (*it->method) (it);
5f5c8ee5
GM
3671
3672 if (it->what == IT_CHARACTER)
3673 {
3674 /* Map via display table or translate control characters.
3675 IT->c, IT->len etc. have been set to the next character by
3676 the function call above. If we have a display table, and it
3677 contains an entry for IT->c, translate it. Don't do this if
3678 IT->c itself comes from a display table, otherwise we could
3679 end up in an infinite recursion. (An alternative could be to
3680 count the recursion depth of this function and signal an
3681 error when a certain maximum depth is reached.) Is it worth
3682 it? */
3683 if (success_p && it->dpvec == NULL)
3684 {
3685 Lisp_Object dv;
3686
3687 if (it->dp
3688 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
3689 VECTORP (dv)))
3690 {
3691 struct Lisp_Vector *v = XVECTOR (dv);
3692
3693 /* Return the first character from the display table
3694 entry, if not empty. If empty, don't display the
3695 current character. */
3696 if (v->size)
3697 {
3698 it->dpvec_char_len = it->len;
3699 it->dpvec = v->contents;
3700 it->dpend = v->contents + v->size;
3701 it->current.dpvec_index = 0;
3702 it->method = next_element_from_display_vector;
3703 }
3704
3705 success_p = get_next_display_element (it);
3706 }
3707
3708 /* Translate control characters into `\003' or `^C' form.
3709 Control characters coming from a display table entry are
3710 currently not translated because we use IT->dpvec to hold
3711 the translation. This could easily be changed but I
197516c2
KH
3712 don't believe that it is worth doing.
3713
3714 Non-printable multibyte characters are also translated
3715 octal form. */
5f5c8ee5
GM
3716 else if ((it->c < ' '
3717 && (it->area != TEXT_AREA
c6e89d6c 3718 || (it->c != '\n' && it->c != '\t')))
54c85a23 3719 || (it->c >= 127
197516c2
KH
3720 && it->len == 1)
3721 || !CHAR_PRINTABLE_P (it->c))
5f5c8ee5
GM
3722 {
3723 /* IT->c is a control character which must be displayed
3724 either as '\003' or as `^C' where the '\\' and '^'
3725 can be defined in the display table. Fill
3726 IT->ctl_chars with glyphs for what we have to
3727 display. Then, set IT->dpvec to these glyphs. */
3728 GLYPH g;
3729
54c85a23 3730 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
3731 {
3732 /* Set IT->ctl_chars[0] to the glyph for `^'. */
3733 if (it->dp
3734 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
3735 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
3736 g = XINT (DISP_CTRL_GLYPH (it->dp));
3737 else
3738 g = FAST_MAKE_GLYPH ('^', 0);
3739 XSETINT (it->ctl_chars[0], g);
3740
3741 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
3742 XSETINT (it->ctl_chars[1], g);
3743
3744 /* Set up IT->dpvec and return first character from it. */
3745 it->dpvec_char_len = it->len;
3746 it->dpvec = it->ctl_chars;
3747 it->dpend = it->dpvec + 2;
3748 it->current.dpvec_index = 0;
3749 it->method = next_element_from_display_vector;
3750 get_next_display_element (it);
3751 }
3752 else
3753 {
260a86a0 3754 unsigned char str[MAX_MULTIBYTE_LENGTH];
c5924f47 3755 int len;
197516c2
KH
3756 int i;
3757 GLYPH escape_glyph;
3758
5f5c8ee5
GM
3759 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
3760 if (it->dp
3761 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
3762 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 3763 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 3764 else
197516c2
KH
3765 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
3766
c5924f47
KH
3767 if (SINGLE_BYTE_CHAR_P (it->c))
3768 str[0] = it->c, len = 1;
3769 else
3770 len = CHAR_STRING (it->c, str);
3771
197516c2
KH
3772 for (i = 0; i < len; i++)
3773 {
3774 XSETINT (it->ctl_chars[i * 4], escape_glyph);
3775 /* Insert three more glyphs into IT->ctl_chars for
3776 the octal display of the character. */
3777 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
3778 XSETINT (it->ctl_chars[i * 4 + 1], g);
3779 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
3780 XSETINT (it->ctl_chars[i * 4 + 2], g);
3781 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
3782 XSETINT (it->ctl_chars[i * 4 + 3], g);
3783 }
5f5c8ee5
GM
3784
3785 /* Set up IT->dpvec and return the first character
3786 from it. */
3787 it->dpvec_char_len = it->len;
3788 it->dpvec = it->ctl_chars;
197516c2 3789 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
3790 it->current.dpvec_index = 0;
3791 it->method = next_element_from_display_vector;
3792 get_next_display_element (it);
3793 }
3794 }
3795 }
3796
980806b6
KH
3797 /* Adjust face id for a multibyte character. There are no
3798 multibyte character in unibyte text. */
5f5c8ee5
GM
3799 if (it->multibyte_p
3800 && success_p
980806b6 3801 && FRAME_WINDOW_P (it->f))
5f5c8ee5 3802 {
980806b6
KH
3803 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3804 it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
5f5c8ee5
GM
3805 }
3806 }
3807
3808 /* Is this character the last one of a run of characters with
3809 box? If yes, set IT->end_of_box_run_p to 1. */
3810 if (it->face_box_p
3811 && it->s == NULL)
3812 {
3813 int face_id;
3814 struct face *face;
3815
3816 it->end_of_box_run_p
3817 = ((face_id = face_after_it_pos (it),
3818 face_id != it->face_id)
3819 && (face = FACE_FROM_ID (it->f, face_id),
3820 face->box == FACE_NO_BOX));
3821 }
3822
3823 /* Value is 0 if end of buffer or string reached. */
3824 return success_p;
3825}
3826
3827
3828/* Move IT to the next display element.
3829
cafafe0b
GM
3830 RESEAT_P non-zero means if called on a newline in buffer text,
3831 skip to the next visible line start.
3832
5f5c8ee5
GM
3833 Functions get_next_display_element and set_iterator_to_next are
3834 separate because I find this arrangement easier to handle than a
3835 get_next_display_element function that also increments IT's
3836 position. The way it is we can first look at an iterator's current
3837 display element, decide whether it fits on a line, and if it does,
3838 increment the iterator position. The other way around we probably
3839 would either need a flag indicating whether the iterator has to be
3840 incremented the next time, or we would have to implement a
3841 decrement position function which would not be easy to write. */
3842
3843void
cafafe0b 3844set_iterator_to_next (it, reseat_p)
5f5c8ee5 3845 struct it *it;
cafafe0b 3846 int reseat_p;
5f5c8ee5 3847{
483de32b
GM
3848 /* Reset flags indicating start and end of a sequence of characters
3849 with box. Reset them at the start of this function because
3850 moving the iterator to a new position might set them. */
3851 it->start_of_box_run_p = it->end_of_box_run_p = 0;
3852
5f5c8ee5
GM
3853 if (it->method == next_element_from_buffer)
3854 {
3855 /* The current display element of IT is a character from
3856 current_buffer. Advance in the buffer, and maybe skip over
3857 invisible lines that are so because of selective display. */
cafafe0b 3858 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
312246d1 3859 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
3860 else
3861 {
3862 xassert (it->len != 0);
3863 IT_BYTEPOS (*it) += it->len;
3864 IT_CHARPOS (*it) += 1;
3865 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
3866 }
3867 }
260a86a0
KH
3868 else if (it->method == next_element_from_composition)
3869 {
3870 xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
3871 if (STRINGP (it->string))
3872 {
3873 IT_STRING_BYTEPOS (*it) += it->len;
3874 IT_STRING_CHARPOS (*it) += it->cmp_len;
3875 it->method = next_element_from_string;
3876 goto consider_string_end;
3877 }
3878 else
3879 {
3880 IT_BYTEPOS (*it) += it->len;
3881 IT_CHARPOS (*it) += it->cmp_len;
3882 it->method = next_element_from_buffer;
3883 }
3884 }
5f5c8ee5
GM
3885 else if (it->method == next_element_from_c_string)
3886 {
3887 /* Current display element of IT is from a C string. */
3888 IT_BYTEPOS (*it) += it->len;
3889 IT_CHARPOS (*it) += 1;
3890 }
3891 else if (it->method == next_element_from_display_vector)
3892 {
3893 /* Current display element of IT is from a display table entry.
3894 Advance in the display table definition. Reset it to null if
3895 end reached, and continue with characters from buffers/
3896 strings. */
3897 ++it->current.dpvec_index;
286bcbc9 3898
980806b6
KH
3899 /* Restore face of the iterator to what they were before the
3900 display vector entry (these entries may contain faces). */
5f5c8ee5 3901 it->face_id = it->saved_face_id;
286bcbc9 3902
5f5c8ee5
GM
3903 if (it->dpvec + it->current.dpvec_index == it->dpend)
3904 {
3905 if (it->s)
3906 it->method = next_element_from_c_string;
3907 else if (STRINGP (it->string))
3908 it->method = next_element_from_string;
3909 else
3910 it->method = next_element_from_buffer;
3911
3912 it->dpvec = NULL;
3913 it->current.dpvec_index = -1;
3914
312246d1
GM
3915 /* Skip over characters which were displayed via IT->dpvec. */
3916 if (it->dpvec_char_len < 0)
3917 reseat_at_next_visible_line_start (it, 1);
3918 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
3919 {
3920 it->len = it->dpvec_char_len;
cafafe0b 3921 set_iterator_to_next (it, reseat_p);
5f5c8ee5
GM
3922 }
3923 }
3924 }
3925 else if (it->method == next_element_from_string)
3926 {
3927 /* Current display element is a character from a Lisp string. */
3928 xassert (it->s == NULL && STRINGP (it->string));
3929 IT_STRING_BYTEPOS (*it) += it->len;
3930 IT_STRING_CHARPOS (*it) += 1;
3931
3932 consider_string_end:
3933
3934 if (it->current.overlay_string_index >= 0)
3935 {
3936 /* IT->string is an overlay string. Advance to the
3937 next, if there is one. */
3938 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3939 next_overlay_string (it);
3940 }
3941 else
3942 {
3943 /* IT->string is not an overlay string. If we reached
3944 its end, and there is something on IT->stack, proceed
3945 with what is on the stack. This can be either another
3946 string, this time an overlay string, or a buffer. */
3947 if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size
3948 && it->sp > 0)
3949 {
3950 pop_it (it);
3951 if (!STRINGP (it->string))
3952 it->method = next_element_from_buffer;
3953 }
3954 }
3955 }
3956 else if (it->method == next_element_from_image
3957 || it->method == next_element_from_stretch)
3958 {
3959 /* The position etc with which we have to proceed are on
3960 the stack. The position may be at the end of a string,
3961 if the `display' property takes up the whole string. */
3962 pop_it (it);
3963 it->image_id = 0;
3964 if (STRINGP (it->string))
3965 {
3966 it->method = next_element_from_string;
3967 goto consider_string_end;
3968 }
3969 else
3970 it->method = next_element_from_buffer;
3971 }
3972 else
3973 /* There are no other methods defined, so this should be a bug. */
3974 abort ();
3975
5f5c8ee5
GM
3976 xassert (it->method != next_element_from_string
3977 || (STRINGP (it->string)
3978 && IT_STRING_CHARPOS (*it) >= 0));
3979}
3980
3981
3982/* Load IT's display element fields with information about the next
3983 display element which comes from a display table entry or from the
3984 result of translating a control character to one of the forms `^C'
3985 or `\003'. IT->dpvec holds the glyphs to return as characters. */
3986
3987static int
3988next_element_from_display_vector (it)
3989 struct it *it;
3990{
3991 /* Precondition. */
3992 xassert (it->dpvec && it->current.dpvec_index >= 0);
3993
3994 /* Remember the current face id in case glyphs specify faces.
3995 IT's face is restored in set_iterator_to_next. */
3996 it->saved_face_id = it->face_id;
3997
3998 if (INTEGERP (*it->dpvec)
3999 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
4000 {
4001 int lface_id;
4002 GLYPH g;
4003
4004 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
4005 it->c = FAST_GLYPH_CHAR (g);
c5924f47 4006 it->len = CHAR_BYTES (it->c);
5f5c8ee5
GM
4007
4008 /* The entry may contain a face id to use. Such a face id is
4009 the id of a Lisp face, not a realized face. A face id of
969065c3 4010 zero means no face is specified. */
5f5c8ee5
GM
4011 lface_id = FAST_GLYPH_FACE (g);
4012 if (lface_id)
4013 {
969065c3 4014 /* The function returns -1 if lface_id is invalid. */
5f5c8ee5
GM
4015 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
4016 if (face_id >= 0)
969065c3 4017 it->face_id = face_id;
5f5c8ee5
GM
4018 }
4019 }
4020 else
4021 /* Display table entry is invalid. Return a space. */
4022 it->c = ' ', it->len = 1;
4023
4024 /* Don't change position and object of the iterator here. They are
4025 still the values of the character that had this display table
4026 entry or was translated, and that's what we want. */
4027 it->what = IT_CHARACTER;
4028 return 1;
4029}
4030
4031
4032/* Load IT with the next display element from Lisp string IT->string.
4033 IT->current.string_pos is the current position within the string.
4034 If IT->current.overlay_string_index >= 0, the Lisp string is an
4035 overlay string. */
4036
4037static int
4038next_element_from_string (it)
4039 struct it *it;
4040{
4041 struct text_pos position;
4042
4043 xassert (STRINGP (it->string));
4044 xassert (IT_STRING_CHARPOS (*it) >= 0);
4045 position = it->current.string_pos;
4046
4047 /* Time to check for invisible text? */
4048 if (IT_STRING_CHARPOS (*it) < it->end_charpos
4049 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
4050 {
4051 handle_stop (it);
4052
4053 /* Since a handler may have changed IT->method, we must
4054 recurse here. */
4055 return get_next_display_element (it);
4056 }
4057
4058 if (it->current.overlay_string_index >= 0)
4059 {
4060 /* Get the next character from an overlay string. In overlay
4061 strings, There is no field width or padding with spaces to
4062 do. */
4063 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
4064 {
4065 it->what = IT_EOB;
4066 return 0;
4067 }
4068 else if (STRING_MULTIBYTE (it->string))
4069 {
4070 int remaining = (STRING_BYTES (XSTRING (it->string))
4071 - IT_STRING_BYTEPOS (*it));
4072 unsigned char *s = (XSTRING (it->string)->data
4073 + IT_STRING_BYTEPOS (*it));
4fdb80f2 4074 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
4075 }
4076 else
4077 {
4078 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
4079 it->len = 1;
4080 }
4081 }
4082 else
4083 {
4084 /* Get the next character from a Lisp string that is not an
4085 overlay string. Such strings come from the mode line, for
4086 example. We may have to pad with spaces, or truncate the
4087 string. See also next_element_from_c_string. */
4088 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
4089 {
4090 it->what = IT_EOB;
4091 return 0;
4092 }
4093 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
4094 {
4095 /* Pad with spaces. */
4096 it->c = ' ', it->len = 1;
4097 CHARPOS (position) = BYTEPOS (position) = -1;
4098 }
4099 else if (STRING_MULTIBYTE (it->string))
4100 {
4101 int maxlen = (STRING_BYTES (XSTRING (it->string))
4102 - IT_STRING_BYTEPOS (*it));
4103 unsigned char *s = (XSTRING (it->string)->data
4104 + IT_STRING_BYTEPOS (*it));
4fdb80f2 4105 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
4106 }
4107 else
4108 {
4109 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
4110 it->len = 1;
4111 }
4112 }
4113
4114 /* Record what we have and where it came from. Note that we store a
4115 buffer position in IT->position although it could arguably be a
4116 string position. */
4117 it->what = IT_CHARACTER;
4118 it->object = it->string;
4119 it->position = position;
4120 return 1;
4121}
4122
4123
4124/* Load IT with next display element from C string IT->s.
4125 IT->string_nchars is the maximum number of characters to return
4126 from the string. IT->end_charpos may be greater than
4127 IT->string_nchars when this function is called, in which case we
4128 may have to return padding spaces. Value is zero if end of string
4129 reached, including padding spaces. */
4130
4131static int
4132next_element_from_c_string (it)
4133 struct it *it;
4134{
4135 int success_p = 1;
4136
4137 xassert (it->s);
4138 it->what = IT_CHARACTER;
4139 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
4140 it->object = Qnil;
4141
4142 /* IT's position can be greater IT->string_nchars in case a field
4143 width or precision has been specified when the iterator was
4144 initialized. */
4145 if (IT_CHARPOS (*it) >= it->end_charpos)
4146 {
4147 /* End of the game. */
4148 it->what = IT_EOB;
4149 success_p = 0;
4150 }
4151 else if (IT_CHARPOS (*it) >= it->string_nchars)
4152 {
4153 /* Pad with spaces. */
4154 it->c = ' ', it->len = 1;
4155 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
4156 }
4157 else if (it->multibyte_p)
4158 {
4159 /* Implementation note: The calls to strlen apparently aren't a
4160 performance problem because there is no noticeable performance
4161 difference between Emacs running in unibyte or multibyte mode. */
4162 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
4163 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
4164 maxlen, &it->len);
5f5c8ee5
GM
4165 }
4166 else
4167 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
4168
4169 return success_p;
4170}
4171
4172
4173/* Set up IT to return characters from an ellipsis, if appropriate.
4174 The definition of the ellipsis glyphs may come from a display table
4175 entry. This function Fills IT with the first glyph from the
4176 ellipsis if an ellipsis is to be displayed. */
4177
13f19968 4178static int
5f5c8ee5
GM
4179next_element_from_ellipsis (it)
4180 struct it *it;
4181{
13f19968 4182 if (it->selective_display_ellipsis_p)
5f5c8ee5 4183 {
13f19968
GM
4184 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
4185 {
4186 /* Use the display table definition for `...'. Invalid glyphs
4187 will be handled by the method returning elements from dpvec. */
4188 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
4189 it->dpvec_char_len = it->len;
4190 it->dpvec = v->contents;
4191 it->dpend = v->contents + v->size;
4192 it->current.dpvec_index = 0;
4193 it->method = next_element_from_display_vector;
4194 }
4195 else
4196 {
4197 /* Use default `...' which is stored in default_invis_vector. */
4198 it->dpvec_char_len = it->len;
4199 it->dpvec = default_invis_vector;
4200 it->dpend = default_invis_vector + 3;
4201 it->current.dpvec_index = 0;
4202 it->method = next_element_from_display_vector;
4203 }
5f5c8ee5 4204 }
13f19968 4205 else
54918e2b
GM
4206 {
4207 it->method = next_element_from_buffer;
4208 reseat_at_next_visible_line_start (it, 1);
4209 }
13f19968
GM
4210
4211 return get_next_display_element (it);
5f5c8ee5
GM
4212}
4213
4214
4215/* Deliver an image display element. The iterator IT is already
4216 filled with image information (done in handle_display_prop). Value
4217 is always 1. */
4218
4219
4220static int
4221next_element_from_image (it)
4222 struct it *it;
4223{
4224 it->what = IT_IMAGE;
4225 return 1;
4226}
4227
4228
4229/* Fill iterator IT with next display element from a stretch glyph
4230 property. IT->object is the value of the text property. Value is
4231 always 1. */
4232
4233static int
4234next_element_from_stretch (it)
4235 struct it *it;
4236{
4237 it->what = IT_STRETCH;
4238 return 1;
4239}
4240
4241
4242/* Load IT with the next display element from current_buffer. Value
4243 is zero if end of buffer reached. IT->stop_charpos is the next
4244 position at which to stop and check for text properties or buffer
4245 end. */
4246
4247static int
4248next_element_from_buffer (it)
4249 struct it *it;
4250{
4251 int success_p = 1;
4252
4253 /* Check this assumption, otherwise, we would never enter the
4254 if-statement, below. */
4255 xassert (IT_CHARPOS (*it) >= BEGV
4256 && IT_CHARPOS (*it) <= it->stop_charpos);
4257
4258 if (IT_CHARPOS (*it) >= it->stop_charpos)
4259 {
4260 if (IT_CHARPOS (*it) >= it->end_charpos)
4261 {
4262 int overlay_strings_follow_p;
4263
4264 /* End of the game, except when overlay strings follow that
4265 haven't been returned yet. */
4266 if (it->overlay_strings_at_end_processed_p)
4267 overlay_strings_follow_p = 0;
4268 else
4269 {
4270 it->overlay_strings_at_end_processed_p = 1;
c880678e 4271 overlay_strings_follow_p = get_overlay_strings (it);
5f5c8ee5
GM
4272 }
4273
4274 if (overlay_strings_follow_p)
4275 success_p = get_next_display_element (it);
4276 else
4277 {
4278 it->what = IT_EOB;
4279 it->position = it->current.pos;
4280 success_p = 0;
4281 }
4282 }
4283 else
4284 {
4285 handle_stop (it);
4286 return get_next_display_element (it);
4287 }
4288 }
4289 else
4290 {
4291 /* No face changes, overlays etc. in sight, so just return a
4292 character from current_buffer. */
4293 unsigned char *p;
4294
4295 /* Maybe run the redisplay end trigger hook. Performance note:
4296 This doesn't seem to cost measurable time. */
4297 if (it->redisplay_end_trigger_charpos
4298 && it->glyph_row
4299 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
4300 run_redisplay_end_trigger_hook (it);
4301
4302 /* Get the next character, maybe multibyte. */
4303 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
260a86a0 4304 if (it->multibyte_p && !ASCII_BYTE_P (*p))
5f5c8ee5
GM
4305 {
4306 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
4307 - IT_BYTEPOS (*it));
4fdb80f2 4308 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
4309 }
4310 else
4311 it->c = *p, it->len = 1;
4312
4313 /* Record what we have and where it came from. */
4314 it->what = IT_CHARACTER;;
4315 it->object = it->w->buffer;
4316 it->position = it->current.pos;
4317
4318 /* Normally we return the character found above, except when we
4319 really want to return an ellipsis for selective display. */
4320 if (it->selective)
4321 {
4322 if (it->c == '\n')
4323 {
4324 /* A value of selective > 0 means hide lines indented more
4325 than that number of columns. */
4326 if (it->selective > 0
4327 && IT_CHARPOS (*it) + 1 < ZV
4328 && indented_beyond_p (IT_CHARPOS (*it) + 1,
4329 IT_BYTEPOS (*it) + 1,
4330 it->selective))
312246d1 4331 {
13f19968 4332 success_p = next_element_from_ellipsis (it);
312246d1
GM
4333 it->dpvec_char_len = -1;
4334 }
5f5c8ee5
GM
4335 }
4336 else if (it->c == '\r' && it->selective == -1)
4337 {
4338 /* A value of selective == -1 means that everything from the
4339 CR to the end of the line is invisible, with maybe an
4340 ellipsis displayed for it. */
13f19968 4341 success_p = next_element_from_ellipsis (it);
312246d1 4342 it->dpvec_char_len = -1;
5f5c8ee5
GM
4343 }
4344 }
4345 }
4346
4347 /* Value is zero if end of buffer reached. */
c880678e 4348 xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
5f5c8ee5
GM
4349 return success_p;
4350}
4351
4352
4353/* Run the redisplay end trigger hook for IT. */
4354
4355static void
4356run_redisplay_end_trigger_hook (it)
4357 struct it *it;
4358{
4359 Lisp_Object args[3];
4360
4361 /* IT->glyph_row should be non-null, i.e. we should be actually
4362 displaying something, or otherwise we should not run the hook. */
4363 xassert (it->glyph_row);
4364
4365 /* Set up hook arguments. */
4366 args[0] = Qredisplay_end_trigger_functions;
4367 args[1] = it->window;
4368 XSETINT (args[2], it->redisplay_end_trigger_charpos);
4369 it->redisplay_end_trigger_charpos = 0;
4370
4371 /* Since we are *trying* to run these functions, don't try to run
4372 them again, even if they get an error. */
4373 it->w->redisplay_end_trigger = Qnil;
4374 Frun_hook_with_args (3, args);
4375
4376 /* Notice if it changed the face of the character we are on. */
4377 handle_face_prop (it);
4378}
4379
4380
260a86a0
KH
4381/* Deliver a composition display element. The iterator IT is already
4382 filled with composition information (done in
4383 handle_composition_prop). Value is always 1. */
4384
4385static int
4386next_element_from_composition (it)
4387 struct it *it;
4388{
4389 it->what = IT_COMPOSITION;
4390 it->position = (STRINGP (it->string)
4391 ? it->current.string_pos
4392 : it->current.pos);
4393 return 1;
4394}
4395
4396
5f5c8ee5
GM
4397\f
4398/***********************************************************************
4399 Moving an iterator without producing glyphs
4400 ***********************************************************************/
4401
4402/* Move iterator IT to a specified buffer or X position within one
4403 line on the display without producing glyphs.
4404
4405 Begin to skip at IT's current position. Skip to TO_CHARPOS or TO_X
4406 whichever is reached first.
4407
4408 TO_CHARPOS <= 0 means no TO_CHARPOS is specified.
4409
4410 TO_X < 0 means that no TO_X is specified. TO_X is normally a value
4411 0 <= TO_X <= IT->last_visible_x. This means in particular, that
4412 TO_X includes the amount by which a window is horizontally
4413 scrolled.
4414
4415 Value is
4416
4417 MOVE_POS_MATCH_OR_ZV
4418 - when TO_POS or ZV was reached.
4419
4420 MOVE_X_REACHED
4421 -when TO_X was reached before TO_POS or ZV were reached.
4422
4423 MOVE_LINE_CONTINUED
4424 - when we reached the end of the display area and the line must
4425 be continued.
4426
4427 MOVE_LINE_TRUNCATED
4428 - when we reached the end of the display area and the line is
4429 truncated.
4430
4431 MOVE_NEWLINE_OR_CR
4432 - when we stopped at a line end, i.e. a newline or a CR and selective
4433 display is on. */
4434
701552dd 4435static enum move_it_result
5f5c8ee5
GM
4436move_it_in_display_line_to (it, to_charpos, to_x, op)
4437 struct it *it;
4438 int to_charpos, to_x, op;
4439{
4440 enum move_it_result result = MOVE_UNDEFINED;
4441 struct glyph_row *saved_glyph_row;
4442
4443 /* Don't produce glyphs in produce_glyphs. */
4444 saved_glyph_row = it->glyph_row;
4445 it->glyph_row = NULL;
4446
5f5c8ee5
GM
4447 while (1)
4448 {
ae26e27d 4449 int x, i, ascent = 0, descent = 0;
5f5c8ee5
GM
4450
4451 /* Stop when ZV or TO_CHARPOS reached. */
4452 if (!get_next_display_element (it)
4453 || ((op & MOVE_TO_POS) != 0
4454 && BUFFERP (it->object)
4455 && IT_CHARPOS (*it) >= to_charpos))
4456 {
4457 result = MOVE_POS_MATCH_OR_ZV;
4458 break;
4459 }
4460
4461 /* The call to produce_glyphs will get the metrics of the
4462 display element IT is loaded with. We record in x the
4463 x-position before this display element in case it does not
4464 fit on the line. */
4465 x = it->current_x;
47589c8c
GM
4466
4467 /* Remember the line height so far in case the next element doesn't
4468 fit on the line. */
4469 if (!it->truncate_lines_p)
4470 {
4471 ascent = it->max_ascent;
4472 descent = it->max_descent;
4473 }
4474
5f5c8ee5
GM
4475 PRODUCE_GLYPHS (it);
4476
4477 if (it->area != TEXT_AREA)
4478 {
cafafe0b 4479 set_iterator_to_next (it, 1);
5f5c8ee5
GM
4480 continue;
4481 }
4482
4483 /* The number of glyphs we get back in IT->nglyphs will normally
4484 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
4485 character on a terminal frame, or (iii) a line end. For the
4486 second case, IT->nglyphs - 1 padding glyphs will be present
4487 (on X frames, there is only one glyph produced for a
4488 composite character.
4489
4490 The behavior implemented below means, for continuation lines,
4491 that as many spaces of a TAB as fit on the current line are
4492 displayed there. For terminal frames, as many glyphs of a
4493 multi-glyph character are displayed in the current line, too.
4494 This is what the old redisplay code did, and we keep it that
4495 way. Under X, the whole shape of a complex character must
4496 fit on the line or it will be completely displayed in the
4497 next line.
4498
4499 Note that both for tabs and padding glyphs, all glyphs have
4500 the same width. */
4501 if (it->nglyphs)
4502 {
4503 /* More than one glyph or glyph doesn't fit on line. All
4504 glyphs have the same width. */
4505 int single_glyph_width = it->pixel_width / it->nglyphs;
4506 int new_x;
4507
4508 for (i = 0; i < it->nglyphs; ++i, x = new_x)
4509 {
4510 new_x = x + single_glyph_width;
4511
4512 /* We want to leave anything reaching TO_X to the caller. */
4513 if ((op & MOVE_TO_X) && new_x > to_x)
4514 {
4515 it->current_x = x;
4516 result = MOVE_X_REACHED;
4517 break;
4518 }
4519 else if (/* Lines are continued. */
4520 !it->truncate_lines_p
4521 && (/* And glyph doesn't fit on the line. */
4522 new_x > it->last_visible_x
4523 /* Or it fits exactly and we're on a window
4524 system frame. */
4525 || (new_x == it->last_visible_x
4526 && FRAME_WINDOW_P (it->f))))
4527 {
4528 if (/* IT->hpos == 0 means the very first glyph
4529 doesn't fit on the line, e.g. a wide image. */
4530 it->hpos == 0
4531 || (new_x == it->last_visible_x
4532 && FRAME_WINDOW_P (it->f)))
4533 {
4534 ++it->hpos;
4535 it->current_x = new_x;
4536 if (i == it->nglyphs - 1)
cafafe0b 4537 set_iterator_to_next (it, 1);
5f5c8ee5
GM
4538 }
4539 else
47589c8c
GM
4540 {
4541 it->current_x = x;
4542 it->max_ascent = ascent;
4543 it->max_descent = descent;
4544 }
4545
4546 TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
4547 IT_CHARPOS (*it)));
5f5c8ee5
GM
4548 result = MOVE_LINE_CONTINUED;
4549 break;
4550 }
4551 else if (new_x > it->first_visible_x)
4552 {
4553 /* Glyph is visible. Increment number of glyphs that
4554 would be displayed. */
4555 ++it->hpos;
4556 }
4557 else
4558 {
4559 /* Glyph is completely off the left margin of the display
4560 area. Nothing to do. */
4561 }
4562 }
4563
4564 if (result != MOVE_UNDEFINED)
4565 break;
4566 }
4567 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
4568 {
4569 /* Stop when TO_X specified and reached. This check is
4570 necessary here because of lines consisting of a line end,
4571 only. The line end will not produce any glyphs and we
4572 would never get MOVE_X_REACHED. */
4573 xassert (it->nglyphs == 0);
4574 result = MOVE_X_REACHED;
4575 break;
4576 }
4577
4578 /* Is this a line end? If yes, we're done. */
4579 if (ITERATOR_AT_END_OF_LINE_P (it))
4580 {
4581 result = MOVE_NEWLINE_OR_CR;
4582 break;
4583 }
4584
4585 /* The current display element has been consumed. Advance
4586 to the next. */
cafafe0b 4587 set_iterator_to_next (it, 1);
5f5c8ee5
GM
4588
4589 /* Stop if lines are truncated and IT's current x-position is
4590 past the right edge of the window now. */
4591 if (it->truncate_lines_p
4592 && it->current_x >= it->last_visible_x)
4593 {
4594 result = MOVE_LINE_TRUNCATED;
4595 break;
4596 }
4597 }
4598
4599 /* Restore the iterator settings altered at the beginning of this
4600 function. */
4601 it->glyph_row = saved_glyph_row;
4602 return result;
4603}
4604
4605
4606/* Move IT forward to a specified buffer position TO_CHARPOS, TO_X,
4607 TO_Y, TO_VPOS. OP is a bit-mask that specifies where to stop. See
4608 the description of enum move_operation_enum.
4609
4610 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
4611 screen line, this function will set IT to the next position >
4612 TO_CHARPOS. */
4613
4614void
4615move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
4616 struct it *it;
4617 int to_charpos, to_x, to_y, to_vpos;
4618 int op;
4619{
4620 enum move_it_result skip, skip2 = MOVE_X_REACHED;
4621 int line_height;
47589c8c 4622 int reached = 0;
5f5c8ee5 4623
47589c8c 4624 for (;;)
5f5c8ee5
GM
4625 {
4626 if (op & MOVE_TO_VPOS)
4627 {
4628 /* If no TO_CHARPOS and no TO_X specified, stop at the
4629 start of the line TO_VPOS. */
4630 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
4631 {
4632 if (it->vpos == to_vpos)
47589c8c
GM
4633 {
4634 reached = 1;
4635 break;
4636 }
4637 else
4638 skip = move_it_in_display_line_to (it, -1, -1, 0);
5f5c8ee5
GM
4639 }
4640 else
4641 {
4642 /* TO_VPOS >= 0 means stop at TO_X in the line at
4643 TO_VPOS, or at TO_POS, whichever comes first. */
47589c8c
GM
4644 if (it->vpos == to_vpos)
4645 {
4646 reached = 2;
4647 break;
4648 }
4649
5f5c8ee5
GM
4650 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
4651
4652 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
47589c8c
GM
4653 {
4654 reached = 3;
4655 break;
4656 }
5f5c8ee5
GM
4657 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
4658 {
4659 /* We have reached TO_X but not in the line we want. */
4660 skip = move_it_in_display_line_to (it, to_charpos,
4661 -1, MOVE_TO_POS);
4662 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
4663 {
4664 reached = 4;
4665 break;
4666 }
5f5c8ee5
GM
4667 }
4668 }
4669 }
4670 else if (op & MOVE_TO_Y)
4671 {
4672 struct it it_backup;
5f5c8ee5
GM
4673
4674 /* TO_Y specified means stop at TO_X in the line containing
4675 TO_Y---or at TO_CHARPOS if this is reached first. The
4676 problem is that we can't really tell whether the line
4677 contains TO_Y before we have completely scanned it, and
4678 this may skip past TO_X. What we do is to first scan to
4679 TO_X.
4680
4681 If TO_X is not specified, use a TO_X of zero. The reason
4682 is to make the outcome of this function more predictable.
4683 If we didn't use TO_X == 0, we would stop at the end of
4684 the line which is probably not what a caller would expect
4685 to happen. */
4686 skip = move_it_in_display_line_to (it, to_charpos,
4687 ((op & MOVE_TO_X)
4688 ? to_x : 0),
4689 (MOVE_TO_X
4690 | (op & MOVE_TO_POS)));
4691
4692 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
4693 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
4694 {
4695 reached = 5;
4696 break;
4697 }
5f5c8ee5
GM
4698
4699 /* If TO_X was reached, we would like to know whether TO_Y
4700 is in the line. This can only be said if we know the
4701 total line height which requires us to scan the rest of
4702 the line. */
5f5c8ee5
GM
4703 if (skip == MOVE_X_REACHED)
4704 {
4705 it_backup = *it;
47589c8c 4706 TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
4707 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
4708 op & MOVE_TO_POS);
47589c8c 4709 TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
4710 }
4711
4712 /* Now, decide whether TO_Y is in this line. */
4713 line_height = it->max_ascent + it->max_descent;
47589c8c 4714 TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
5f5c8ee5
GM
4715
4716 if (to_y >= it->current_y
4717 && to_y < it->current_y + line_height)
4718 {
4719 if (skip == MOVE_X_REACHED)
4720 /* If TO_Y is in this line and TO_X was reached above,
4721 we scanned too far. We have to restore IT's settings
4722 to the ones before skipping. */
4723 *it = it_backup;
47589c8c 4724 reached = 6;
5f5c8ee5
GM
4725 }
4726 else if (skip == MOVE_X_REACHED)
4727 {
4728 skip = skip2;
4729 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c 4730 reached = 7;
5f5c8ee5
GM
4731 }
4732
47589c8c 4733 if (reached)
5f5c8ee5
GM
4734 break;
4735 }
4736 else
4737 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
4738
4739 switch (skip)
4740 {
4741 case MOVE_POS_MATCH_OR_ZV:
47589c8c
GM
4742 reached = 8;
4743 goto out;
5f5c8ee5
GM
4744
4745 case MOVE_NEWLINE_OR_CR:
cafafe0b 4746 set_iterator_to_next (it, 1);
5f5c8ee5
GM
4747 it->continuation_lines_width = 0;
4748 break;
4749
4750 case MOVE_LINE_TRUNCATED:
4751 it->continuation_lines_width = 0;
312246d1 4752 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4753 if ((op & MOVE_TO_POS) != 0
4754 && IT_CHARPOS (*it) > to_charpos)
47589c8c
GM
4755 {
4756 reached = 9;
4757 goto out;
4758 }
5f5c8ee5
GM
4759 break;
4760
4761 case MOVE_LINE_CONTINUED:
4762 it->continuation_lines_width += it->current_x;
4763 break;
4764
4765 default:
4766 abort ();
4767 }
4768
4769 /* Reset/increment for the next run. */
4770 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
4771 it->current_x = it->hpos = 0;
4772 it->current_y += it->max_ascent + it->max_descent;
4773 ++it->vpos;
4774 last_height = it->max_ascent + it->max_descent;
4775 last_max_ascent = it->max_ascent;
4776 it->max_ascent = it->max_descent = 0;
4777 }
47589c8c
GM
4778
4779 out:
4780
4781 TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
5f5c8ee5
GM
4782}
4783
4784
4785/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
4786
4787 If DY > 0, move IT backward at least that many pixels. DY = 0
4788 means move IT backward to the preceding line start or BEGV. This
4789 function may move over more than DY pixels if IT->current_y - DY
4790 ends up in the middle of a line; in this case IT->current_y will be
4791 set to the top of the line moved to. */
4792
4793void
4794move_it_vertically_backward (it, dy)
4795 struct it *it;
4796 int dy;
4797{
4798 int nlines, h, line_height;
4799 struct it it2;
4800 int start_pos = IT_CHARPOS (*it);
4801
4802 xassert (dy >= 0);
4803
4804 /* Estimate how many newlines we must move back. */
4805 nlines = max (1, dy / CANON_Y_UNIT (it->f));
4806
4807 /* Set the iterator's position that many lines back. */
4808 while (nlines-- && IT_CHARPOS (*it) > BEGV)
4809 back_to_previous_visible_line_start (it);
4810
4811 /* Reseat the iterator here. When moving backward, we don't want
4812 reseat to skip forward over invisible text, set up the iterator
4813 to deliver from overlay strings at the new position etc. So,
4814 use reseat_1 here. */
4815 reseat_1 (it, it->current.pos, 1);
4816
4817 /* We are now surely at a line start. */
4818 it->current_x = it->hpos = 0;
4819
4820 /* Move forward and see what y-distance we moved. First move to the
4821 start of the next line so that we get its height. We need this
4822 height to be able to tell whether we reached the specified
4823 y-distance. */
4824 it2 = *it;
4825 it2.max_ascent = it2.max_descent = 0;
4826 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
4827 MOVE_TO_POS | MOVE_TO_VPOS);
4828 xassert (IT_CHARPOS (*it) >= BEGV);
4829 line_height = it2.max_ascent + it2.max_descent;
47589c8c 4830
5f5c8ee5
GM
4831 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
4832 xassert (IT_CHARPOS (*it) >= BEGV);
4833 h = it2.current_y - it->current_y;
4834 nlines = it2.vpos - it->vpos;
4835
4836 /* Correct IT's y and vpos position. */
4837 it->vpos -= nlines;
4838 it->current_y -= h;
4839
4840 if (dy == 0)
4841 {
4842 /* DY == 0 means move to the start of the screen line. The
4843 value of nlines is > 0 if continuation lines were involved. */
4844 if (nlines > 0)
4845 move_it_by_lines (it, nlines, 1);
4846 xassert (IT_CHARPOS (*it) <= start_pos);
4847 }
4848 else if (nlines)
4849 {
4850 /* The y-position we try to reach. Note that h has been
4851 subtracted in front of the if-statement. */
4852 int target_y = it->current_y + h - dy;
4853
4854 /* If we did not reach target_y, try to move further backward if
4855 we can. If we moved too far backward, try to move forward. */
4856 if (target_y < it->current_y
4857 && IT_CHARPOS (*it) > BEGV)
4858 {
4859 move_it_vertically (it, target_y - it->current_y);
4860 xassert (IT_CHARPOS (*it) >= BEGV);
4861 }
4862 else if (target_y >= it->current_y + line_height
4863 && IT_CHARPOS (*it) < ZV)
4864 {
4865 move_it_vertically (it, target_y - (it->current_y + line_height));
4866 xassert (IT_CHARPOS (*it) >= BEGV);
4867 }
4868 }
4869}
4870
4871
4872/* Move IT by a specified amount of pixel lines DY. DY negative means
4873 move backwards. DY = 0 means move to start of screen line. At the
4874 end, IT will be on the start of a screen line. */
4875
4876void
4877move_it_vertically (it, dy)
4878 struct it *it;
4879 int dy;
4880{
4881 if (dy <= 0)
4882 move_it_vertically_backward (it, -dy);
4883 else if (dy > 0)
4884 {
47589c8c 4885 TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
5f5c8ee5
GM
4886 move_it_to (it, ZV, -1, it->current_y + dy, -1,
4887 MOVE_TO_POS | MOVE_TO_Y);
47589c8c 4888 TRACE_MOVE ((stderr, "move_it_v: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
4889
4890 /* If buffer ends in ZV without a newline, move to the start of
4891 the line to satisfy the post-condition. */
4892 if (IT_CHARPOS (*it) == ZV
4893 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
4894 move_it_by_lines (it, 0, 0);
4895 }
4896}
4897
4898
4899/* Return non-zero if some text between buffer positions START_CHARPOS
4900 and END_CHARPOS is invisible. IT->window is the window for text
4901 property lookup. */
4902
4903static int
4904invisible_text_between_p (it, start_charpos, end_charpos)
4905 struct it *it;
4906 int start_charpos, end_charpos;
4907{
5f5c8ee5
GM
4908 Lisp_Object prop, limit;
4909 int invisible_found_p;
4910
4911 xassert (it != NULL && start_charpos <= end_charpos);
4912
4913 /* Is text at START invisible? */
4914 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
4915 it->window);
4916 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4917 invisible_found_p = 1;
4918 else
4919 {
016b5642
MB
4920 limit = Fnext_single_char_property_change (make_number (start_charpos),
4921 Qinvisible, Qnil,
4922 make_number (end_charpos));
5f5c8ee5
GM
4923 invisible_found_p = XFASTINT (limit) < end_charpos;
4924 }
4925
4926 return invisible_found_p;
5f5c8ee5
GM
4927}
4928
4929
4930/* Move IT by a specified number DVPOS of screen lines down. DVPOS
4931 negative means move up. DVPOS == 0 means move to the start of the
4932 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
4933 NEED_Y_P is zero, IT->current_y will be left unchanged.
4934
4935 Further optimization ideas: If we would know that IT->f doesn't use
4936 a face with proportional font, we could be faster for
4937 truncate-lines nil. */
4938
4939void
4940move_it_by_lines (it, dvpos, need_y_p)
4941 struct it *it;
4942 int dvpos, need_y_p;
4943{
4944 struct position pos;
4945
4946 if (!FRAME_WINDOW_P (it->f))
4947 {
4948 struct text_pos textpos;
4949
4950 /* We can use vmotion on frames without proportional fonts. */
4951 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
4952 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
4953 reseat (it, textpos, 1);
4954 it->vpos += pos.vpos;
4955 it->current_y += pos.vpos;
4956 }
4957 else if (dvpos == 0)
4958 {
4959 /* DVPOS == 0 means move to the start of the screen line. */
4960 move_it_vertically_backward (it, 0);
4961 xassert (it->current_x == 0 && it->hpos == 0);
4962 }
4963 else if (dvpos > 0)
4964 {
4965 /* If there are no continuation lines, and if there is no
4966 selective display, try the simple method of moving forward
4967 DVPOS newlines, then see where we are. */
4968 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4969 {
4970 int shortage = 0, charpos;
4971
4972 if (FETCH_BYTE (IT_BYTEPOS (*it) == '\n'))
4973 charpos = IT_CHARPOS (*it) + 1;
4974 else
4975 charpos = scan_buffer ('\n', IT_CHARPOS (*it), 0, dvpos,
4976 &shortage, 0);
4977
4978 if (!invisible_text_between_p (it, IT_CHARPOS (*it), charpos))
4979 {
4980 struct text_pos pos;
4981 CHARPOS (pos) = charpos;
4982 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4983 reseat (it, pos, 1);
4984 it->vpos += dvpos - shortage;
4985 it->hpos = it->current_x = 0;
4986 return;
4987 }
4988 }
4989
4990 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
4991 }
4992 else
4993 {
4994 struct it it2;
4995 int start_charpos, i;
4996
4997 /* If there are no continuation lines, and if there is no
4998 selective display, try the simple method of moving backward
4999 -DVPOS newlines. */
5000 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
5001 {
5002 int shortage;
5003 int charpos = IT_CHARPOS (*it);
5004 int bytepos = IT_BYTEPOS (*it);
5005
5006 /* If in the middle of a line, go to its start. */
5007 if (charpos > BEGV && FETCH_BYTE (bytepos - 1) != '\n')
5008 {
5009 charpos = find_next_newline_no_quit (charpos, -1);
5010 bytepos = CHAR_TO_BYTE (charpos);
5011 }
5012
5013 if (charpos == BEGV)
5014 {
5015 struct text_pos pos;
5016 CHARPOS (pos) = charpos;
5017 BYTEPOS (pos) = bytepos;
5018 reseat (it, pos, 1);
5019 it->hpos = it->current_x = 0;
5020 return;
5021 }
5022 else
5023 {
5024 charpos = scan_buffer ('\n', charpos - 1, 0, dvpos, &shortage, 0);
5025 if (!invisible_text_between_p (it, charpos, IT_CHARPOS (*it)))
5026 {
5027 struct text_pos pos;
5028 CHARPOS (pos) = charpos;
5029 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
5030 reseat (it, pos, 1);
5031 it->vpos += dvpos + (shortage ? shortage - 1 : 0);
5032 it->hpos = it->current_x = 0;
5033 return;
5034 }
5035 }
5036 }
5037
5038 /* Go back -DVPOS visible lines and reseat the iterator there. */
5039 start_charpos = IT_CHARPOS (*it);
5040 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
5041 back_to_previous_visible_line_start (it);
5042 reseat (it, it->current.pos, 1);
5043 it->current_x = it->hpos = 0;
5044
5045 /* Above call may have moved too far if continuation lines
5046 are involved. Scan forward and see if it did. */
5047 it2 = *it;
5048 it2.vpos = it2.current_y = 0;
5049 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
5050 it->vpos -= it2.vpos;
5051 it->current_y -= it2.current_y;
5052 it->current_x = it->hpos = 0;
5053
5054 /* If we moved too far, move IT some lines forward. */
5055 if (it2.vpos > -dvpos)
5056 {
5057 int delta = it2.vpos + dvpos;
5058 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
5059 }
5060 }
5061}
5062
5063
5064\f
5065/***********************************************************************
5066 Messages
5067 ***********************************************************************/
5068
5069
937248bc
GM
5070/* Add a message with format string FORMAT and arguments ARG1 and ARG2
5071 to *Messages*. */
5072
5073void
5074add_to_log (format, arg1, arg2)
5075 char *format;
5076 Lisp_Object arg1, arg2;
5077{
5078 Lisp_Object args[3];
5079 Lisp_Object msg, fmt;
5080 char *buffer;
5081 int len;
5082 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5083
5084 fmt = msg = Qnil;
5085 GCPRO4 (fmt, msg, arg1, arg2);
5086
5087 args[0] = fmt = build_string (format);
5088 args[1] = arg1;
5089 args[2] = arg2;
6fc556fd 5090 msg = Fformat (3, args);
937248bc
GM
5091
5092 len = STRING_BYTES (XSTRING (msg)) + 1;
5093 buffer = (char *) alloca (len);
5094 strcpy (buffer, XSTRING (msg)->data);
5095
796184bc 5096 message_dolog (buffer, len - 1, 1, 0);
937248bc
GM
5097 UNGCPRO;
5098}
5099
5100
5f5c8ee5
GM
5101/* Output a newline in the *Messages* buffer if "needs" one. */
5102
5103void
5104message_log_maybe_newline ()
5105{
5106 if (message_log_need_newline)
5107 message_dolog ("", 0, 1, 0);
5108}
5109
5110
5111/* Add a string M of length LEN to the message log, optionally
5112 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
5113 nonzero, means interpret the contents of M as multibyte. This
5114 function calls low-level routines in order to bypass text property
5115 hooks, etc. which might not be safe to run. */
5116
5117void
5118message_dolog (m, len, nlflag, multibyte)
5119 char *m;
5120 int len, nlflag, multibyte;
5121{
5122 if (!NILP (Vmessage_log_max))
5123 {
5124 struct buffer *oldbuf;
5125 Lisp_Object oldpoint, oldbegv, oldzv;
5126 int old_windows_or_buffers_changed = windows_or_buffers_changed;
5127 int point_at_end = 0;
5128 int zv_at_end = 0;
5129 Lisp_Object old_deactivate_mark, tem;
5130 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5131
5132 old_deactivate_mark = Vdeactivate_mark;
5133 oldbuf = current_buffer;
6a94510a 5134 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
5f5c8ee5
GM
5135 current_buffer->undo_list = Qt;
5136
5137 oldpoint = Fpoint_marker ();
5138 oldbegv = Fpoint_min_marker ();
5139 oldzv = Fpoint_max_marker ();
5140 GCPRO4 (oldpoint, oldbegv, oldzv, old_deactivate_mark);
5141
5142 if (PT == Z)
5143 point_at_end = 1;
5144 if (ZV == Z)
5145 zv_at_end = 1;
5146
5147 BEGV = BEG;
5148 BEGV_BYTE = BEG_BYTE;
5149 ZV = Z;
5150 ZV_BYTE = Z_BYTE;
5151 TEMP_SET_PT_BOTH (Z, Z_BYTE);
5152
5153 /* Insert the string--maybe converting multibyte to single byte
5154 or vice versa, so that all the text fits the buffer. */
5155 if (multibyte
5156 && NILP (current_buffer->enable_multibyte_characters))
5157 {
5158 int i, c, nbytes;
5159 unsigned char work[1];
5160
5161 /* Convert a multibyte string to single-byte
5162 for the *Message* buffer. */
5163 for (i = 0; i < len; i += nbytes)
5164 {
4fdb80f2 5165 c = string_char_and_length (m + i, len - i, &nbytes);
5f5c8ee5
GM
5166 work[0] = (SINGLE_BYTE_CHAR_P (c)
5167 ? c
5168 : multibyte_char_to_unibyte (c, Qnil));
5169 insert_1_both (work, 1, 1, 1, 0, 0);
5170 }
5171 }
5172 else if (! multibyte
5173 && ! NILP (current_buffer->enable_multibyte_characters))
5174 {
5175 int i, c, nbytes;
5176 unsigned char *msg = (unsigned char *) m;
260a86a0 5177 unsigned char str[MAX_MULTIBYTE_LENGTH];
5f5c8ee5
GM
5178 /* Convert a single-byte string to multibyte
5179 for the *Message* buffer. */
5180 for (i = 0; i < len; i++)
5181 {
5182 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
5183 nbytes = CHAR_STRING (c, str);
5184 insert_1_both (str, 1, nbytes, 1, 0, 0);
5f5c8ee5
GM
5185 }
5186 }
5187 else if (len)
5188 insert_1 (m, len, 1, 0, 0);
5189
5190 if (nlflag)
5191 {
5192 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
5193 insert_1 ("\n", 1, 1, 0, 0);
5194
5195 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
5196 this_bol = PT;
5197 this_bol_byte = PT_BYTE;
5198
5199 if (this_bol > BEG)
5200 {
5201 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
5202 prev_bol = PT;
5203 prev_bol_byte = PT_BYTE;
5204
5205 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
5206 this_bol, this_bol_byte);
5207 if (dup)
5208 {
5209 del_range_both (prev_bol, prev_bol_byte,
5210 this_bol, this_bol_byte, 0);
5211 if (dup > 1)
5212 {
5213 char dupstr[40];
5214 int duplen;
5215
5216 /* If you change this format, don't forget to also
5217 change message_log_check_duplicate. */
5218 sprintf (dupstr, " [%d times]", dup);
5219 duplen = strlen (dupstr);
5220 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
5221 insert_1 (dupstr, duplen, 1, 0, 1);
5222 }
5223 }
5224 }
5225
5226 if (NATNUMP (Vmessage_log_max))
5227 {
5228 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
5229 -XFASTINT (Vmessage_log_max) - 1, 0);
5230 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
5231 }
5232 }
5233 BEGV = XMARKER (oldbegv)->charpos;
5234 BEGV_BYTE = marker_byte_position (oldbegv);
5235
5236 if (zv_at_end)
5237 {
5238 ZV = Z;
5239 ZV_BYTE = Z_BYTE;
5240 }
5241 else
5242 {
5243 ZV = XMARKER (oldzv)->charpos;
5244 ZV_BYTE = marker_byte_position (oldzv);
5245 }
5246
5247 if (point_at_end)
5248 TEMP_SET_PT_BOTH (Z, Z_BYTE);
5249 else
5250 /* We can't do Fgoto_char (oldpoint) because it will run some
5251 Lisp code. */
5252 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
5253 XMARKER (oldpoint)->bytepos);
5254
5255 UNGCPRO;
5256 free_marker (oldpoint);
5257 free_marker (oldbegv);
5258 free_marker (oldzv);
5259
5260 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
5261 set_buffer_internal (oldbuf);
5262 if (NILP (tem))
5263 windows_or_buffers_changed = old_windows_or_buffers_changed;
5264 message_log_need_newline = !nlflag;
5265 Vdeactivate_mark = old_deactivate_mark;
5266 }
5267}
5268
5269
5270/* We are at the end of the buffer after just having inserted a newline.
5271 (Note: We depend on the fact we won't be crossing the gap.)
5272 Check to see if the most recent message looks a lot like the previous one.
5273 Return 0 if different, 1 if the new one should just replace it, or a
5274 value N > 1 if we should also append " [N times]". */
5275
5276static int
5277message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
5278 int prev_bol, this_bol;
5279 int prev_bol_byte, this_bol_byte;
5280{
5281 int i;
5282 int len = Z_BYTE - 1 - this_bol_byte;
5283 int seen_dots = 0;
5284 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
5285 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
5286
5287 for (i = 0; i < len; i++)
5288 {
5289 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
5290 && p1[i] != '\n')
5291 seen_dots = 1;
5292 if (p1[i] != p2[i])
5293 return seen_dots;
5294 }
5295 p1 += len;
5296 if (*p1 == '\n')
5297 return 2;
5298 if (*p1++ == ' ' && *p1++ == '[')
5299 {
5300 int n = 0;
5301 while (*p1 >= '0' && *p1 <= '9')
5302 n = n * 10 + *p1++ - '0';
5303 if (strncmp (p1, " times]\n", 8) == 0)
5304 return n+1;
5305 }
5306 return 0;
5307}
5308
5309
5310/* Display an echo area message M with a specified length of LEN
5311 chars. The string may include null characters. If M is 0, clear
5312 out any existing message, and let the mini-buffer text show through.
5313
5314 The buffer M must continue to exist until after the echo area gets
5315 cleared or some other message gets displayed there. This means do
5316 not pass text that is stored in a Lisp string; do not pass text in
5317 a buffer that was alloca'd. */
5318
5319void
5320message2 (m, len, multibyte)
5321 char *m;
5322 int len;
5323 int multibyte;
5324{
5325 /* First flush out any partial line written with print. */
5326 message_log_maybe_newline ();
5327 if (m)
5328 message_dolog (m, len, 1, multibyte);
5329 message2_nolog (m, len, multibyte);
5330}
5331
5332
5333/* The non-logging counterpart of message2. */
5334
5335void
5336message2_nolog (m, len, multibyte)
5337 char *m;
5338 int len;
5339{
886bd6f2 5340 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5341 message_enable_multibyte = multibyte;
5342
5343 if (noninteractive)
5344 {
5345 if (noninteractive_need_newline)
5346 putc ('\n', stderr);
5347 noninteractive_need_newline = 0;
5348 if (m)
5349 fwrite (m, len, 1, stderr);
5350 if (cursor_in_echo_area == 0)
5351 fprintf (stderr, "\n");
5352 fflush (stderr);
5353 }
5354 /* A null message buffer means that the frame hasn't really been
5355 initialized yet. Error messages get reported properly by
5356 cmd_error, so this must be just an informative message; toss it. */
5357 else if (INTERACTIVE
886bd6f2
GM
5358 && sf->glyphs_initialized_p
5359 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
5360 {
5361 Lisp_Object mini_window;
5362 struct frame *f;
5363
5364 /* Get the frame containing the mini-buffer
5365 that the selected frame is using. */
886bd6f2 5366 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5367 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5368
5369 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 5370 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
5371 && ! FRAME_VISIBLE_P (f))
5372 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
5373
5374 if (m)
5375 {
c6e89d6c 5376 set_message (m, Qnil, len, multibyte);
5f5c8ee5
GM
5377 if (minibuffer_auto_raise)
5378 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5379 }
5380 else
c6e89d6c 5381 clear_message (1, 1);
5f5c8ee5 5382
c6e89d6c 5383 do_pending_window_change (0);
5f5c8ee5 5384 echo_area_display (1);
c6e89d6c 5385 do_pending_window_change (0);
5f5c8ee5
GM
5386 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
5387 (*frame_up_to_date_hook) (f);
5388 }
5389}
5390
5391
c6e89d6c
GM
5392/* Display an echo area message M with a specified length of NBYTES
5393 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
5394 string, clear out any existing message, and let the mini-buffer
5395 text show through. */
5396
5397void
c6e89d6c 5398message3 (m, nbytes, multibyte)
5f5c8ee5 5399 Lisp_Object m;
c6e89d6c 5400 int nbytes;
5f5c8ee5
GM
5401 int multibyte;
5402{
5403 struct gcpro gcpro1;
5404
5405 GCPRO1 (m);
5406
5407 /* First flush out any partial line written with print. */
5408 message_log_maybe_newline ();
5409 if (STRINGP (m))
c6e89d6c
GM
5410 message_dolog (XSTRING (m)->data, nbytes, 1, multibyte);
5411 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
5412
5413 UNGCPRO;
5414}
5415
5416
5417/* The non-logging version of message3. */
5418
5419void
c6e89d6c 5420message3_nolog (m, nbytes, multibyte)
5f5c8ee5 5421 Lisp_Object m;
c6e89d6c 5422 int nbytes, multibyte;
5f5c8ee5 5423{
886bd6f2 5424 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5425 message_enable_multibyte = multibyte;
5426
5427 if (noninteractive)
5428 {
5429 if (noninteractive_need_newline)
5430 putc ('\n', stderr);
5431 noninteractive_need_newline = 0;
5432 if (STRINGP (m))
c6e89d6c 5433 fwrite (XSTRING (m)->data, nbytes, 1, stderr);
5f5c8ee5
GM
5434 if (cursor_in_echo_area == 0)
5435 fprintf (stderr, "\n");
5436 fflush (stderr);
5437 }
5438 /* A null message buffer means that the frame hasn't really been
5439 initialized yet. Error messages get reported properly by
5440 cmd_error, so this must be just an informative message; toss it. */
5441 else if (INTERACTIVE
886bd6f2
GM
5442 && sf->glyphs_initialized_p
5443 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
5444 {
5445 Lisp_Object mini_window;
c6e89d6c 5446 Lisp_Object frame;
5f5c8ee5
GM
5447 struct frame *f;
5448
5449 /* Get the frame containing the mini-buffer
5450 that the selected frame is using. */
886bd6f2 5451 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5452 frame = XWINDOW (mini_window)->frame;
5453 f = XFRAME (frame);
5f5c8ee5
GM
5454
5455 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 5456 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
5457 && !FRAME_VISIBLE_P (f))
5458 Fmake_frame_visible (frame);
5f5c8ee5 5459
c6e89d6c 5460 if (STRINGP (m) && XSTRING (m)->size)
5f5c8ee5 5461 {
c6e89d6c 5462 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
5463 if (minibuffer_auto_raise)
5464 Fraise_frame (frame);
5f5c8ee5
GM
5465 }
5466 else
c6e89d6c 5467 clear_message (1, 1);
5f5c8ee5 5468
c6e89d6c 5469 do_pending_window_change (0);
5f5c8ee5 5470 echo_area_display (1);
c6e89d6c 5471 do_pending_window_change (0);
5f5c8ee5
GM
5472 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
5473 (*frame_up_to_date_hook) (f);
5474 }
5475}
5476
5477
5478/* Display a null-terminated echo area message M. If M is 0, clear
5479 out any existing message, and let the mini-buffer text show through.
5480
5481 The buffer M must continue to exist until after the echo area gets
5482 cleared or some other message gets displayed there. Do not pass
5483 text that is stored in a Lisp string. Do not pass text in a buffer
5484 that was alloca'd. */
5485
5486void
5487message1 (m)
5488 char *m;
5489{
5490 message2 (m, (m ? strlen (m) : 0), 0);
5491}
5492
5493
5494/* The non-logging counterpart of message1. */
5495
5496void
5497message1_nolog (m)
5498 char *m;
5499{
5500 message2_nolog (m, (m ? strlen (m) : 0), 0);
5501}
5502
5503/* Display a message M which contains a single %s
5504 which gets replaced with STRING. */
5505
5506void
5507message_with_string (m, string, log)
5508 char *m;
5509 Lisp_Object string;
5510 int log;
5511{
5512 if (noninteractive)
5513 {
5514 if (m)
5515 {
5516 if (noninteractive_need_newline)
5517 putc ('\n', stderr);
5518 noninteractive_need_newline = 0;
5519 fprintf (stderr, m, XSTRING (string)->data);
5520 if (cursor_in_echo_area == 0)
5521 fprintf (stderr, "\n");
5522 fflush (stderr);
5523 }
5524 }
5525 else if (INTERACTIVE)
5526 {
5527 /* The frame whose minibuffer we're going to display the message on.
5528 It may be larger than the selected frame, so we need
5529 to use its buffer, not the selected frame's buffer. */
5530 Lisp_Object mini_window;
886bd6f2 5531 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5532
5533 /* Get the frame containing the minibuffer
5534 that the selected frame is using. */
886bd6f2 5535 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5536 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5537
5538 /* A null message buffer means that the frame hasn't really been
5539 initialized yet. Error messages get reported properly by
5540 cmd_error, so this must be just an informative message; toss it. */
5541 if (FRAME_MESSAGE_BUF (f))
5542 {
5543 int len;
5544 char *a[1];
5545 a[0] = (char *) XSTRING (string)->data;
5546
5547 len = doprnt (FRAME_MESSAGE_BUF (f),
5548 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5549
5550 if (log)
5551 message2 (FRAME_MESSAGE_BUF (f), len,
5552 STRING_MULTIBYTE (string));
5553 else
5554 message2_nolog (FRAME_MESSAGE_BUF (f), len,
5555 STRING_MULTIBYTE (string));
5556
5557 /* Print should start at the beginning of the message
5558 buffer next time. */
5559 message_buf_print = 0;
5560 }
5561 }
5562}
5563
5564
5f5c8ee5
GM
5565/* Dump an informative message to the minibuf. If M is 0, clear out
5566 any existing message, and let the mini-buffer text show through. */
5567
5568/* VARARGS 1 */
5569void
5570message (m, a1, a2, a3)
5571 char *m;
5572 EMACS_INT a1, a2, a3;
5573{
5574 if (noninteractive)
5575 {
5576 if (m)
5577 {
5578 if (noninteractive_need_newline)
5579 putc ('\n', stderr);
5580 noninteractive_need_newline = 0;
5581 fprintf (stderr, m, a1, a2, a3);
5582 if (cursor_in_echo_area == 0)
5583 fprintf (stderr, "\n");
5584 fflush (stderr);
5585 }
5586 }
5587 else if (INTERACTIVE)
5588 {
5589 /* The frame whose mini-buffer we're going to display the message
5590 on. It may be larger than the selected frame, so we need to
5591 use its buffer, not the selected frame's buffer. */
5592 Lisp_Object mini_window;
886bd6f2 5593 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5594
5595 /* Get the frame containing the mini-buffer
5596 that the selected frame is using. */
886bd6f2 5597 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5598 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5599
5600 /* A null message buffer means that the frame hasn't really been
5601 initialized yet. Error messages get reported properly by
5602 cmd_error, so this must be just an informative message; toss
5603 it. */
5604 if (FRAME_MESSAGE_BUF (f))
5605 {
5606 if (m)
5607 {
5608 int len;
5609#ifdef NO_ARG_ARRAY
5610 char *a[3];
5611 a[0] = (char *) a1;
5612 a[1] = (char *) a2;
5613 a[2] = (char *) a3;
5614
5615 len = doprnt (FRAME_MESSAGE_BUF (f),
5616 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5617#else
5618 len = doprnt (FRAME_MESSAGE_BUF (f),
5619 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
5620 (char **) &a1);
5621#endif /* NO_ARG_ARRAY */
5622
5623 message2 (FRAME_MESSAGE_BUF (f), len, 0);
5624 }
5625 else
5626 message1 (0);
5627
5628 /* Print should start at the beginning of the message
5629 buffer next time. */
5630 message_buf_print = 0;
5631 }
5632 }
5633}
5634
5635
5636/* The non-logging version of message. */
5637
5638void
5639message_nolog (m, a1, a2, a3)
5640 char *m;
5641 EMACS_INT a1, a2, a3;
5642{
5643 Lisp_Object old_log_max;
5644 old_log_max = Vmessage_log_max;
5645 Vmessage_log_max = Qnil;
5646 message (m, a1, a2, a3);
5647 Vmessage_log_max = old_log_max;
5648}
5649
5650
c6e89d6c
GM
5651/* Display the current message in the current mini-buffer. This is
5652 only called from error handlers in process.c, and is not time
5653 critical. */
5f5c8ee5
GM
5654
5655void
5656update_echo_area ()
5657{
c6e89d6c
GM
5658 if (!NILP (echo_area_buffer[0]))
5659 {
5660 Lisp_Object string;
5661 string = Fcurrent_message ();
5662 message3 (string, XSTRING (string)->size,
5663 !NILP (current_buffer->enable_multibyte_characters));
5664 }
5665}
5666
5667
5bcfeb49
GM
5668/* Make sure echo area buffers in echo_buffers[] are life. If they
5669 aren't, make new ones. */
5670
5671static void
5672ensure_echo_area_buffers ()
5673{
5674 int i;
5675
5676 for (i = 0; i < 2; ++i)
5677 if (!BUFFERP (echo_buffer[i])
5678 || NILP (XBUFFER (echo_buffer[i])->name))
5679 {
5680 char name[30];
ff3d9573
GM
5681 Lisp_Object old_buffer;
5682 int j;
5683
5684 old_buffer = echo_buffer[i];
5bcfeb49
GM
5685 sprintf (name, " *Echo Area %d*", i);
5686 echo_buffer[i] = Fget_buffer_create (build_string (name));
ad4f174e 5687 XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
ff3d9573
GM
5688
5689 for (j = 0; j < 2; ++j)
5690 if (EQ (old_buffer, echo_area_buffer[j]))
5691 echo_area_buffer[j] = echo_buffer[i];
5bcfeb49
GM
5692 }
5693}
5694
5695
23a96c77 5696/* Call FN with args A1..A4 with either the current or last displayed
c6e89d6c
GM
5697 echo_area_buffer as current buffer.
5698
5699 WHICH zero means use the current message buffer
5700 echo_area_buffer[0]. If that is nil, choose a suitable buffer
5701 from echo_buffer[] and clear it.
5702
5703 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
5704 suitable buffer from echo_buffer[] and clear it.
5705
5706 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
5707 that the current message becomes the last displayed one, make
5708 choose a suitable buffer for echo_area_buffer[0], and clear it.
5709
5710 Value is what FN returns. */
5711
5712static int
23a96c77 5713with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
c6e89d6c
GM
5714 struct window *w;
5715 int which;
23dd2d97
KR
5716 int (*fn) P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
5717 EMACS_INT a1;
5718 Lisp_Object a2;
5719 EMACS_INT a3, a4;
c6e89d6c
GM
5720{
5721 Lisp_Object buffer;
15e26c76 5722 int this_one, the_other, clear_buffer_p, rc;
c6e89d6c
GM
5723 int count = specpdl_ptr - specpdl;
5724
5725 /* If buffers aren't life, make new ones. */
5bcfeb49 5726 ensure_echo_area_buffers ();
c6e89d6c
GM
5727
5728 clear_buffer_p = 0;
5729
5730 if (which == 0)
5731 this_one = 0, the_other = 1;
5732 else if (which > 0)
5733 this_one = 1, the_other = 0;
5f5c8ee5 5734 else
c6e89d6c
GM
5735 {
5736 this_one = 0, the_other = 1;
5737 clear_buffer_p = 1;
5738
5739 /* We need a fresh one in case the current echo buffer equals
5740 the one containing the last displayed echo area message. */
5741 if (!NILP (echo_area_buffer[this_one])
5742 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
5743 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
5744 }
5745
5746 /* Choose a suitable buffer from echo_buffer[] is we don't
5747 have one. */
5748 if (NILP (echo_area_buffer[this_one]))
5749 {
5750 echo_area_buffer[this_one]
5751 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
5752 ? echo_buffer[the_other]
5753 : echo_buffer[this_one]);
5754 clear_buffer_p = 1;
5755 }
5756
5757 buffer = echo_area_buffer[this_one];
5758
5759 record_unwind_protect (unwind_with_echo_area_buffer,
5760 with_echo_area_buffer_unwind_data (w));
5761
5762 /* Make the echo area buffer current. Note that for display
5763 purposes, it is not necessary that the displayed window's buffer
5764 == current_buffer, except for text property lookup. So, let's
5765 only set that buffer temporarily here without doing a full
5766 Fset_window_buffer. We must also change w->pointm, though,
5767 because otherwise an assertions in unshow_buffer fails, and Emacs
5768 aborts. */
9142dd5b 5769 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
5770 if (w)
5771 {
5772 w->buffer = buffer;
5773 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
5774 }
ad4f174e 5775
c6e89d6c
GM
5776 current_buffer->undo_list = Qt;
5777 current_buffer->read_only = Qnil;
5778
5779 if (clear_buffer_p && Z > BEG)
5780 del_range (BEG, Z);
5781
5782 xassert (BEGV >= BEG);
5783 xassert (ZV <= Z && ZV >= BEGV);
5784
23a96c77 5785 rc = fn (a1, a2, a3, a4);
c6e89d6c
GM
5786
5787 xassert (BEGV >= BEG);
5788 xassert (ZV <= Z && ZV >= BEGV);
5789
5790 unbind_to (count, Qnil);
5791 return rc;
5f5c8ee5
GM
5792}
5793
5794
c6e89d6c
GM
5795/* Save state that should be preserved around the call to the function
5796 FN called in with_echo_area_buffer. */
5f5c8ee5 5797
c6e89d6c
GM
5798static Lisp_Object
5799with_echo_area_buffer_unwind_data (w)
5800 struct window *w;
5f5c8ee5 5801{
c6e89d6c
GM
5802 int i = 0;
5803 Lisp_Object vector;
5f5c8ee5 5804
c6e89d6c
GM
5805 /* Reduce consing by keeping one vector in
5806 Vwith_echo_area_save_vector. */
5807 vector = Vwith_echo_area_save_vector;
5808 Vwith_echo_area_save_vector = Qnil;
5809
5810 if (NILP (vector))
9142dd5b 5811 vector = Fmake_vector (make_number (7), Qnil);
c6e89d6c
GM
5812
5813 XSETBUFFER (XVECTOR (vector)->contents[i], current_buffer); ++i;
5814 XVECTOR (vector)->contents[i++] = Vdeactivate_mark;
5815 XVECTOR (vector)->contents[i++] = make_number (windows_or_buffers_changed);
c6e89d6c
GM
5816
5817 if (w)
5818 {
5819 XSETWINDOW (XVECTOR (vector)->contents[i], w); ++i;
5820 XVECTOR (vector)->contents[i++] = w->buffer;
5821 XVECTOR (vector)->contents[i++]
5822 = make_number (XMARKER (w->pointm)->charpos);
5823 XVECTOR (vector)->contents[i++]
5824 = make_number (XMARKER (w->pointm)->bytepos);
5825 }
5826 else
5827 {
5828 int end = i + 4;
5829 while (i < end)
5830 XVECTOR (vector)->contents[i++] = Qnil;
5831 }
5f5c8ee5 5832
c6e89d6c
GM
5833 xassert (i == XVECTOR (vector)->size);
5834 return vector;
5835}
5f5c8ee5 5836
5f5c8ee5 5837
c6e89d6c
GM
5838/* Restore global state from VECTOR which was created by
5839 with_echo_area_buffer_unwind_data. */
5840
5841static Lisp_Object
5842unwind_with_echo_area_buffer (vector)
5843 Lisp_Object vector;
5844{
5845 int i = 0;
5846
9142dd5b 5847 set_buffer_internal_1 (XBUFFER (XVECTOR (vector)->contents[i])); ++i;
c6e89d6c
GM
5848 Vdeactivate_mark = XVECTOR (vector)->contents[i]; ++i;
5849 windows_or_buffers_changed = XFASTINT (XVECTOR (vector)->contents[i]); ++i;
c6e89d6c
GM
5850
5851 if (WINDOWP (XVECTOR (vector)->contents[i]))
5852 {
5853 struct window *w;
5854 Lisp_Object buffer, charpos, bytepos;
5855
5856 w = XWINDOW (XVECTOR (vector)->contents[i]); ++i;
5857 buffer = XVECTOR (vector)->contents[i]; ++i;
5858 charpos = XVECTOR (vector)->contents[i]; ++i;
5859 bytepos = XVECTOR (vector)->contents[i]; ++i;
5860
5861 w->buffer = buffer;
5862 set_marker_both (w->pointm, buffer,
5863 XFASTINT (charpos), XFASTINT (bytepos));
5864 }
5865
5866 Vwith_echo_area_save_vector = vector;
5867 return Qnil;
5868}
5869
5870
5871/* Set up the echo area for use by print functions. MULTIBYTE_P
5872 non-zero means we will print multibyte. */
5873
5874void
5875setup_echo_area_for_printing (multibyte_p)
5876 int multibyte_p;
5877{
5bcfeb49
GM
5878 ensure_echo_area_buffers ();
5879
c6e89d6c
GM
5880 if (!message_buf_print)
5881 {
5882 /* A message has been output since the last time we printed.
5883 Choose a fresh echo area buffer. */
5884 if (EQ (echo_area_buffer[1], echo_buffer[0]))
5885 echo_area_buffer[0] = echo_buffer[1];
5886 else
5887 echo_area_buffer[0] = echo_buffer[0];
5888
5889 /* Switch to that buffer and clear it. */
5890 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5891 if (Z > BEG)
5892 del_range (BEG, Z);
5893 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5894
5895 /* Set up the buffer for the multibyteness we need. */
5896 if (multibyte_p
5897 != !NILP (current_buffer->enable_multibyte_characters))
5898 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
5899
5900 /* Raise the frame containing the echo area. */
5901 if (minibuffer_auto_raise)
5902 {
886bd6f2 5903 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5904 Lisp_Object mini_window;
886bd6f2 5905 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5906 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5907 }
5908
8a4e3c0c 5909 message_log_maybe_newline ();
c6e89d6c
GM
5910 message_buf_print = 1;
5911 }
fa77249f
GM
5912 else
5913 {
5914 if (NILP (echo_area_buffer[0]))
5915 {
5916 if (EQ (echo_area_buffer[1], echo_buffer[0]))
5917 echo_area_buffer[0] = echo_buffer[1];
5918 else
5919 echo_area_buffer[0] = echo_buffer[0];
5920 }
5921
5922 if (current_buffer != XBUFFER (echo_area_buffer[0]))
5923 /* Someone switched buffers between print requests. */
5924 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5925 }
c6e89d6c
GM
5926}
5927
5928
dd2eb166
GM
5929/* Display an echo area message in window W. Value is non-zero if W's
5930 height is changed. If display_last_displayed_message_p is
5931 non-zero, display the message that was last displayed, otherwise
5932 display the current message. */
c6e89d6c
GM
5933
5934static int
5935display_echo_area (w)
5936 struct window *w;
5937{
25edb08f
GM
5938 int i, no_message_p, window_height_changed_p, count;
5939
5940 /* Temporarily disable garbage collections while displaying the echo
5941 area. This is done because a GC can print a message itself.
5942 That message would modify the echo area buffer's contents while a
5943 redisplay of the buffer is going on, and seriously confuse
5944 redisplay. */
5945 count = inhibit_garbage_collection ();
dd2eb166
GM
5946
5947 /* If there is no message, we must call display_echo_area_1
5948 nevertheless because it resizes the window. But we will have to
5949 reset the echo_area_buffer in question to nil at the end because
5950 with_echo_area_buffer will sets it to an empty buffer. */
5951 i = display_last_displayed_message_p ? 1 : 0;
5952 no_message_p = NILP (echo_area_buffer[i]);
5953
5954 window_height_changed_p
5955 = with_echo_area_buffer (w, display_last_displayed_message_p,
23a96c77 5956 display_echo_area_1,
23dd2d97 5957 (EMACS_INT) w, Qnil, 0, 0);
dd2eb166
GM
5958
5959 if (no_message_p)
5960 echo_area_buffer[i] = Qnil;
25edb08f
GM
5961
5962 unbind_to (count, Qnil);
dd2eb166 5963 return window_height_changed_p;
c6e89d6c
GM
5964}
5965
5966
5967/* Helper for display_echo_area. Display the current buffer which
23a96c77
GM
5968 contains the current echo area message in window W, a mini-window,
5969 a pointer to which is passed in A1. A2..A4 are currently not used.
c6e89d6c
GM
5970 Change the height of W so that all of the message is displayed.
5971 Value is non-zero if height of W was changed. */
5972
5973static int
23a96c77 5974display_echo_area_1 (a1, a2, a3, a4)
23dd2d97
KR
5975 EMACS_INT a1;
5976 Lisp_Object a2;
5977 EMACS_INT a3, a4;
c6e89d6c 5978{
23a96c77 5979 struct window *w = (struct window *) a1;
c6e89d6c 5980 Lisp_Object window;
c6e89d6c
GM
5981 struct text_pos start;
5982 int window_height_changed_p = 0;
5983
5984 /* Do this before displaying, so that we have a large enough glyph
5985 matrix for the display. */
92a90e89 5986 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
5987
5988 /* Display. */
5989 clear_glyph_matrix (w->desired_matrix);
5990 XSETWINDOW (window, w);
5991 SET_TEXT_POS (start, BEG, BEG_BYTE);
5992 try_window (window, start);
5993
c6e89d6c
GM
5994 return window_height_changed_p;
5995}
5996
5997
92a90e89
GM
5998/* Resize the echo area window to exactly the size needed for the
5999 currently displayed message, if there is one. */
6000
6001void
6002resize_echo_area_axactly ()
6003{
6004 if (BUFFERP (echo_area_buffer[0])
6005 && WINDOWP (echo_area_window))
6006 {
6007 struct window *w = XWINDOW (echo_area_window);
6008 int resized_p;
6009
23a96c77 6010 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
23dd2d97 6011 (EMACS_INT) w, Qnil, 0, 0);
92a90e89
GM
6012 if (resized_p)
6013 {
6014 ++windows_or_buffers_changed;
6015 ++update_mode_lines;
6016 redisplay_internal (0);
6017 }
6018 }
6019}
6020
6021
23a96c77
GM
6022/* Callback function for with_echo_area_buffer, when used from
6023 resize_echo_area_axactly. A1 contains a pointer to the window to
6024 resize, A2 to A4 are not used. Value is what resize_mini_window
6025 returns. */
6026
6027static int
6028resize_mini_window_1 (a1, a2, a3, a4)
23dd2d97
KR
6029 EMACS_INT a1;
6030 Lisp_Object a2;
6031 EMACS_INT a3, a4;
23a96c77
GM
6032{
6033 return resize_mini_window ((struct window *) a1, 1);
6034}
6035
6036
92a90e89
GM
6037/* Resize mini-window W to fit the size of its contents. EXACT:P
6038 means size the window exactly to the size needed. Otherwise, it's
6039 only enlarged until W's buffer is empty. Value is non-zero if
6040 the window height has been changed. */
c6e89d6c 6041
9472f927 6042int
92a90e89 6043resize_mini_window (w, exact_p)
c6e89d6c 6044 struct window *w;
92a90e89 6045 int exact_p;
c6e89d6c
GM
6046{
6047 struct frame *f = XFRAME (w->frame);
6048 int window_height_changed_p = 0;
6049
6050 xassert (MINI_WINDOW_P (w));
97cafc0f
GM
6051
6052 /* Nil means don't try to resize. */
00f6d59e
GM
6053 if (NILP (Vmax_mini_window_height)
6054 || (FRAME_X_P (f) && f->output_data.x == NULL))
97cafc0f 6055 return 0;
c6e89d6c
GM
6056
6057 if (!FRAME_MINIBUF_ONLY_P (f))
6058 {
6059 struct it it;
dd2eb166
GM
6060 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
6061 int total_height = XFASTINT (root->height) + XFASTINT (w->height);
6062 int height, max_height;
6063 int unit = CANON_Y_UNIT (f);
6064 struct text_pos start;
9142dd5b 6065
c6e89d6c 6066 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 6067
dd2eb166
GM
6068 /* Compute the max. number of lines specified by the user. */
6069 if (FLOATP (Vmax_mini_window_height))
6070 max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
6071 else if (INTEGERP (Vmax_mini_window_height))
6072 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
6073 else
6074 max_height = total_height / 4;
dd2eb166
GM
6075
6076 /* Correct that max. height if it's bogus. */
6077 max_height = max (1, max_height);
6078 max_height = min (total_height, max_height);
6079
6080 /* Find out the height of the text in the window. */
ad4f174e
GM
6081 if (it.truncate_lines_p)
6082 height = 1;
55b064bd 6083 else
ad4f174e
GM
6084 {
6085 last_height = 0;
6086 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
6087 if (it.max_ascent == 0 && it.max_descent == 0)
6088 height = it.current_y + last_height;
6089 else
6090 height = it.current_y + it.max_ascent + it.max_descent;
3c4b7685 6091 height -= it.extra_line_spacing;
ad4f174e
GM
6092 height = (height + unit - 1) / unit;
6093 }
dd2eb166
GM
6094
6095 /* Compute a suitable window start. */
6096 if (height > max_height)
6097 {
6098 height = max_height;
6099 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
6100 move_it_vertically_backward (&it, (height - 1) * unit);
6101 start = it.current.pos;
6102 }
6103 else
6104 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
6105 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 6106
9472f927
GM
6107 /* Let it grow only, until we display an empty message, in which
6108 case the window shrinks again. */
da448723 6109 if (height > XFASTINT (w->height))
dd2eb166 6110 {
d2c48e86 6111 int old_height = XFASTINT (w->height);
da448723
GM
6112 freeze_window_starts (f, 1);
6113 grow_mini_window (w, height - XFASTINT (w->height));
6114 window_height_changed_p = XFASTINT (w->height) != old_height;
6115 }
6116 else if (height < XFASTINT (w->height)
6117 && (exact_p || BEGV == ZV))
6118 {
6119 int old_height = XFASTINT (w->height);
6120 freeze_window_starts (f, 0);
6121 shrink_mini_window (w);
d2c48e86 6122 window_height_changed_p = XFASTINT (w->height) != old_height;
9142dd5b 6123 }
c6e89d6c
GM
6124 }
6125
6126 return window_height_changed_p;
6127}
6128
6129
6130/* Value is the current message, a string, or nil if there is no
6131 current message. */
6132
6133Lisp_Object
6134current_message ()
6135{
6136 Lisp_Object msg;
6137
6138 if (NILP (echo_area_buffer[0]))
6139 msg = Qnil;
6140 else
6141 {
23a96c77 6142 with_echo_area_buffer (0, 0, current_message_1,
23dd2d97 6143 (EMACS_INT) &msg, Qnil, 0, 0);
c6e89d6c
GM
6144 if (NILP (msg))
6145 echo_area_buffer[0] = Qnil;
6146 }
6147
6148 return msg;
6149}
6150
6151
6152static int
23a96c77 6153current_message_1 (a1, a2, a3, a4)
23dd2d97
KR
6154 EMACS_INT a1;
6155 Lisp_Object a2;
6156 EMACS_INT a3, a4;
c6e89d6c 6157{
23a96c77
GM
6158 Lisp_Object *msg = (Lisp_Object *) a1;
6159
c6e89d6c
GM
6160 if (Z > BEG)
6161 *msg = make_buffer_string (BEG, Z, 1);
6162 else
6163 *msg = Qnil;
6164 return 0;
6165}
6166
6167
6168/* Push the current message on Vmessage_stack for later restauration
6169 by restore_message. Value is non-zero if the current message isn't
6170 empty. This is a relatively infrequent operation, so it's not
6171 worth optimizing. */
6172
6173int
6174push_message ()
6175{
6176 Lisp_Object msg;
6177 msg = current_message ();
6178 Vmessage_stack = Fcons (msg, Vmessage_stack);
6179 return STRINGP (msg);
6180}
6181
6182
6183/* Restore message display from the top of Vmessage_stack. */
6184
6185void
6186restore_message ()
6187{
6188 Lisp_Object msg;
6189
6190 xassert (CONSP (Vmessage_stack));
6191 msg = XCAR (Vmessage_stack);
6192 if (STRINGP (msg))
6193 message3_nolog (msg, STRING_BYTES (XSTRING (msg)), STRING_MULTIBYTE (msg));
6194 else
6195 message3_nolog (msg, 0, 0);
6196}
6197
6198
6199/* Pop the top-most entry off Vmessage_stack. */
6200
6201void
6202pop_message ()
6203{
6204 xassert (CONSP (Vmessage_stack));
6205 Vmessage_stack = XCDR (Vmessage_stack);
6206}
6207
6208
6209/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
6210 exits. If the stack is not empty, we have a missing pop_message
6211 somewhere. */
6212
6213void
6214check_message_stack ()
6215{
6216 if (!NILP (Vmessage_stack))
6217 abort ();
6218}
6219
6220
6221/* Truncate to NCHARS what will be displayed in the echo area the next
6222 time we display it---but don't redisplay it now. */
6223
6224void
6225truncate_echo_area (nchars)
6226 int nchars;
6227{
6228 if (nchars == 0)
6229 echo_area_buffer[0] = Qnil;
6230 /* A null message buffer means that the frame hasn't really been
6231 initialized yet. Error messages get reported properly by
6232 cmd_error, so this must be just an informative message; toss it. */
6233 else if (!noninteractive
6234 && INTERACTIVE
c6e89d6c 6235 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
6236 {
6237 struct frame *sf = SELECTED_FRAME ();
6238 if (FRAME_MESSAGE_BUF (sf))
23dd2d97 6239 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0);
886bd6f2 6240 }
c6e89d6c
GM
6241}
6242
6243
6244/* Helper function for truncate_echo_area. Truncate the current
6245 message to at most NCHARS characters. */
6246
6247static int
23a96c77 6248truncate_message_1 (nchars, a2, a3, a4)
23dd2d97
KR
6249 EMACS_INT nchars;
6250 Lisp_Object a2;
6251 EMACS_INT a3, a4;
c6e89d6c
GM
6252{
6253 if (BEG + nchars < Z)
6254 del_range (BEG + nchars, Z);
6255 if (Z == BEG)
6256 echo_area_buffer[0] = Qnil;
6257 return 0;
6258}
6259
6260
6261/* Set the current message to a substring of S or STRING.
6262
6263 If STRING is a Lisp string, set the message to the first NBYTES
6264 bytes from STRING. NBYTES zero means use the whole string. If
6265 STRING is multibyte, the message will be displayed multibyte.
6266
6267 If S is not null, set the message to the first LEN bytes of S. LEN
6268 zero means use the whole string. MULTIBYTE_P non-zero means S is
6269 multibyte. Display the message multibyte in that case. */
6270
6271void
6272set_message (s, string, nbytes, multibyte_p)
6273 char *s;
6274 Lisp_Object string;
6275 int nbytes;
6276{
6277 message_enable_multibyte
6278 = ((s && multibyte_p)
6279 || (STRINGP (string) && STRING_MULTIBYTE (string)));
6280
23a96c77
GM
6281 with_echo_area_buffer (0, -1, set_message_1,
6282 (EMACS_INT) s, string, nbytes, multibyte_p);
c6e89d6c 6283 message_buf_print = 0;
21fdfb65 6284 help_echo_showing_p = 0;
c6e89d6c
GM
6285}
6286
6287
6288/* Helper function for set_message. Arguments have the same meaning
23a96c77
GM
6289 as there, with A1 corresponding to S and A2 corresponding to STRING
6290 This function is called with the echo area buffer being
c6e89d6c
GM
6291 current. */
6292
6293static int
23a96c77 6294set_message_1 (a1, a2, nbytes, multibyte_p)
23dd2d97
KR
6295 EMACS_INT a1;
6296 Lisp_Object a2;
6297 EMACS_INT nbytes, multibyte_p;
c6e89d6c 6298{
23a96c77 6299 char *s = (char *) a1;
23dd2d97 6300 Lisp_Object string = a2;
23a96c77 6301
c6e89d6c
GM
6302 xassert (BEG == Z);
6303
6304 /* Change multibyteness of the echo buffer appropriately. */
6305 if (message_enable_multibyte
6306 != !NILP (current_buffer->enable_multibyte_characters))
6307 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
6308
ad4f174e
GM
6309 current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
6310
c6e89d6c
GM
6311 /* Insert new message at BEG. */
6312 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
6313
6314 if (STRINGP (string))
6315 {
6316 int nchars;
6317
6318 if (nbytes == 0)
6319 nbytes = XSTRING (string)->size_byte;
6320 nchars = string_byte_to_char (string, nbytes);
6321
6322 /* This function takes care of single/multibyte conversion. We
6323 just have to ensure that the echo area buffer has the right
6324 setting of enable_multibyte_characters. */
6325 insert_from_string (string, 0, 0, nchars, nbytes, 1);
6326 }
6327 else if (s)
6328 {
6329 if (nbytes == 0)
6330 nbytes = strlen (s);
6331
6332 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
6333 {
6334 /* Convert from multi-byte to single-byte. */
6335 int i, c, n;
6336 unsigned char work[1];
6337
6338 /* Convert a multibyte string to single-byte. */
6339 for (i = 0; i < nbytes; i += n)
6340 {
6341 c = string_char_and_length (s + i, nbytes - i, &n);
6342 work[0] = (SINGLE_BYTE_CHAR_P (c)
6343 ? c
6344 : multibyte_char_to_unibyte (c, Qnil));
6345 insert_1_both (work, 1, 1, 1, 0, 0);
6346 }
6347 }
6348 else if (!multibyte_p
6349 && !NILP (current_buffer->enable_multibyte_characters))
6350 {
6351 /* Convert from single-byte to multi-byte. */
6352 int i, c, n;
6353 unsigned char *msg = (unsigned char *) s;
260a86a0 6354 unsigned char str[MAX_MULTIBYTE_LENGTH];
c6e89d6c
GM
6355
6356 /* Convert a single-byte string to multibyte. */
6357 for (i = 0; i < nbytes; i++)
6358 {
6359 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
6360 n = CHAR_STRING (c, str);
6361 insert_1_both (str, 1, n, 1, 0, 0);
c6e89d6c
GM
6362 }
6363 }
6364 else
6365 insert_1 (s, nbytes, 1, 0, 0);
6366 }
6367
6368 return 0;
6369}
6370
6371
6372/* Clear messages. CURRENT_P non-zero means clear the current
6373 message. LAST_DISPLAYED_P non-zero means clear the message
6374 last displayed. */
6375
6376void
6377clear_message (current_p, last_displayed_p)
6378 int current_p, last_displayed_p;
6379{
6380 if (current_p)
6381 echo_area_buffer[0] = Qnil;
6382
6383 if (last_displayed_p)
6384 echo_area_buffer[1] = Qnil;
6385
6386 message_buf_print = 0;
6387}
6388
6389/* Clear garbaged frames.
6390
6391 This function is used where the old redisplay called
6392 redraw_garbaged_frames which in turn called redraw_frame which in
6393 turn called clear_frame. The call to clear_frame was a source of
6394 flickering. I believe a clear_frame is not necessary. It should
6395 suffice in the new redisplay to invalidate all current matrices,
6396 and ensure a complete redisplay of all windows. */
6397
6398static void
6399clear_garbaged_frames ()
6400{
5f5c8ee5
GM
6401 if (frame_garbaged)
6402 {
5f5c8ee5
GM
6403 Lisp_Object tail, frame;
6404
6405 FOR_EACH_FRAME (tail, frame)
6406 {
6407 struct frame *f = XFRAME (frame);
6408
6409 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
6410 {
6411 clear_current_matrices (f);
6412 f->garbaged = 0;
6413 }
6414 }
6415
6416 frame_garbaged = 0;
6417 ++windows_or_buffers_changed;
6418 }
c6e89d6c 6419}
5f5c8ee5 6420
5f5c8ee5 6421
886bd6f2
GM
6422/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
6423 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 6424 mini-windows height has been changed. */
5f5c8ee5 6425
c6e89d6c
GM
6426static int
6427echo_area_display (update_frame_p)
6428 int update_frame_p;
6429{
6430 Lisp_Object mini_window;
6431 struct window *w;
6432 struct frame *f;
6433 int window_height_changed_p = 0;
886bd6f2 6434 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 6435
886bd6f2 6436 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6437 w = XWINDOW (mini_window);
6438 f = XFRAME (WINDOW_FRAME (w));
6439
6440 /* Don't display if frame is invisible or not yet initialized. */
6441 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
6442 return 0;
5f5c8ee5 6443
1a578e9b
AC
6444/* The terminal frame is used as the first Emacs frame on the Mac OS. */
6445#ifndef macintosh
1ab3e082 6446#ifdef HAVE_WINDOW_SYSTEM
c6e89d6c
GM
6447 /* When Emacs starts, selected_frame may be a visible terminal
6448 frame, even if we run under a window system. If we let this
6449 through, a message would be displayed on the terminal. */
622e3754
GM
6450 if (EQ (selected_frame, Vterminal_frame)
6451 && !NILP (Vwindow_system))
c6e89d6c 6452 return 0;
1ab3e082 6453#endif /* HAVE_WINDOW_SYSTEM */
1a578e9b 6454#endif
c6e89d6c
GM
6455
6456 /* Redraw garbaged frames. */
6457 if (frame_garbaged)
6458 clear_garbaged_frames ();
6459
6460 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
6461 {
6462 echo_area_window = mini_window;
6463 window_height_changed_p = display_echo_area (w);
5f5c8ee5 6464 w->must_be_updated_p = 1;
c59c668a 6465
715e84c9 6466 /* Update the display, unless called from redisplay_internal. */
5f5c8ee5
GM
6467 if (update_frame_p)
6468 {
715e84c9 6469 int n = 0;
edc68111 6470
715e84c9
GM
6471 /* If the display update has been interrupted by pending
6472 input, update mode lines in the frame. Due to the
6473 pending input, it might have been that redisplay hasn't
6474 been called, so that mode lines above the echo area are
6475 garbaged. This looks odd, so we prevent it here. */
6476 if (!display_completed)
6477 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
6478
6479 if (window_height_changed_p)
c59c668a 6480 {
715e84c9 6481 /* Must update other windows. */
edc68111 6482 windows_or_buffers_changed = 1;
c59c668a
GM
6483 redisplay_internal (0);
6484 }
715e84c9 6485 else if (FRAME_WINDOW_P (f) && n == 0)
5f5c8ee5 6486 {
edc68111 6487 /* Window configuration is the same as before.
715e84c9
GM
6488 Can do with a display update of the echo area,
6489 unless we displayed some mode lines. */
5f5c8ee5
GM
6490 update_single_window (w, 1);
6491 rif->flush_display (f);
6492 }
6493 else
6494 update_frame (f, 1, 1);
6495 }
6496 }
6497 else if (!EQ (mini_window, selected_window))
6498 windows_or_buffers_changed++;
c59c668a
GM
6499
6500 /* Last displayed message is now the current message. */
dd2eb166
GM
6501 echo_area_buffer[1] = echo_area_buffer[0];
6502
5f5c8ee5
GM
6503 /* Prevent redisplay optimization in redisplay_internal by resetting
6504 this_line_start_pos. This is done because the mini-buffer now
6505 displays the message instead of its buffer text. */
6506 if (EQ (mini_window, selected_window))
6507 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
6508
6509 return window_height_changed_p;
5f5c8ee5
GM
6510}
6511
6512
6513\f
6514/***********************************************************************
6515 Frame Titles
6516 ***********************************************************************/
6517
6518
6519#ifdef HAVE_WINDOW_SYSTEM
6520
6521/* A buffer for constructing frame titles in it; allocated from the
6522 heap in init_xdisp and resized as needed in store_frame_title_char. */
6523
6524static char *frame_title_buf;
6525
6526/* The buffer's end, and a current output position in it. */
6527
6528static char *frame_title_buf_end;
6529static char *frame_title_ptr;
6530
6531
6532/* Store a single character C for the frame title in frame_title_buf.
6533 Re-allocate frame_title_buf if necessary. */
6534
6535static void
6536store_frame_title_char (c)
6537 char c;
6538{
6539 /* If output position has reached the end of the allocated buffer,
6540 double the buffer's size. */
6541 if (frame_title_ptr == frame_title_buf_end)
6542 {
6543 int len = frame_title_ptr - frame_title_buf;
6544 int new_size = 2 * len * sizeof *frame_title_buf;
6545 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
6546 frame_title_buf_end = frame_title_buf + new_size;
6547 frame_title_ptr = frame_title_buf + len;
6548 }
6549
6550 *frame_title_ptr++ = c;
6551}
6552
6553
6554/* Store part of a frame title in frame_title_buf, beginning at
6555 frame_title_ptr. STR is the string to store. Do not copy more
6556 than PRECISION number of bytes from STR; PRECISION <= 0 means copy
6557 the whole string. Pad with spaces until FIELD_WIDTH number of
6558 characters have been copied; FIELD_WIDTH <= 0 means don't pad.
6559 Called from display_mode_element when it is used to build a frame
6560 title. */
6561
6562static int
6563store_frame_title (str, field_width, precision)
6564 unsigned char *str;
6565 int field_width, precision;
6566{
6567 int n = 0;
6568
6569 /* Copy at most PRECISION chars from STR. */
6570 while ((precision <= 0 || n < precision)
6571 && *str)
6572 {
6573 store_frame_title_char (*str++);
6574 ++n;
6575 }
6576
6577 /* Fill up with spaces until FIELD_WIDTH reached. */
6578 while (field_width > 0
6579 && n < field_width)
6580 {
6581 store_frame_title_char (' ');
6582 ++n;
6583 }
6584
6585 return n;
6586}
6587
6588
6589/* Set the title of FRAME, if it has changed. The title format is
6590 Vicon_title_format if FRAME is iconified, otherwise it is
6591 frame_title_format. */
6592
6593static void
6594x_consider_frame_title (frame)
6595 Lisp_Object frame;
6596{
6597 struct frame *f = XFRAME (frame);
6598
6599 if (FRAME_WINDOW_P (f)
6600 || FRAME_MINIBUF_ONLY_P (f)
6601 || f->explicit_name)
6602 {
6603 /* Do we have more than one visible frame on this X display? */
6604 Lisp_Object tail;
6605 Lisp_Object fmt;
6606 struct buffer *obuf;
6607 int len;
6608 struct it it;
6609
9472f927 6610 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 6611 {
9472f927 6612 struct frame *tf = XFRAME (XCAR (tail));
5f5c8ee5
GM
6613
6614 if (tf != f
6615 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
6616 && !FRAME_MINIBUF_ONLY_P (tf)
6617 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
6618 break;
6619 }
6620
6621 /* Set global variable indicating that multiple frames exist. */
6622 multiple_frames = CONSP (tail);
6623
6624 /* Switch to the buffer of selected window of the frame. Set up
6625 frame_title_ptr so that display_mode_element will output into it;
6626 then display the title. */
6627 obuf = current_buffer;
6628 Fset_buffer (XWINDOW (f->selected_window)->buffer);
6629 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
6630 frame_title_ptr = frame_title_buf;
6631 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
6632 NULL, DEFAULT_FACE_ID);
6633 len = display_mode_element (&it, 0, -1, -1, fmt);
6634 frame_title_ptr = NULL;
6635 set_buffer_internal (obuf);
6636
6637 /* Set the title only if it's changed. This avoids consing in
6638 the common case where it hasn't. (If it turns out that we've
6639 already wasted too much time by walking through the list with
6640 display_mode_element, then we might need to optimize at a
6641 higher level than this.) */
6642 if (! STRINGP (f->name)
6643 || STRING_BYTES (XSTRING (f->name)) != len
6644 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
6645 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
6646 }
6647}
6648
6649#else /* not HAVE_WINDOW_SYSTEM */
6650
6651#define frame_title_ptr ((char *)0)
6652#define store_frame_title(str, mincol, maxcol) 0
6653
6654#endif /* not HAVE_WINDOW_SYSTEM */
6655
6656
6657
6658\f
6659/***********************************************************************
6660 Menu Bars
6661 ***********************************************************************/
6662
6663
6664/* Prepare for redisplay by updating menu-bar item lists when
6665 appropriate. This can call eval. */
6666
6667void
6668prepare_menu_bars ()
6669{
6670 int all_windows;
6671 struct gcpro gcpro1, gcpro2;
6672 struct frame *f;
6673 struct frame *tooltip_frame;
6674
6675#ifdef HAVE_X_WINDOWS
6676 tooltip_frame = tip_frame;
6677#else
6678 tooltip_frame = NULL;
6679#endif
6680
6681 /* Update all frame titles based on their buffer names, etc. We do
6682 this before the menu bars so that the buffer-menu will show the
6683 up-to-date frame titles. */
6684#ifdef HAVE_WINDOW_SYSTEM
6685 if (windows_or_buffers_changed || update_mode_lines)
6686 {
6687 Lisp_Object tail, frame;
6688
6689 FOR_EACH_FRAME (tail, frame)
6690 {
6691 f = XFRAME (frame);
6692 if (f != tooltip_frame
6693 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
6694 x_consider_frame_title (frame);
6695 }
6696 }
6697#endif /* HAVE_WINDOW_SYSTEM */
6698
6699 /* Update the menu bar item lists, if appropriate. This has to be
6700 done before any actual redisplay or generation of display lines. */
6701 all_windows = (update_mode_lines
6702 || buffer_shared > 1
6703 || windows_or_buffers_changed);
6704 if (all_windows)
6705 {
6706 Lisp_Object tail, frame;
6707 int count = specpdl_ptr - specpdl;
6708
6709 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6710
6711 FOR_EACH_FRAME (tail, frame)
6712 {
6713 f = XFRAME (frame);
6714
6715 /* Ignore tooltip frame. */
6716 if (f == tooltip_frame)
6717 continue;
6718
6719 /* If a window on this frame changed size, report that to
6720 the user and clear the size-change flag. */
6721 if (FRAME_WINDOW_SIZES_CHANGED (f))
6722 {
6723 Lisp_Object functions;
6724
6725 /* Clear flag first in case we get an error below. */
6726 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
6727 functions = Vwindow_size_change_functions;
6728 GCPRO2 (tail, functions);
6729
6730 while (CONSP (functions))
6731 {
6732 call1 (XCAR (functions), frame);
6733 functions = XCDR (functions);
6734 }
6735 UNGCPRO;
6736 }
6737
6738 GCPRO1 (tail);
6739 update_menu_bar (f, 0);
6740#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 6741 update_tool_bar (f, 0);
5f5c8ee5
GM
6742#endif
6743 UNGCPRO;
6744 }
6745
6746 unbind_to (count, Qnil);
6747 }
6748 else
6749 {
886bd6f2
GM
6750 struct frame *sf = SELECTED_FRAME ();
6751 update_menu_bar (sf, 1);
5f5c8ee5 6752#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 6753 update_tool_bar (sf, 1);
5f5c8ee5
GM
6754#endif
6755 }
6756
6757 /* Motif needs this. See comment in xmenu.c. Turn it off when
6758 pending_menu_activation is not defined. */
6759#ifdef USE_X_TOOLKIT
6760 pending_menu_activation = 0;
6761#endif
6762}
6763
6764
6765/* Update the menu bar item list for frame F. This has to be done
6766 before we start to fill in any display lines, because it can call
6767 eval.
6768
6769 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
6770
6771static void
6772update_menu_bar (f, save_match_data)
6773 struct frame *f;
6774 int save_match_data;
6775{
6776 Lisp_Object window;
6777 register struct window *w;
6778
6779 window = FRAME_SELECTED_WINDOW (f);
6780 w = XWINDOW (window);
6781
6782 if (update_mode_lines)
6783 w->update_mode_line = Qt;
6784
6785 if (FRAME_WINDOW_P (f)
6786 ?
1a578e9b 6787#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
5f5c8ee5
GM
6788 FRAME_EXTERNAL_MENU_BAR (f)
6789#else
6790 FRAME_MENU_BAR_LINES (f) > 0
6791#endif
6792 : FRAME_MENU_BAR_LINES (f) > 0)
6793 {
6794 /* If the user has switched buffers or windows, we need to
6795 recompute to reflect the new bindings. But we'll
6796 recompute when update_mode_lines is set too; that means
6797 that people can use force-mode-line-update to request
6798 that the menu bar be recomputed. The adverse effect on
6799 the rest of the redisplay algorithm is about the same as
6800 windows_or_buffers_changed anyway. */
6801 if (windows_or_buffers_changed
6802 || !NILP (w->update_mode_line)
6803 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6804 < BUF_MODIFF (XBUFFER (w->buffer)))
6805 != !NILP (w->last_had_star))
6806 || ((!NILP (Vtransient_mark_mode)
6807 && !NILP (XBUFFER (w->buffer)->mark_active))
6808 != !NILP (w->region_showing)))
6809 {
6810 struct buffer *prev = current_buffer;
6811 int count = specpdl_ptr - specpdl;
6812
6813 set_buffer_internal_1 (XBUFFER (w->buffer));
6814 if (save_match_data)
6815 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6816 if (NILP (Voverriding_local_map_menu_flag))
6817 {
6818 specbind (Qoverriding_terminal_local_map, Qnil);
6819 specbind (Qoverriding_local_map, Qnil);
6820 }
6821
6822 /* Run the Lucid hook. */
6823 call1 (Vrun_hooks, Qactivate_menubar_hook);
6824
6825 /* If it has changed current-menubar from previous value,
6826 really recompute the menu-bar from the value. */
6827 if (! NILP (Vlucid_menu_bar_dirty_flag))
6828 call0 (Qrecompute_lucid_menubar);
6829
6830 safe_run_hooks (Qmenu_bar_update_hook);
6831 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
6832
6833 /* Redisplay the menu bar in case we changed it. */
1a578e9b
AC
6834#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
6835 if (FRAME_WINDOW_P (f)
6836#if defined (macintosh)
6837 /* All frames on Mac OS share the same menubar. So only the
6838 selected frame should be allowed to set it. */
6839 && f == SELECTED_FRAME ()
6840#endif
6841 )
5f5c8ee5
GM
6842 set_frame_menubar (f, 0, 0);
6843 else
6844 /* On a terminal screen, the menu bar is an ordinary screen
6845 line, and this makes it get updated. */
6846 w->update_mode_line = Qt;
6847#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6848 /* In the non-toolkit version, the menu bar is an ordinary screen
6849 line, and this makes it get updated. */
6850 w->update_mode_line = Qt;
6851#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6852
6853 unbind_to (count, Qnil);
6854 set_buffer_internal_1 (prev);
6855 }
6856 }
6857}
6858
6859
6860\f
6861/***********************************************************************
e037b9ec 6862 Tool-bars
5f5c8ee5
GM
6863 ***********************************************************************/
6864
6865#ifdef HAVE_WINDOW_SYSTEM
6866
e037b9ec 6867/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
6868 before we start to fill in any display lines. Called from
6869 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
6870 and restore it here. */
6871
6872static void
e037b9ec 6873update_tool_bar (f, save_match_data)
5f5c8ee5
GM
6874 struct frame *f;
6875 int save_match_data;
6876{
e037b9ec
GM
6877 if (WINDOWP (f->tool_bar_window)
6878 && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
5f5c8ee5
GM
6879 {
6880 Lisp_Object window;
6881 struct window *w;
6882
6883 window = FRAME_SELECTED_WINDOW (f);
6884 w = XWINDOW (window);
6885
6886 /* If the user has switched buffers or windows, we need to
6887 recompute to reflect the new bindings. But we'll
6888 recompute when update_mode_lines is set too; that means
6889 that people can use force-mode-line-update to request
6890 that the menu bar be recomputed. The adverse effect on
6891 the rest of the redisplay algorithm is about the same as
6892 windows_or_buffers_changed anyway. */
6893 if (windows_or_buffers_changed
6894 || !NILP (w->update_mode_line)
6895 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6896 < BUF_MODIFF (XBUFFER (w->buffer)))
6897 != !NILP (w->last_had_star))
6898 || ((!NILP (Vtransient_mark_mode)
6899 && !NILP (XBUFFER (w->buffer)->mark_active))
6900 != !NILP (w->region_showing)))
6901 {
6902 struct buffer *prev = current_buffer;
6903 int count = specpdl_ptr - specpdl;
a2889657 6904
5f5c8ee5
GM
6905 /* Set current_buffer to the buffer of the selected
6906 window of the frame, so that we get the right local
6907 keymaps. */
6908 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 6909
5f5c8ee5
GM
6910 /* Save match data, if we must. */
6911 if (save_match_data)
6912 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6913
6914 /* Make sure that we don't accidentally use bogus keymaps. */
6915 if (NILP (Voverriding_local_map_menu_flag))
6916 {
6917 specbind (Qoverriding_terminal_local_map, Qnil);
6918 specbind (Qoverriding_local_map, Qnil);
1f40cad2 6919 }
1f40cad2 6920
e037b9ec
GM
6921 /* Build desired tool-bar items from keymaps. */
6922 f->desired_tool_bar_items
6923 = tool_bar_items (f->desired_tool_bar_items,
6924 &f->n_desired_tool_bar_items);
5f5c8ee5 6925
e037b9ec 6926 /* Redisplay the tool-bar in case we changed it. */
5f5c8ee5
GM
6927 w->update_mode_line = Qt;
6928
6929 unbind_to (count, Qnil);
6930 set_buffer_internal_1 (prev);
81d478f3 6931 }
a2889657
JB
6932 }
6933}
6934
6c4429a5 6935
e037b9ec
GM
6936/* Set F->desired_tool_bar_string to a Lisp string representing frame
6937 F's desired tool-bar contents. F->desired_tool_bar_items must have
5f5c8ee5
GM
6938 been set up previously by calling prepare_menu_bars. */
6939
a2889657 6940static void
e037b9ec 6941build_desired_tool_bar_string (f)
5f5c8ee5 6942 struct frame *f;
a2889657 6943{
5f5c8ee5
GM
6944 int i, size, size_needed, string_idx;
6945 struct gcpro gcpro1, gcpro2, gcpro3;
6946 Lisp_Object image, plist, props;
a2889657 6947
5f5c8ee5
GM
6948 image = plist = props = Qnil;
6949 GCPRO3 (image, plist, props);
a2889657 6950
e037b9ec 6951 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5
GM
6952 Otherwise, make a new string. */
6953
6954 /* The size of the string we might be able to reuse. */
e037b9ec
GM
6955 size = (STRINGP (f->desired_tool_bar_string)
6956 ? XSTRING (f->desired_tool_bar_string)->size
5f5c8ee5
GM
6957 : 0);
6958
6959 /* Each image in the string we build is preceded by a space,
6960 and there is a space at the end. */
e037b9ec 6961 size_needed = f->n_desired_tool_bar_items + 1;
5f5c8ee5 6962
e037b9ec 6963 /* Reuse f->desired_tool_bar_string, if possible. */
5f5c8ee5 6964 if (size < size_needed)
6fc556fd
KR
6965 f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
6966 make_number (' '));
5f5c8ee5
GM
6967 else
6968 {
6969 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
6970 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 6971 props, f->desired_tool_bar_string);
5f5c8ee5 6972 }
a2889657 6973
5f5c8ee5 6974 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
6975 put a `menu_item' property on tool-bar items with a value that
6976 is the index of the item in F's tool-bar item vector. */
5f5c8ee5 6977 for (i = 0, string_idx = 0;
e037b9ec 6978 i < f->n_desired_tool_bar_items;
5f5c8ee5 6979 ++i, string_idx += 1)
a2889657 6980 {
5f5c8ee5 6981#define PROP(IDX) \
e037b9ec
GM
6982 (XVECTOR (f->desired_tool_bar_items) \
6983 ->contents[i * TOOL_BAR_ITEM_NSLOTS + (IDX)])
5f5c8ee5 6984
e037b9ec
GM
6985 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
6986 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
37e4e482 6987 int margin, relief, idx;
5f5c8ee5
GM
6988 extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
6989 extern Lisp_Object Qlaplace;
6990
6991 /* If image is a vector, choose the image according to the
6992 button state. */
e037b9ec 6993 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
6994 if (VECTORP (image))
6995 {
5f5c8ee5
GM
6996 if (enabled_p)
6997 idx = (selected_p
e037b9ec
GM
6998 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6999 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
7000 else
7001 idx = (selected_p
e037b9ec
GM
7002 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
7003 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
5f5c8ee5 7004
37e4e482
GM
7005 xassert (ASIZE (image) >= idx);
7006 image = AREF (image, idx);
5f5c8ee5 7007 }
37e4e482
GM
7008 else
7009 idx = -1;
5f5c8ee5
GM
7010
7011 /* Ignore invalid image specifications. */
7012 if (!valid_image_p (image))
7013 continue;
7014
e037b9ec 7015 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
7016 plist = Fcopy_sequence (XCDR (image));
7017
7018 /* Compute margin and relief to draw. */
e037b9ec
GM
7019 relief = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
7020 margin = relief + max (0, tool_bar_button_margin);
5f5c8ee5 7021
e037b9ec 7022 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
7023 {
7024 /* Add a `:relief' property to the image spec if the item is
7025 selected. */
7026 if (selected_p)
7027 {
7028 plist = Fplist_put (plist, QCrelief, make_number (-relief));
7029 margin -= relief;
7030 }
7031 }
7032 else
7033 {
7034 /* If image is selected, display it pressed, i.e. with a
7035 negative relief. If it's not selected, display it with a
7036 raised relief. */
7037 plist = Fplist_put (plist, QCrelief,
7038 (selected_p
7039 ? make_number (-relief)
7040 : make_number (relief)));
7041 margin -= relief;
7042 }
7043
7044 /* Put a margin around the image. */
7045 if (margin)
7046 plist = Fplist_put (plist, QCmargin, make_number (margin));
7047
37e4e482
GM
7048 /* If button is not enabled, and we don't have special images
7049 for the disabled state, make the image appear disabled by
5f5c8ee5 7050 applying an appropriate algorithm to it. */
37e4e482
GM
7051 if (!enabled_p && idx < 0)
7052 plist = Fplist_put (plist, QCalgorithm, Qdisabled);
5f5c8ee5
GM
7053
7054 /* Put a `display' text property on the string for the image to
7055 display. Put a `menu-item' property on the string that gives
e037b9ec 7056 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
7057 vector. */
7058 image = Fcons (Qimage, plist);
7059 props = list4 (Qdisplay, image,
e037b9ec 7060 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)),
5f5c8ee5
GM
7061 Fadd_text_properties (make_number (string_idx),
7062 make_number (string_idx + 1),
e037b9ec 7063 props, f->desired_tool_bar_string);
5f5c8ee5 7064#undef PROP
a2889657
JB
7065 }
7066
5f5c8ee5
GM
7067 UNGCPRO;
7068}
7069
7070
e037b9ec 7071/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
7072
7073static void
e037b9ec 7074display_tool_bar_line (it)
5f5c8ee5
GM
7075 struct it *it;
7076{
7077 struct glyph_row *row = it->glyph_row;
7078 int max_x = it->last_visible_x;
7079 struct glyph *last;
7080
7081 prepare_desired_row (row);
7082 row->y = it->current_y;
7083
7084 while (it->current_x < max_x)
a2889657 7085 {
5f5c8ee5 7086 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 7087
5f5c8ee5
GM
7088 /* Get the next display element. */
7089 if (!get_next_display_element (it))
7090 break;
73af359d 7091
5f5c8ee5
GM
7092 /* Produce glyphs. */
7093 x_before = it->current_x;
7094 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
7095 PRODUCE_GLYPHS (it);
daa37602 7096
5f5c8ee5
GM
7097 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
7098 i = 0;
7099 x = x_before;
7100 while (i < nglyphs)
7101 {
7102 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
7103
7104 if (x + glyph->pixel_width > max_x)
7105 {
7106 /* Glyph doesn't fit on line. */
7107 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
7108 it->current_x = x;
7109 goto out;
7110 }
daa37602 7111
5f5c8ee5
GM
7112 ++it->hpos;
7113 x += glyph->pixel_width;
7114 ++i;
7115 }
7116
7117 /* Stop at line ends. */
7118 if (ITERATOR_AT_END_OF_LINE_P (it))
7119 break;
7120
cafafe0b 7121 set_iterator_to_next (it, 1);
a2889657 7122 }
a2889657 7123
5f5c8ee5 7124 out:;
a2889657 7125
5f5c8ee5
GM
7126 row->displays_text_p = row->used[TEXT_AREA] != 0;
7127 extend_face_to_end_of_line (it);
7128 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
7129 last->right_box_line_p = 1;
7130 compute_line_metrics (it);
7131
e037b9ec 7132 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
7133 if (!row->displays_text_p)
7134 {
312246d1
GM
7135 row->height = row->phys_height = it->last_visible_y - row->y;
7136 row->ascent = row->phys_ascent = 0;
5f5c8ee5
GM
7137 }
7138
7139 row->full_width_p = 1;
7140 row->continued_p = 0;
7141 row->truncated_on_left_p = 0;
7142 row->truncated_on_right_p = 0;
7143
7144 it->current_x = it->hpos = 0;
7145 it->current_y += row->height;
7146 ++it->vpos;
7147 ++it->glyph_row;
a2889657 7148}
96a410bc 7149
5f5c8ee5 7150
e037b9ec 7151/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 7152 items of frame F visible. */
96a410bc 7153
d39b6696 7154static int
e037b9ec 7155tool_bar_lines_needed (f)
5f5c8ee5 7156 struct frame *f;
d39b6696 7157{
e037b9ec 7158 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5
GM
7159 struct it it;
7160
e037b9ec
GM
7161 /* Initialize an iterator for iteration over
7162 F->desired_tool_bar_string in the tool-bar window of frame F. */
7163 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
7164 it.first_visible_x = 0;
7165 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
e037b9ec 7166 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
7167
7168 while (!ITERATOR_AT_END_P (&it))
7169 {
7170 it.glyph_row = w->desired_matrix->rows;
7171 clear_glyph_row (it.glyph_row);
e037b9ec 7172 display_tool_bar_line (&it);
5f5c8ee5
GM
7173 }
7174
7175 return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
d39b6696 7176}
96a410bc 7177
5f5c8ee5 7178
e037b9ec 7179/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
7180 height should be changed. */
7181
7182static int
e037b9ec 7183redisplay_tool_bar (f)
5f5c8ee5 7184 struct frame *f;
96a410bc 7185{
5f5c8ee5
GM
7186 struct window *w;
7187 struct it it;
7188 struct glyph_row *row;
7189 int change_height_p = 0;
7190
e037b9ec
GM
7191 /* If frame hasn't a tool-bar window or if it is zero-height, don't
7192 do anything. This means you must start with tool-bar-lines
5f5c8ee5 7193 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
7194 can turn off tool-bars by specifying tool-bar-lines zero. */
7195 if (!WINDOWP (f->tool_bar_window)
7196 || (w = XWINDOW (f->tool_bar_window),
5f5c8ee5
GM
7197 XFASTINT (w->height) == 0))
7198 return 0;
96a410bc 7199
e037b9ec
GM
7200 /* Set up an iterator for the tool-bar window. */
7201 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
7202 it.first_visible_x = 0;
7203 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
7204 row = it.glyph_row;
3450d04c 7205
e037b9ec
GM
7206 /* Build a string that represents the contents of the tool-bar. */
7207 build_desired_tool_bar_string (f);
7208 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 7209
e037b9ec 7210 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 7211 while (it.current_y < it.last_visible_y)
e037b9ec 7212 display_tool_bar_line (&it);
3450d04c 7213
e037b9ec 7214 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
7215 window, so don't do it. */
7216 w->desired_matrix->no_scrolling_p = 1;
7217 w->must_be_updated_p = 1;
3450d04c 7218
e037b9ec 7219 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
7220 {
7221 int nlines;
7222
7223 /* If there are blank lines at the end, except for a partially
7224 visible blank line at the end that is smaller than
e037b9ec 7225 CANON_Y_UNIT, change the tool-bar's height. */
5f5c8ee5
GM
7226 row = it.glyph_row - 1;
7227 if (!row->displays_text_p
7228 && row->height >= CANON_Y_UNIT (f))
7229 change_height_p = 1;
7230
e037b9ec
GM
7231 /* If row displays tool-bar items, but is partially visible,
7232 change the tool-bar's height. */
5f5c8ee5
GM
7233 if (row->displays_text_p
7234 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
7235 change_height_p = 1;
7236
e037b9ec 7237 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
7238 frame parameter. */
7239 if (change_height_p
e037b9ec 7240 && (nlines = tool_bar_lines_needed (f),
5f5c8ee5
GM
7241 nlines != XFASTINT (w->height)))
7242 {
e037b9ec 7243 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5
GM
7244 Lisp_Object frame;
7245
7246 XSETFRAME (frame, f);
7247 clear_glyph_matrix (w->desired_matrix);
7248 Fmodify_frame_parameters (frame,
e037b9ec 7249 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
7250 make_number (nlines)),
7251 Qnil));
7252 fonts_changed_p = 1;
7253 }
7254 }
3450d04c 7255
5f5c8ee5 7256 return change_height_p;
96a410bc 7257}
90adcf20 7258
5f5c8ee5 7259
e037b9ec
GM
7260/* Get information about the tool-bar item which is displayed in GLYPH
7261 on frame F. Return in *PROP_IDX the index where tool-bar item
7262 properties start in F->current_tool_bar_items. Value is zero if
7263 GLYPH doesn't display a tool-bar item. */
5f5c8ee5
GM
7264
7265int
e037b9ec 7266tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
7267 struct frame *f;
7268 struct glyph *glyph;
7269 int *prop_idx;
90adcf20 7270{
5f5c8ee5
GM
7271 Lisp_Object prop;
7272 int success_p;
7273
7274 /* Get the text property `menu-item' at pos. The value of that
7275 property is the start index of this item's properties in
e037b9ec 7276 F->current_tool_bar_items. */
5f5c8ee5 7277 prop = Fget_text_property (make_number (glyph->charpos),
e037b9ec 7278 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
7279 if (INTEGERP (prop))
7280 {
7281 *prop_idx = XINT (prop);
7282 success_p = 1;
7283 }
7284 else
7285 success_p = 0;
90adcf20 7286
5f5c8ee5
GM
7287 return success_p;
7288}
7289
7290#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 7291
feb0c42f 7292
5f5c8ee5
GM
7293\f
7294/************************************************************************
7295 Horizontal scrolling
7296 ************************************************************************/
feb0c42f 7297
5f5c8ee5
GM
7298static int hscroll_window_tree P_ ((Lisp_Object));
7299static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 7300
5f5c8ee5
GM
7301/* For all leaf windows in the window tree rooted at WINDOW, set their
7302 hscroll value so that PT is (i) visible in the window, and (ii) so
7303 that it is not within a certain margin at the window's left and
7304 right border. Value is non-zero if any window's hscroll has been
7305 changed. */
7306
7307static int
7308hscroll_window_tree (window)
7309 Lisp_Object window;
7310{
7311 int hscrolled_p = 0;
7312
7313 while (WINDOWP (window))
90adcf20 7314 {
5f5c8ee5
GM
7315 struct window *w = XWINDOW (window);
7316
7317 if (WINDOWP (w->hchild))
7318 hscrolled_p |= hscroll_window_tree (w->hchild);
7319 else if (WINDOWP (w->vchild))
7320 hscrolled_p |= hscroll_window_tree (w->vchild);
7321 else if (w->cursor.vpos >= 0)
7322 {
7323 int hscroll_margin, text_area_x, text_area_y;
7324 int text_area_width, text_area_height;
92a90e89
GM
7325 struct glyph_row *current_cursor_row
7326 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
7327 struct glyph_row *desired_cursor_row
7328 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
7329 struct glyph_row *cursor_row
7330 = (desired_cursor_row->enabled_p
7331 ? desired_cursor_row
7332 : current_cursor_row);
a2725ab2 7333
5f5c8ee5
GM
7334 window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
7335 &text_area_width, &text_area_height);
90adcf20 7336
5f5c8ee5
GM
7337 /* Scroll when cursor is inside this scroll margin. */
7338 hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
7339
7340 if ((XFASTINT (w->hscroll)
7341 && w->cursor.x < hscroll_margin)
92a90e89
GM
7342 || (cursor_row->enabled_p
7343 && cursor_row->truncated_on_right_p
5f5c8ee5 7344 && (w->cursor.x > text_area_width - hscroll_margin)))
08b610e4 7345 {
5f5c8ee5
GM
7346 struct it it;
7347 int hscroll;
7348 struct buffer *saved_current_buffer;
7349 int pt;
7350
7351 /* Find point in a display of infinite width. */
7352 saved_current_buffer = current_buffer;
7353 current_buffer = XBUFFER (w->buffer);
7354
7355 if (w == XWINDOW (selected_window))
7356 pt = BUF_PT (current_buffer);
7357 else
08b610e4 7358 {
5f5c8ee5
GM
7359 pt = marker_position (w->pointm);
7360 pt = max (BEGV, pt);
7361 pt = min (ZV, pt);
7362 }
7363
7364 /* Move iterator to pt starting at cursor_row->start in
7365 a line with infinite width. */
7366 init_to_row_start (&it, w, cursor_row);
7367 it.last_visible_x = INFINITY;
7368 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
7369 current_buffer = saved_current_buffer;
7370
7371 /* Center cursor in window. */
7372 hscroll = (max (0, it.current_x - text_area_width / 2)
7373 / CANON_X_UNIT (it.f));
7374
7375 /* Don't call Fset_window_hscroll if value hasn't
7376 changed because it will prevent redisplay
7377 optimizations. */
7378 if (XFASTINT (w->hscroll) != hscroll)
7379 {
7380 Fset_window_hscroll (window, make_number (hscroll));
7381 hscrolled_p = 1;
08b610e4 7382 }
08b610e4 7383 }
08b610e4 7384 }
a2725ab2 7385
5f5c8ee5 7386 window = w->next;
90adcf20 7387 }
cd6dfed6 7388
5f5c8ee5
GM
7389 /* Value is non-zero if hscroll of any leaf window has been changed. */
7390 return hscrolled_p;
7391}
7392
7393
7394/* Set hscroll so that cursor is visible and not inside horizontal
7395 scroll margins for all windows in the tree rooted at WINDOW. See
7396 also hscroll_window_tree above. Value is non-zero if any window's
7397 hscroll has been changed. If it has, desired matrices on the frame
7398 of WINDOW are cleared. */
7399
7400static int
7401hscroll_windows (window)
7402 Lisp_Object window;
7403{
d475bcb8
GM
7404 int hscrolled_p;
7405
7406 if (automatic_hscrolling_p)
7407 {
7408 hscrolled_p = hscroll_window_tree (window);
7409 if (hscrolled_p)
7410 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
7411 }
7412 else
7413 hscrolled_p = 0;
5f5c8ee5 7414 return hscrolled_p;
90adcf20 7415}
5f5c8ee5
GM
7416
7417
90adcf20 7418\f
5f5c8ee5
GM
7419/************************************************************************
7420 Redisplay
7421 ************************************************************************/
7422
7423/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
7424 to a non-zero value. This is sometimes handy to have in a debugger
7425 session. */
7426
7427#if GLYPH_DEBUG
a2889657 7428
5f5c8ee5
GM
7429/* First and last unchanged row for try_window_id. */
7430
7431int debug_first_unchanged_at_end_vpos;
7432int debug_last_unchanged_at_beg_vpos;
7433
7434/* Delta vpos and y. */
7435
7436int debug_dvpos, debug_dy;
7437
7438/* Delta in characters and bytes for try_window_id. */
7439
7440int debug_delta, debug_delta_bytes;
7441
7442/* Values of window_end_pos and window_end_vpos at the end of
7443 try_window_id. */
7444
7445int debug_end_pos, debug_end_vpos;
7446
7447/* Append a string to W->desired_matrix->method. FMT is a printf
7448 format string. A1...A9 are a supplement for a variable-length
7449 argument list. If trace_redisplay_p is non-zero also printf the
7450 resulting string to stderr. */
7451
7452static void
7453debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
7454 struct window *w;
7455 char *fmt;
7456 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
7457{
7458 char buffer[512];
7459 char *method = w->desired_matrix->method;
7460 int len = strlen (method);
7461 int size = sizeof w->desired_matrix->method;
7462 int remaining = size - len - 1;
7463
7464 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
7465 if (len && remaining)
7466 {
7467 method[len] = '|';
7468 --remaining, ++len;
7469 }
7470
7471 strncpy (method + len, buffer, remaining);
7472
7473 if (trace_redisplay_p)
7474 fprintf (stderr, "%p (%s): %s\n",
7475 w,
7476 ((BUFFERP (w->buffer)
7477 && STRINGP (XBUFFER (w->buffer)->name))
7478 ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
7479 : "no buffer"),
7480 buffer);
7481}
a2889657 7482
5f5c8ee5 7483#endif /* GLYPH_DEBUG */
90adcf20 7484
a2889657 7485
5f5c8ee5
GM
7486/* This counter is used to clear the face cache every once in a while
7487 in redisplay_internal. It is incremented for each redisplay.
7488 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
7489 cleared. */
0d231165 7490
5f5c8ee5 7491#define CLEAR_FACE_CACHE_COUNT 10000
463f6b91
RS
7492static int clear_face_cache_count;
7493
20de20dc 7494/* Record the previous terminal frame we displayed. */
5f5c8ee5
GM
7495
7496static struct frame *previous_terminal_frame;
7497
7498/* Non-zero while redisplay_internal is in progress. */
7499
7500int redisplaying_p;
7501
7502
7503/* Value is non-zero if all changes in window W, which displays
7504 current_buffer, are in the text between START and END. START is a
7505 buffer position, END is given as a distance from Z. Used in
7506 redisplay_internal for display optimization. */
7507
7508static INLINE int
7509text_outside_line_unchanged_p (w, start, end)
7510 struct window *w;
7511 int start, end;
7512{
7513 int unchanged_p = 1;
7514
7515 /* If text or overlays have changed, see where. */
7516 if (XFASTINT (w->last_modified) < MODIFF
7517 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
7518 {
7519 /* Gap in the line? */
7520 if (GPT < start || Z - GPT < end)
7521 unchanged_p = 0;
7522
7523 /* Changes start in front of the line, or end after it? */
7524 if (unchanged_p
9142dd5b
GM
7525 && (BEG_UNCHANGED < start - 1
7526 || END_UNCHANGED < end))
5f5c8ee5
GM
7527 unchanged_p = 0;
7528
7529 /* If selective display, can't optimize if changes start at the
7530 beginning of the line. */
7531 if (unchanged_p
7532 && INTEGERP (current_buffer->selective_display)
7533 && XINT (current_buffer->selective_display) > 0
9142dd5b 7534 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5
GM
7535 unchanged_p = 0;
7536 }
7537
7538 return unchanged_p;
7539}
7540
7541
7542/* Do a frame update, taking possible shortcuts into account. This is
7543 the main external entry point for redisplay.
7544
7545 If the last redisplay displayed an echo area message and that message
7546 is no longer requested, we clear the echo area or bring back the
7547 mini-buffer if that is in use. */
20de20dc 7548
a2889657
JB
7549void
7550redisplay ()
e9874cee
RS
7551{
7552 redisplay_internal (0);
7553}
7554
260a86a0
KH
7555/* Return 1 if point moved out of or into a composition. Otherwise
7556 return 0. PREV_BUF and PREV_PT are the last point buffer and
7557 position. BUF and PT are the current point buffer and position. */
7558
7559int
7560check_point_in_composition (prev_buf, prev_pt, buf, pt)
7561 struct buffer *prev_buf, *buf;
7562 int prev_pt, pt;
7563{
7564 int start, end;
7565 Lisp_Object prop;
7566 Lisp_Object buffer;
7567
7568 XSETBUFFER (buffer, buf);
7569 /* Check a composition at the last point if point moved within the
7570 same buffer. */
7571 if (prev_buf == buf)
7572 {
7573 if (prev_pt == pt)
7574 /* Point didn't move. */
7575 return 0;
7576
7577 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
7578 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
7579 && COMPOSITION_VALID_P (start, end, prop)
7580 && start < prev_pt && end > prev_pt)
7581 /* The last point was within the composition. Return 1 iff
7582 point moved out of the composition. */
7583 return (pt <= start || pt >= end);
7584 }
7585
7586 /* Check a composition at the current point. */
7587 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
7588 && find_composition (pt, -1, &start, &end, &prop, buffer)
7589 && COMPOSITION_VALID_P (start, end, prop)
7590 && start < pt && end > pt);
7591}
5f5c8ee5 7592
9142dd5b
GM
7593/* Reconsider the setting of B->clip_changed which is displayed
7594 in window W. */
7595
7596static INLINE void
7597reconsider_clip_changes (w, b)
7598 struct window *w;
7599 struct buffer *b;
7600{
7601 if (b->prevent_redisplay_optimizations_p)
7602 b->clip_changed = 1;
7603 else if (b->clip_changed
7604 && !NILP (w->window_end_valid)
7605 && w->current_matrix->buffer == b
7606 && w->current_matrix->zv == BUF_ZV (b)
7607 && w->current_matrix->begv == BUF_BEGV (b))
7608 b->clip_changed = 0;
260a86a0
KH
7609
7610 /* If display wasn't paused, and W is not a tool bar window, see if
7611 point has been moved into or out of a composition. In that case,
7612 we set b->clip_changed to 1 to force updating the screen. If
7613 b->clip_changed has already been set to 1, we can skip this
7614 check. */
7615 if (!b->clip_changed
7616 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
7617 {
7618 int pt;
7619
7620 if (w == XWINDOW (selected_window))
7621 pt = BUF_PT (current_buffer);
7622 else
7623 pt = marker_position (w->pointm);
7624
7625 if ((w->current_matrix->buffer != XBUFFER (w->buffer)
6fc556fd 7626 || pt != XINT (w->last_point))
260a86a0 7627 && check_point_in_composition (w->current_matrix->buffer,
6fc556fd 7628 XINT (w->last_point),
260a86a0
KH
7629 XBUFFER (w->buffer), pt))
7630 b->clip_changed = 1;
7631 }
9142dd5b
GM
7632}
7633
7634
5f5c8ee5
GM
7635/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
7636 response to any user action; therefore, we should preserve the echo
7637 area. (Actually, our caller does that job.) Perhaps in the future
7638 avoid recentering windows if it is not necessary; currently that
7639 causes some problems. */
e9874cee
RS
7640
7641static void
7642redisplay_internal (preserve_echo_area)
7643 int preserve_echo_area;
a2889657 7644{
5f5c8ee5
GM
7645 struct window *w = XWINDOW (selected_window);
7646 struct frame *f = XFRAME (w->frame);
7647 int pause;
a2889657 7648 int must_finish = 0;
5f5c8ee5 7649 struct text_pos tlbufpos, tlendpos;
89819bdd 7650 int number_of_visible_frames;
28514cd9 7651 int count;
886bd6f2 7652 struct frame *sf = SELECTED_FRAME ();
a2889657 7653
5f5c8ee5
GM
7654 /* Non-zero means redisplay has to consider all windows on all
7655 frames. Zero means, only selected_window is considered. */
7656 int consider_all_windows_p;
7657
7658 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
7659
7660 /* No redisplay if running in batch mode or frame is not yet fully
7661 initialized, or redisplay is explicitly turned off by setting
7662 Vinhibit_redisplay. */
7663 if (noninteractive
7664 || !NILP (Vinhibit_redisplay)
7665 || !f->glyphs_initialized_p)
a2889657
JB
7666 return;
7667
5f5c8ee5
GM
7668 /* The flag redisplay_performed_directly_p is set by
7669 direct_output_for_insert when it already did the whole screen
7670 update necessary. */
7671 if (redisplay_performed_directly_p)
7672 {
7673 redisplay_performed_directly_p = 0;
7674 if (!hscroll_windows (selected_window))
7675 return;
7676 }
7677
15f0cf78
RS
7678#ifdef USE_X_TOOLKIT
7679 if (popup_activated ())
7680 return;
7681#endif
7682
28514cd9 7683 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 7684 if (redisplaying_p)
735c094c
KH
7685 return;
7686
28514cd9
GM
7687 /* Record a function that resets redisplaying_p to its old value
7688 when we leave this function. */
7689 count = specpdl_ptr - specpdl;
7690 record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
7691 ++redisplaying_p;
7692
8b32d885 7693 retry:
bd9d0f3f 7694 pause = 0;
9142dd5b
GM
7695 reconsider_clip_changes (w, current_buffer);
7696
5f5c8ee5
GM
7697 /* If new fonts have been loaded that make a glyph matrix adjustment
7698 necessary, do it. */
7699 if (fonts_changed_p)
7700 {
7701 adjust_glyphs (NULL);
7702 ++windows_or_buffers_changed;
7703 fonts_changed_p = 0;
7704 }
7705
886bd6f2
GM
7706 if (! FRAME_WINDOW_P (sf)
7707 && previous_terminal_frame != sf)
20de20dc 7708 {
5f5c8ee5
GM
7709 /* Since frames on an ASCII terminal share the same display
7710 area, displaying a different frame means redisplay the whole
7711 thing. */
20de20dc 7712 windows_or_buffers_changed++;
886bd6f2
GM
7713 SET_FRAME_GARBAGED (sf);
7714 XSETFRAME (Vterminal_frame, sf);
20de20dc 7715 }
886bd6f2 7716 previous_terminal_frame = sf;
20de20dc 7717
5f5c8ee5
GM
7718 /* Set the visible flags for all frames. Do this before checking
7719 for resized or garbaged frames; they want to know if their frames
7720 are visible. See the comment in frame.h for
7721 FRAME_SAMPLE_VISIBILITY. */
d724d989 7722 {
35f56f96 7723 Lisp_Object tail, frame;
d724d989 7724
89819bdd
RS
7725 number_of_visible_frames = 0;
7726
35f56f96 7727 FOR_EACH_FRAME (tail, frame)
f82aff7c 7728 {
5f5c8ee5
GM
7729 struct frame *f = XFRAME (frame);
7730
7731 FRAME_SAMPLE_VISIBILITY (f);
7732 if (FRAME_VISIBLE_P (f))
7733 ++number_of_visible_frames;
7734 clear_desired_matrices (f);
f82aff7c 7735 }
d724d989
JB
7736 }
7737
44fa5b1e 7738 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 7739 do_pending_window_change (1);
a2889657 7740
5f5c8ee5 7741 /* Clear frames marked as garbaged. */
44fa5b1e 7742 if (frame_garbaged)
c6e89d6c 7743 clear_garbaged_frames ();
a2889657 7744
e037b9ec 7745 /* Build menubar and tool-bar items. */
f82aff7c
RS
7746 prepare_menu_bars ();
7747
28995e67 7748 if (windows_or_buffers_changed)
a2889657
JB
7749 update_mode_lines++;
7750
538f13d4
RS
7751 /* Detect case that we need to write or remove a star in the mode line. */
7752 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
7753 {
7754 w->update_mode_line = Qt;
7755 if (buffer_shared > 1)
7756 update_mode_lines++;
7757 }
7758
5f5c8ee5 7759 /* If %c is in the mode line, update it if needed. */
28995e67
RS
7760 if (!NILP (w->column_number_displayed)
7761 /* This alternative quickly identifies a common case
7762 where no change is needed. */
7763 && !(PT == XFASTINT (w->last_point)
8850a573
RS
7764 && XFASTINT (w->last_modified) >= MODIFF
7765 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
7766 && XFASTINT (w->column_number_displayed) != current_column ())
7767 w->update_mode_line = Qt;
7768
44fa5b1e 7769 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 7770
5f5c8ee5
GM
7771 /* The variable buffer_shared is set in redisplay_window and
7772 indicates that we redisplay a buffer in different windows. See
7773 there. */
7774 consider_all_windows_p = update_mode_lines || buffer_shared > 1;
a2889657
JB
7775
7776 /* If specs for an arrow have changed, do thorough redisplay
7777 to ensure we remove any arrow that should no longer exist. */
d45de95b 7778 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 7779 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 7780 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 7781
90adcf20
RS
7782 /* Normally the message* functions will have already displayed and
7783 updated the echo area, but the frame may have been trashed, or
7784 the update may have been preempted, so display the echo area
c6e89d6c
GM
7785 again here. Checking both message buffers captures the case that
7786 the echo area should be cleared. */
7787 if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
90adcf20 7788 {
c6e89d6c 7789 int window_height_changed_p = echo_area_display (0);
90adcf20 7790 must_finish = 1;
dd2eb166 7791
c6e89d6c
GM
7792 if (fonts_changed_p)
7793 goto retry;
7794 else if (window_height_changed_p)
7795 {
7796 consider_all_windows_p = 1;
7797 ++update_mode_lines;
7798 ++windows_or_buffers_changed;
9142dd5b
GM
7799
7800 /* If window configuration was changed, frames may have been
7801 marked garbaged. Clear them or we will experience
7802 surprises wrt scrolling. */
7803 if (frame_garbaged)
7804 clear_garbaged_frames ();
c6e89d6c 7805 }
90adcf20 7806 }
97a36635 7807 else if (EQ (selected_window, minibuf_window)
dd2eb166
GM
7808 && (current_buffer->clip_changed
7809 || XFASTINT (w->last_modified) < MODIFF
7810 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 7811 && resize_mini_window (w, 0))
c6e89d6c
GM
7812 {
7813 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
7814 showing if its contents might have changed. */
7815 must_finish = 1;
7816 consider_all_windows_p = 1;
c6e89d6c 7817 ++windows_or_buffers_changed;
dd2eb166 7818 ++update_mode_lines;
9142dd5b
GM
7819
7820 /* If window configuration was changed, frames may have been
7821 marked garbaged. Clear them or we will experience
7822 surprises wrt scrolling. */
7823 if (frame_garbaged)
7824 clear_garbaged_frames ();
c6e89d6c
GM
7825 }
7826
90adcf20 7827
5f5c8ee5
GM
7828 /* If showing the region, and mark has changed, we must redisplay
7829 the whole window. The assignment to this_line_start_pos prevents
7830 the optimization directly below this if-statement. */
bd66d1ba
RS
7831 if (((!NILP (Vtransient_mark_mode)
7832 && !NILP (XBUFFER (w->buffer)->mark_active))
7833 != !NILP (w->region_showing))
82d04750
JB
7834 || (!NILP (w->region_showing)
7835 && !EQ (w->region_showing,
7836 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
7837 CHARPOS (this_line_start_pos) = 0;
7838
7839 /* Optimize the case that only the line containing the cursor in the
7840 selected window has changed. Variables starting with this_ are
7841 set in display_line and record information about the line
7842 containing the cursor. */
7843 tlbufpos = this_line_start_pos;
7844 tlendpos = this_line_end_pos;
7845 if (!consider_all_windows_p
7846 && CHARPOS (tlbufpos) > 0
7847 && NILP (w->update_mode_line)
73af359d 7848 && !current_buffer->clip_changed
44fa5b1e 7849 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 7850 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 7851 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
7852 && this_line_buffer == current_buffer
7853 && current_buffer == XBUFFER (w->buffer)
265a9e55 7854 && NILP (w->force_start)
5f5c8ee5
GM
7855 /* Point must be on the line that we have info recorded about. */
7856 && PT >= CHARPOS (tlbufpos)
7857 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
7858 /* All text outside that line, including its final newline,
7859 must be unchanged */
5f5c8ee5
GM
7860 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
7861 CHARPOS (tlendpos)))
7862 {
7863 if (CHARPOS (tlbufpos) > BEGV
7864 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
7865 && (CHARPOS (tlbufpos) == ZV
7866 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
7867 /* Former continuation line has disappeared by becoming empty */
7868 goto cancel;
7869 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 7870 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
7871 || MINI_WINDOW_P (w))
7872 {
1c9241f5
KH
7873 /* We have to handle the case of continuation around a
7874 wide-column character (See the comment in indent.c around
7875 line 885).
7876
7877 For instance, in the following case:
7878
7879 -------- Insert --------
7880 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
7881 J_I_ ==> J_I_ `^^' are cursors.
7882 ^^ ^^
7883 -------- --------
7884
7885 As we have to redraw the line above, we should goto cancel. */
7886
5f5c8ee5
GM
7887 struct it it;
7888 int line_height_before = this_line_pixel_height;
7889
7890 /* Note that start_display will handle the case that the
7891 line starting at tlbufpos is a continuation lines. */
7892 start_display (&it, w, tlbufpos);
7893
7894 /* Implementation note: It this still necessary? */
7895 if (it.current_x != this_line_start_x)
1c9241f5
KH
7896 goto cancel;
7897
5f5c8ee5
GM
7898 TRACE ((stderr, "trying display optimization 1\n"));
7899 w->cursor.vpos = -1;
a2889657 7900 overlay_arrow_seen = 0;
5f5c8ee5
GM
7901 it.vpos = this_line_vpos;
7902 it.current_y = this_line_y;
7903 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
7904 display_line (&it);
7905
a2889657 7906 /* If line contains point, is not continued,
5f5c8ee5
GM
7907 and ends at same distance from eob as before, we win */
7908 if (w->cursor.vpos >= 0
7909 /* Line is not continued, otherwise this_line_start_pos
7910 would have been set to 0 in display_line. */
7911 && CHARPOS (this_line_start_pos)
7912 /* Line ends as before. */
7913 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
7914 /* Line has same height as before. Otherwise other lines
7915 would have to be shifted up or down. */
7916 && this_line_pixel_height == line_height_before)
a2889657 7917 {
5f5c8ee5
GM
7918 /* If this is not the window's last line, we must adjust
7919 the charstarts of the lines below. */
7920 if (it.current_y < it.last_visible_y)
7921 {
7922 struct glyph_row *row
7923 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
7924 int delta, delta_bytes;
7925
7926 if (Z - CHARPOS (tlendpos) == ZV)
7927 {
7928 /* This line ends at end of (accessible part of)
7929 buffer. There is no newline to count. */
7930 delta = (Z
7931 - CHARPOS (tlendpos)
7932 - MATRIX_ROW_START_CHARPOS (row));
7933 delta_bytes = (Z_BYTE
7934 - BYTEPOS (tlendpos)
7935 - MATRIX_ROW_START_BYTEPOS (row));
7936 }
7937 else
7938 {
7939 /* This line ends in a newline. Must take
7940 account of the newline and the rest of the
7941 text that follows. */
7942 delta = (Z
7943 - CHARPOS (tlendpos)
7944 - MATRIX_ROW_START_CHARPOS (row));
7945 delta_bytes = (Z_BYTE
7946 - BYTEPOS (tlendpos)
7947 - MATRIX_ROW_START_BYTEPOS (row));
7948 }
7949
f2d86d7a
GM
7950 increment_matrix_positions (w->current_matrix,
7951 this_line_vpos + 1,
7952 w->current_matrix->nrows,
7953 delta, delta_bytes);
85bcef6c 7954 }
46db8486 7955
5f5c8ee5
GM
7956 /* If this row displays text now but previously didn't,
7957 or vice versa, w->window_end_vpos may have to be
7958 adjusted. */
7959 if ((it.glyph_row - 1)->displays_text_p)
7960 {
7961 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
7962 XSETINT (w->window_end_vpos, this_line_vpos);
7963 }
7964 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
7965 && this_line_vpos > 0)
7966 XSETINT (w->window_end_vpos, this_line_vpos - 1);
7967 w->window_end_valid = Qnil;
7968
7969 /* Update hint: No need to try to scroll in update_window. */
7970 w->desired_matrix->no_scrolling_p = 1;
7971
7972#if GLYPH_DEBUG
7973 *w->desired_matrix->method = 0;
7974 debug_method_add (w, "optimization 1");
7975#endif
a2889657
JB
7976 goto update;
7977 }
7978 else
7979 goto cancel;
7980 }
5f5c8ee5
GM
7981 else if (/* Cursor position hasn't changed. */
7982 PT == XFASTINT (w->last_point)
b6f0fe04
RS
7983 /* Make sure the cursor was last displayed
7984 in this window. Otherwise we have to reposition it. */
5f5c8ee5
GM
7985 && 0 <= w->cursor.vpos
7986 && XINT (w->height) > w->cursor.vpos)
a2889657
JB
7987 {
7988 if (!must_finish)
7989 {
c6e89d6c 7990 do_pending_window_change (1);
5f5c8ee5
GM
7991
7992 /* We used to always goto end_of_redisplay here, but this
7993 isn't enough if we have a blinking cursor. */
7994 if (w->cursor_off_p == w->last_cursor_off_p)
7995 goto end_of_redisplay;
a2889657
JB
7996 }
7997 goto update;
7998 }
8b51f1e3
KH
7999 /* If highlighting the region, or if the cursor is in the echo area,
8000 then we can't just move the cursor. */
bd66d1ba
RS
8001 else if (! (!NILP (Vtransient_mark_mode)
8002 && !NILP (current_buffer->mark_active))
97a36635 8003 && (EQ (selected_window, current_buffer->last_selected_window)
293a54ce 8004 || highlight_nonselected_windows)
8b51f1e3 8005 && NILP (w->region_showing)
8f897821 8006 && NILP (Vshow_trailing_whitespace)
8b51f1e3 8007 && !cursor_in_echo_area)
a2889657 8008 {
5f5c8ee5
GM
8009 struct it it;
8010 struct glyph_row *row;
8011
8012 /* Skip from tlbufpos to PT and see where it is. Note that
8013 PT may be in invisible text. If so, we will end at the
8014 next visible position. */
8015 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
8016 NULL, DEFAULT_FACE_ID);
8017 it.current_x = this_line_start_x;
8018 it.current_y = this_line_y;
8019 it.vpos = this_line_vpos;
8020
8021 /* The call to move_it_to stops in front of PT, but
8022 moves over before-strings. */
8023 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
8024
8025 if (it.vpos == this_line_vpos
8026 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
8027 row->enabled_p))
a2889657 8028 {
5f5c8ee5
GM
8029 xassert (this_line_vpos == it.vpos);
8030 xassert (this_line_y == it.current_y);
8031 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
a2889657
JB
8032 goto update;
8033 }
8034 else
8035 goto cancel;
8036 }
5f5c8ee5 8037
a2889657 8038 cancel:
5f5c8ee5
GM
8039 /* Text changed drastically or point moved off of line. */
8040 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
8041 }
8042
5f5c8ee5
GM
8043 CHARPOS (this_line_start_pos) = 0;
8044 consider_all_windows_p |= buffer_shared > 1;
8045 ++clear_face_cache_count;
a2889657 8046
5f5c8ee5 8047
bd9d0f3f
GM
8048 /* Build desired matrices, and update the display. If
8049 consider_all_windows_p is non-zero, do it for all windows on all
8050 frames. Otherwise do it for selected_window, only. */
463f6b91 8051
5f5c8ee5 8052 if (consider_all_windows_p)
a2889657 8053 {
35f56f96 8054 Lisp_Object tail, frame;
a2889657 8055
5f5c8ee5
GM
8056 /* Clear the face cache eventually. */
8057 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 8058 {
5f5c8ee5 8059 clear_face_cache (0);
463f6b91
RS
8060 clear_face_cache_count = 0;
8061 }
31b24551 8062
5f5c8ee5
GM
8063 /* Recompute # windows showing selected buffer. This will be
8064 incremented each time such a window is displayed. */
a2889657
JB
8065 buffer_shared = 0;
8066
35f56f96 8067 FOR_EACH_FRAME (tail, frame)
30c566e4 8068 {
5f5c8ee5 8069 struct frame *f = XFRAME (frame);
bd9d0f3f 8070
886bd6f2 8071 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 8072 {
5f5c8ee5
GM
8073 /* Mark all the scroll bars to be removed; we'll redeem
8074 the ones we want when we redisplay their windows. */
9769686d
RS
8075 if (condemn_scroll_bars_hook)
8076 (*condemn_scroll_bars_hook) (f);
30c566e4 8077
f21ef775 8078 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 8079 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 8080
5f5c8ee5
GM
8081 /* Any scroll bars which redisplay_windows should have
8082 nuked should now go away. */
9769686d
RS
8083 if (judge_scroll_bars_hook)
8084 (*judge_scroll_bars_hook) (f);
bd9d0f3f
GM
8085
8086 /* If fonts changed, display again. */
8087 if (fonts_changed_p)
8088 goto retry;
8089
8090 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
8091 {
8092 /* See if we have to hscroll. */
8093 if (hscroll_windows (f->root_window))
8094 goto retry;
8095
8096 /* Prevent various kinds of signals during display
8097 update. stdio is not robust about handling
8098 signals, which can cause an apparent I/O
8099 error. */
8100 if (interrupt_input)
8101 unrequest_sigio ();
8102 stop_polling ();
8103
8104 /* Update the display. */
8105 set_window_update_flags (XWINDOW (f->root_window), 1);
8106 pause |= update_frame (f, 0, 0);
8107 if (pause)
8108 break;
8109
8110 mark_window_display_accurate (f->root_window, 1);
8111 if (frame_up_to_date_hook)
8112 frame_up_to_date_hook (f);
8113 }
9769686d 8114 }
30c566e4 8115 }
a2889657 8116 }
bd9d0f3f
GM
8117 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
8118 {
8119 Lisp_Object mini_window;
8120 struct frame *mini_frame;
5f5c8ee5 8121
bd9d0f3f 8122 redisplay_window (selected_window, 1);
5f5c8ee5 8123
bd9d0f3f
GM
8124 /* Compare desired and current matrices, perform output. */
8125 update:
5f5c8ee5 8126
bd9d0f3f
GM
8127 /* If fonts changed, display again. */
8128 if (fonts_changed_p)
92a90e89 8129 goto retry;
a2889657 8130
bd9d0f3f
GM
8131 /* Prevent various kinds of signals during display update.
8132 stdio is not robust about handling signals,
8133 which can cause an apparent I/O error. */
8134 if (interrupt_input)
8135 unrequest_sigio ();
8136 stop_polling ();
1af9f229 8137
bd9d0f3f 8138 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
5f5c8ee5 8139 {
92a90e89
GM
8140 if (hscroll_windows (selected_window))
8141 goto retry;
8142
5f5c8ee5 8143 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 8144 pause = update_frame (sf, 0, 0);
5f5c8ee5 8145 }
d724d989 8146
8de2d90b 8147 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
8148 function. If the echo area is on another frame, that may
8149 have put text on a frame other than the selected one, so the
8150 above call to update_frame would not have caught it. Catch
8de2d90b 8151 it here. */
bd9d0f3f
GM
8152 mini_window = FRAME_MINIBUF_WINDOW (sf);
8153 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
8de2d90b 8154
bd9d0f3f
GM
8155 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
8156 {
8157 XWINDOW (mini_window)->must_be_updated_p = 1;
8158 pause |= update_frame (mini_frame, 0, 0);
8159 if (!pause && hscroll_windows (mini_window))
8160 goto retry;
8161 }
6e8290aa 8162 }
a2889657 8163
5f5c8ee5
GM
8164 /* If display was paused because of pending input, make sure we do a
8165 thorough update the next time. */
a2889657
JB
8166 if (pause)
8167 {
5f5c8ee5
GM
8168 /* Prevent the optimization at the beginning of
8169 redisplay_internal that tries a single-line update of the
8170 line containing the cursor in the selected window. */
8171 CHARPOS (this_line_start_pos) = 0;
8172
8173 /* Let the overlay arrow be updated the next time. */
265a9e55 8174 if (!NILP (last_arrow_position))
a2889657
JB
8175 {
8176 last_arrow_position = Qt;
8177 last_arrow_string = Qt;
8178 }
5f5c8ee5
GM
8179
8180 /* If we pause after scrolling, some rows in the current
8181 matrices of some windows are not valid. */
8182 if (!WINDOW_FULL_WIDTH_P (w)
8183 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
8184 update_mode_lines = 1;
8185 }
8186
5f5c8ee5
GM
8187 /* Now text on frame agrees with windows, so put info into the
8188 windows for partial redisplay to follow. */
a2889657
JB
8189 if (!pause)
8190 {
8191 register struct buffer *b = XBUFFER (w->buffer);
8192
9142dd5b
GM
8193 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
8194 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
8195 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
8196 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
a2889657 8197
5f5c8ee5 8198 if (consider_all_windows_p)
886bd6f2 8199 mark_window_display_accurate (FRAME_ROOT_WINDOW (sf), 1);
a2889657
JB
8200 else
8201 {
5f5c8ee5
GM
8202 XSETFASTINT (w->last_point, BUF_PT (b));
8203 w->last_cursor = w->cursor;
8204 w->last_cursor_off_p = w->cursor_off_p;
8205
28995e67 8206 b->clip_changed = 0;
9142dd5b 8207 b->prevent_redisplay_optimizations_p = 0;
a2889657 8208 w->update_mode_line = Qnil;
c2213350 8209 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
8850a573 8210 XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
538f13d4
RS
8211 w->last_had_star
8212 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
8213 ? Qt : Qnil);
3ee4159a
RS
8214
8215 /* Record if we are showing a region, so can make sure to
8216 update it fully at next redisplay. */
8217 w->region_showing = (!NILP (Vtransient_mark_mode)
97a36635
GM
8218 && (EQ (selected_window,
8219 current_buffer->last_selected_window)
293a54ce 8220 || highlight_nonselected_windows)
3ee4159a
RS
8221 && !NILP (XBUFFER (w->buffer)->mark_active)
8222 ? Fmarker_position (XBUFFER (w->buffer)->mark)
8223 : Qnil);
8224
d2f84654 8225 w->window_end_valid = w->buffer;
d45de95b 8226 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657 8227 last_arrow_string = Voverlay_arrow_string;
efc63ef0 8228 if (frame_up_to_date_hook != 0)
886bd6f2 8229 (*frame_up_to_date_hook) (sf);
9142dd5b
GM
8230
8231 w->current_matrix->buffer = b;
8232 w->current_matrix->begv = BUF_BEGV (b);
8233 w->current_matrix->zv = BUF_ZV (b);
a2889657 8234 }
15e26c76 8235
a2889657
JB
8236 update_mode_lines = 0;
8237 windows_or_buffers_changed = 0;
8238 }
8239
5f5c8ee5
GM
8240 /* Start SIGIO interrupts coming again. Having them off during the
8241 code above makes it less likely one will discard output, but not
8242 impossible, since there might be stuff in the system buffer here.
a2889657 8243 But it is much hairier to try to do anything about that. */
a2889657
JB
8244 if (interrupt_input)
8245 request_sigio ();
8246 start_polling ();
8247
5f5c8ee5
GM
8248 /* If a frame has become visible which was not before, redisplay
8249 again, so that we display it. Expose events for such a frame
8250 (which it gets when becoming visible) don't call the parts of
8251 redisplay constructing glyphs, so simply exposing a frame won't
8252 display anything in this case. So, we have to display these
8253 frames here explicitly. */
11c52c4f
RS
8254 if (!pause)
8255 {
8256 Lisp_Object tail, frame;
8257 int new_count = 0;
8258
8259 FOR_EACH_FRAME (tail, frame)
8260 {
8261 int this_is_visible = 0;
8e83f802
RS
8262
8263 if (XFRAME (frame)->visible)
8264 this_is_visible = 1;
8265 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
8266 if (XFRAME (frame)->visible)
8267 this_is_visible = 1;
11c52c4f
RS
8268
8269 if (this_is_visible)
8270 new_count++;
8271 }
8272
89819bdd 8273 if (new_count != number_of_visible_frames)
11c52c4f
RS
8274 windows_or_buffers_changed++;
8275 }
8276
44fa5b1e 8277 /* Change frame size now if a change is pending. */
c6e89d6c 8278 do_pending_window_change (1);
d8e242fd 8279
8b32d885
RS
8280 /* If we just did a pending size change, or have additional
8281 visible frames, redisplay again. */
3c8c72e0 8282 if (windows_or_buffers_changed && !pause)
8b32d885 8283 goto retry;
5f5c8ee5
GM
8284
8285 end_of_redisplay:;
c6e89d6c 8286
28514cd9 8287 unbind_to (count, Qnil);
a2889657
JB
8288}
8289
5f5c8ee5
GM
8290
8291/* Redisplay, but leave alone any recent echo area message unless
8292 another message has been requested in its place.
a2889657
JB
8293
8294 This is useful in situations where you need to redisplay but no
8295 user action has occurred, making it inappropriate for the message
8296 area to be cleared. See tracking_off and
8297 wait_reading_process_input for examples of these situations. */
8298
8991bb31 8299void
a2889657
JB
8300redisplay_preserve_echo_area ()
8301{
c6e89d6c 8302 if (!NILP (echo_area_buffer[1]))
a2889657 8303 {
c6e89d6c
GM
8304 /* We have a previously displayed message, but no current
8305 message. Redisplay the previous message. */
8306 display_last_displayed_message_p = 1;
e9874cee 8307 redisplay_internal (1);
c6e89d6c 8308 display_last_displayed_message_p = 0;
a2889657
JB
8309 }
8310 else
e9874cee 8311 redisplay_internal (1);
a2889657
JB
8312}
8313
5f5c8ee5 8314
28514cd9
GM
8315/* Function registered with record_unwind_protect in
8316 redisplay_internal. Clears the flag indicating that a redisplay is
8317 in progress. */
8318
8319static Lisp_Object
8320unwind_redisplay (old_redisplaying_p)
8321 Lisp_Object old_redisplaying_p;
8322{
8323 redisplaying_p = XFASTINT (old_redisplaying_p);
c6e89d6c 8324 return Qnil;
28514cd9
GM
8325}
8326
8327
5f5c8ee5
GM
8328/* Mark the display of windows in the window tree rooted at WINDOW as
8329 accurate or inaccurate. If FLAG is non-zero mark display of WINDOW
8330 as accurate. If FLAG is zero arrange for WINDOW to be redisplayed
8331 the next time redisplay_internal is called. */
8332
a2889657 8333void
5f5c8ee5 8334mark_window_display_accurate (window, accurate_p)
a2889657 8335 Lisp_Object window;
5f5c8ee5 8336 int accurate_p;
a2889657 8337{
5f5c8ee5
GM
8338 struct window *w;
8339
8340 for (; !NILP (window); window = w->next)
a2889657
JB
8341 {
8342 w = XWINDOW (window);
8343
5f5c8ee5 8344 if (BUFFERP (w->buffer))
bd66d1ba 8345 {
5f5c8ee5
GM
8346 struct buffer *b = XBUFFER (w->buffer);
8347
c2213350 8348 XSETFASTINT (w->last_modified,
5f5c8ee5 8349 accurate_p ? BUF_MODIFF (b) : 0);
8850a573 8350 XSETFASTINT (w->last_overlay_modified,
5f5c8ee5
GM
8351 accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
8352 w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)
8353 ? Qt : Qnil);
bd66d1ba 8354
5f5c8ee5
GM
8355#if 0 /* I don't think this is necessary because display_line does it.
8356 Let's check it. */
bd66d1ba
RS
8357 /* Record if we are showing a region, so can make sure to
8358 update it fully at next redisplay. */
5f5c8ee5
GM
8359 w->region_showing
8360 = (!NILP (Vtransient_mark_mode)
8361 && (w == XWINDOW (current_buffer->last_selected_window)
8362 || highlight_nonselected_windows)
8363 && (!NILP (b->mark_active)
8364 ? Fmarker_position (b->mark)
8365 : Qnil));
8366#endif
8367
8368 if (accurate_p)
8369 {
8370 b->clip_changed = 0;
9142dd5b
GM
8371 b->prevent_redisplay_optimizations_p = 0;
8372 w->current_matrix->buffer = b;
8373 w->current_matrix->begv = BUF_BEGV (b);
8374 w->current_matrix->zv = BUF_ZV (b);
5f5c8ee5
GM
8375 w->last_cursor = w->cursor;
8376 w->last_cursor_off_p = w->cursor_off_p;
8377 if (w == XWINDOW (selected_window))
6fc556fd 8378 w->last_point = make_number (BUF_PT (b));
5f5c8ee5 8379 else
6fc556fd 8380 w->last_point = make_number (XMARKER (w->pointm)->charpos);
5f5c8ee5 8381 }
bd66d1ba
RS
8382 }
8383
d2f84654 8384 w->window_end_valid = w->buffer;
a2889657
JB
8385 w->update_mode_line = Qnil;
8386
265a9e55 8387 if (!NILP (w->vchild))
5f5c8ee5 8388 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 8389 if (!NILP (w->hchild))
5f5c8ee5 8390 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
8391 }
8392
5f5c8ee5 8393 if (accurate_p)
a2889657 8394 {
d45de95b 8395 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
8396 last_arrow_string = Voverlay_arrow_string;
8397 }
8398 else
8399 {
5f5c8ee5
GM
8400 /* Force a thorough redisplay the next time by setting
8401 last_arrow_position and last_arrow_string to t, which is
8402 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
8403 last_arrow_position = Qt;
8404 last_arrow_string = Qt;
8405 }
8406}
5f5c8ee5
GM
8407
8408
8409/* Return value in display table DP (Lisp_Char_Table *) for character
8410 C. Since a display table doesn't have any parent, we don't have to
8411 follow parent. Do not call this function directly but use the
8412 macro DISP_CHAR_VECTOR. */
8413
8414Lisp_Object
8415disp_char_vector (dp, c)
8416 struct Lisp_Char_Table *dp;
8417 int c;
8418{
8419 int code[4], i;
8420 Lisp_Object val;
8421
8422 if (SINGLE_BYTE_CHAR_P (c))
8423 return (dp->contents[c]);
8424
c5924f47 8425 SPLIT_CHAR (c, code[0], code[1], code[2]);
260a86a0
KH
8426 if (code[1] < 32)
8427 code[1] = -1;
8428 else if (code[2] < 32)
8429 code[2] = -1;
5f5c8ee5
GM
8430
8431 /* Here, the possible range of code[0] (== charset ID) is
8432 128..max_charset. Since the top level char table contains data
8433 for multibyte characters after 256th element, we must increment
8434 code[0] by 128 to get a correct index. */
8435 code[0] += 128;
8436 code[3] = -1; /* anchor */
8437
8438 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
8439 {
8440 val = dp->contents[code[i]];
8441 if (!SUB_CHAR_TABLE_P (val))
8442 return (NILP (val) ? dp->defalt : val);
8443 }
8444
8445 /* Here, val is a sub char table. We return the default value of
8446 it. */
8447 return (dp->defalt);
8448}
8449
8450
a2889657 8451\f
5f5c8ee5
GM
8452/***********************************************************************
8453 Window Redisplay
8454 ***********************************************************************/
a2725ab2 8455
5f5c8ee5 8456/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
8457
8458static void
5f5c8ee5
GM
8459redisplay_windows (window)
8460 Lisp_Object window;
90adcf20 8461{
5f5c8ee5
GM
8462 while (!NILP (window))
8463 {
8464 struct window *w = XWINDOW (window);
8465
8466 if (!NILP (w->hchild))
8467 redisplay_windows (w->hchild);
8468 else if (!NILP (w->vchild))
8469 redisplay_windows (w->vchild);
8470 else
8471 redisplay_window (window, 0);
a2725ab2 8472
5f5c8ee5
GM
8473 window = w->next;
8474 }
8475}
8476
8477
8478/* Set cursor position of W. PT is assumed to be displayed in ROW.
8479 DELTA is the number of bytes by which positions recorded in ROW
8480 differ from current buffer positions. */
8481
8482void
8483set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
8484 struct window *w;
8485 struct glyph_row *row;
8486 struct glyph_matrix *matrix;
8487 int delta, delta_bytes, dy, dvpos;
8488{
8489 struct glyph *glyph = row->glyphs[TEXT_AREA];
8490 struct glyph *end = glyph + row->used[TEXT_AREA];
8491 int x = row->x;
8492 int pt_old = PT - delta;
8493
8494 /* Skip over glyphs not having an object at the start of the row.
8495 These are special glyphs like truncation marks on terminal
8496 frames. */
8497 if (row->displays_text_p)
8498 while (glyph < end
6fc556fd 8499 && INTEGERP (glyph->object)
5f5c8ee5
GM
8500 && glyph->charpos < 0)
8501 {
8502 x += glyph->pixel_width;
8503 ++glyph;
8504 }
8505
8506 while (glyph < end
6fc556fd 8507 && !INTEGERP (glyph->object)
5f5c8ee5
GM
8508 && (!BUFFERP (glyph->object)
8509 || glyph->charpos < pt_old))
8510 {
8511 x += glyph->pixel_width;
8512 ++glyph;
8513 }
8514
8515 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
8516 w->cursor.x = x;
8517 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
8518 w->cursor.y = row->y + dy;
8519
8520 if (w == XWINDOW (selected_window))
8521 {
8522 if (!row->continued_p
8523 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
8524 && row->x == 0)
8525 {
8526 this_line_buffer = XBUFFER (w->buffer);
8527
8528 CHARPOS (this_line_start_pos)
8529 = MATRIX_ROW_START_CHARPOS (row) + delta;
8530 BYTEPOS (this_line_start_pos)
8531 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
8532
8533 CHARPOS (this_line_end_pos)
8534 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
8535 BYTEPOS (this_line_end_pos)
8536 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
8537
8538 this_line_y = w->cursor.y;
8539 this_line_pixel_height = row->height;
8540 this_line_vpos = w->cursor.vpos;
8541 this_line_start_x = row->x;
8542 }
8543 else
8544 CHARPOS (this_line_start_pos) = 0;
8545 }
8546}
8547
8548
8549/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
8550 start STARTP. Sets the window start of WINDOW to that position.
8551
8552 We assume that the window's buffer is really current. */
5f5c8ee5
GM
8553
8554static INLINE struct text_pos
8555run_window_scroll_functions (window, startp)
8556 Lisp_Object window;
8557 struct text_pos startp;
8558{
8559 struct window *w = XWINDOW (window);
8560 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
8561
8562 if (current_buffer != XBUFFER (w->buffer))
8563 abort ();
8564
5f5c8ee5
GM
8565 if (!NILP (Vwindow_scroll_functions))
8566 {
8567 run_hook_with_args_2 (Qwindow_scroll_functions, window,
8568 make_number (CHARPOS (startp)));
8569 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
8570 /* In case the hook functions switch buffers. */
8571 if (current_buffer != XBUFFER (w->buffer))
8572 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8573 }
90adcf20 8574
5f5c8ee5
GM
8575 return startp;
8576}
8577
8578
8579/* Modify the desired matrix of window W and W->vscroll so that the
8580 line containing the cursor is fully visible. */
8581
8582static void
8583make_cursor_line_fully_visible (w)
8584 struct window *w;
8585{
8586 struct glyph_matrix *matrix;
8587 struct glyph_row *row;
b28cb6ed 8588 int window_height, header_line_height;
5f5c8ee5
GM
8589
8590 /* It's not always possible to find the cursor, e.g, when a window
8591 is full of overlay strings. Don't do anything in that case. */
8592 if (w->cursor.vpos < 0)
8593 return;
8594
8595 matrix = w->desired_matrix;
8596 row = MATRIX_ROW (matrix, w->cursor.vpos);
8597
b28cb6ed
GM
8598 /* If the cursor row is not partially visible, there's nothing
8599 to do. */
8600 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
8601 return;
8602
8603 /* If the row the cursor is in is taller than the window's height,
8604 it's not clear what to do, so do nothing. */
8605 window_height = window_box_height (w);
8606 if (row->height >= window_height)
8607 return;
8608
8609 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
5f5c8ee5
GM
8610 {
8611 int dy = row->height - row->visible_height;
8612 w->vscroll = 0;
8613 w->cursor.y += dy;
8614 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
8615 }
b28cb6ed 8616 else /* MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) */
5f5c8ee5
GM
8617 {
8618 int dy = - (row->height - row->visible_height);
8619 w->vscroll = dy;
8620 w->cursor.y += dy;
8621 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
8622 }
b28cb6ed 8623
5f5c8ee5
GM
8624 /* When we change the cursor y-position of the selected window,
8625 change this_line_y as well so that the display optimization for
8626 the cursor line of the selected window in redisplay_internal uses
8627 the correct y-position. */
8628 if (w == XWINDOW (selected_window))
8629 this_line_y = w->cursor.y;
8630}
8631
8632
8633/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
8634 non-zero means only WINDOW is redisplayed in redisplay_internal.
8635 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
8636 in redisplay_window to bring a partially visible line into view in
8637 the case that only the cursor has moved.
8638
8639 Value is
8640
8641 1 if scrolling succeeded
8642
8643 0 if scrolling didn't find point.
8644
8645 -1 if new fonts have been loaded so that we must interrupt
8646 redisplay, adjust glyph matrices, and try again. */
8647
8648static int
8649try_scrolling (window, just_this_one_p, scroll_conservatively,
8650 scroll_step, temp_scroll_step)
8651 Lisp_Object window;
8652 int just_this_one_p;
8653 int scroll_conservatively, scroll_step;
8654 int temp_scroll_step;
8655{
8656 struct window *w = XWINDOW (window);
8657 struct frame *f = XFRAME (w->frame);
8658 struct text_pos scroll_margin_pos;
8659 struct text_pos pos;
8660 struct text_pos startp;
8661 struct it it;
8662 Lisp_Object window_end;
8663 int this_scroll_margin;
8664 int dy = 0;
8665 int scroll_max;
b8a63ccb 8666 int rc;
5f5c8ee5
GM
8667 int amount_to_scroll = 0;
8668 Lisp_Object aggressive;
8669 int height;
8670
8671#if GLYPH_DEBUG
8672 debug_method_add (w, "try_scrolling");
78614721 8673#endif
5f5c8ee5
GM
8674
8675 SET_TEXT_POS_FROM_MARKER (startp, w->start);
8676
8677 /* Compute scroll margin height in pixels. We scroll when point is
8678 within this distance from the top or bottom of the window. */
8679 if (scroll_margin > 0)
90adcf20 8680 {
5f5c8ee5
GM
8681 this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
8682 this_scroll_margin *= CANON_Y_UNIT (f);
8683 }
8684 else
8685 this_scroll_margin = 0;
8686
8687 /* Compute how much we should try to scroll maximally to bring point
8688 into view. */
8689 if (scroll_step)
8690 scroll_max = scroll_step;
8691 else if (scroll_conservatively)
8692 scroll_max = scroll_conservatively;
8693 else if (temp_scroll_step)
8694 scroll_max = temp_scroll_step;
8695 else if (NUMBERP (current_buffer->scroll_down_aggressively)
8696 || NUMBERP (current_buffer->scroll_up_aggressively))
8697 /* We're trying to scroll because of aggressive scrolling
8698 but no scroll_step is set. Choose an arbitrary one. Maybe
8699 there should be a variable for this. */
8700 scroll_max = 10;
8701 else
8702 scroll_max = 0;
8703 scroll_max *= CANON_Y_UNIT (f);
8704
8705 /* Decide whether we have to scroll down. Start at the window end
8706 and move this_scroll_margin up to find the position of the scroll
8707 margin. */
8708 window_end = Fwindow_end (window, Qt);
8709 CHARPOS (scroll_margin_pos) = XINT (window_end);
8710 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
8711 if (this_scroll_margin)
8712 {
8713 start_display (&it, w, scroll_margin_pos);
8714 move_it_vertically (&it, - this_scroll_margin);
8715 scroll_margin_pos = it.current.pos;
8716 }
8717
8718 if (PT >= CHARPOS (scroll_margin_pos))
8719 {
8720 int y0;
b8a63ccb
GM
8721#if 0
8722 int line_height;
8723#endif
5f5c8ee5
GM
8724
8725 /* Point is in the scroll margin at the bottom of the window, or
8726 below. Compute a new window start that makes point visible. */
47589c8c 8727
5f5c8ee5
GM
8728 /* Compute the distance from the scroll margin to PT.
8729 Give up if the distance is greater than scroll_max. */
8730 start_display (&it, w, scroll_margin_pos);
8731 y0 = it.current_y;
8732 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8733 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
b8a63ccb 8734#if 0 /* Taking the line's height into account here looks wrong. */
5f5c8ee5
GM
8735 line_height = (it.max_ascent + it.max_descent
8736 ? it.max_ascent + it.max_descent
8737 : last_height);
8738 dy = it.current_y + line_height - y0;
b8a63ccb
GM
8739#else
8740 dy = it.current_y - y0;
8741#endif
47589c8c 8742
5f5c8ee5
GM
8743 if (dy > scroll_max)
8744 return 0;
8745
8746 /* Move the window start down. If scrolling conservatively,
8747 move it just enough down to make point visible. If
8748 scroll_step is set, move it down by scroll_step. */
8749 start_display (&it, w, startp);
8750
8751 if (scroll_conservatively)
8752 amount_to_scroll = dy;
8753 else if (scroll_step || temp_scroll_step)
8754 amount_to_scroll = scroll_max;
8755 else
90adcf20 8756 {
5f5c8ee5
GM
8757 aggressive = current_buffer->scroll_down_aggressively;
8758 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8759 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8760 if (NUMBERP (aggressive))
8761 amount_to_scroll = XFLOATINT (aggressive) * height;
8762 }
a2725ab2 8763
5f5c8ee5
GM
8764 if (amount_to_scroll <= 0)
8765 return 0;
a2725ab2 8766
5f5c8ee5
GM
8767 move_it_vertically (&it, amount_to_scroll);
8768 startp = it.current.pos;
8769 }
8770 else
8771 {
8772 /* See if point is inside the scroll margin at the top of the
8773 window. */
8774 scroll_margin_pos = startp;
8775 if (this_scroll_margin)
8776 {
8777 start_display (&it, w, startp);
8778 move_it_vertically (&it, this_scroll_margin);
8779 scroll_margin_pos = it.current.pos;
8780 }
8781
8782 if (PT < CHARPOS (scroll_margin_pos))
8783 {
8784 /* Point is in the scroll margin at the top of the window or
8785 above what is displayed in the window. */
8786 int y0;
8787
8788 /* Compute the vertical distance from PT to the scroll
8789 margin position. Give up if distance is greater than
8790 scroll_max. */
8791 SET_TEXT_POS (pos, PT, PT_BYTE);
8792 start_display (&it, w, pos);
8793 y0 = it.current_y;
8794 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
8795 it.last_visible_y, -1,
8796 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8797 dy = it.current_y - y0;
8798 if (dy > scroll_max)
8799 return 0;
8800
8801 /* Compute new window start. */
8802 start_display (&it, w, startp);
8803
8804 if (scroll_conservatively)
8805 amount_to_scroll = dy;
8806 else if (scroll_step || temp_scroll_step)
8807 amount_to_scroll = scroll_max;
538f13d4 8808 else
5f5c8ee5
GM
8809 {
8810 aggressive = current_buffer->scroll_up_aggressively;
8811 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8812 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8813 if (NUMBERP (aggressive))
8814 amount_to_scroll = XFLOATINT (aggressive) * height;
8815 }
a2725ab2 8816
5f5c8ee5
GM
8817 if (amount_to_scroll <= 0)
8818 return 0;
8819
8820 move_it_vertically (&it, - amount_to_scroll);
8821 startp = it.current.pos;
90adcf20
RS
8822 }
8823 }
a2889657 8824
5f5c8ee5
GM
8825 /* Run window scroll functions. */
8826 startp = run_window_scroll_functions (window, startp);
90adcf20 8827
5f5c8ee5
GM
8828 /* Display the window. Give up if new fonts are loaded, or if point
8829 doesn't appear. */
8830 if (!try_window (window, startp))
8831 rc = -1;
8832 else if (w->cursor.vpos < 0)
8833 {
8834 clear_glyph_matrix (w->desired_matrix);
8835 rc = 0;
8836 }
8837 else
8838 {
8839 /* Maybe forget recorded base line for line number display. */
8840 if (!just_this_one_p
8841 || current_buffer->clip_changed
9142dd5b 8842 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5
GM
8843 w->base_line_number = Qnil;
8844
8845 /* If cursor ends up on a partially visible line, shift display
8846 lines up or down. */
8847 make_cursor_line_fully_visible (w);
8848 rc = 1;
8849 }
8850
8851 return rc;
a2889657
JB
8852}
8853
5f5c8ee5
GM
8854
8855/* Compute a suitable window start for window W if display of W starts
8856 on a continuation line. Value is non-zero if a new window start
8857 was computed.
8858
8859 The new window start will be computed, based on W's width, starting
8860 from the start of the continued line. It is the start of the
8861 screen line with the minimum distance from the old start W->start. */
8862
8863static int
8864compute_window_start_on_continuation_line (w)
8865 struct window *w;
1f1ff51d 8866{
5f5c8ee5
GM
8867 struct text_pos pos, start_pos;
8868 int window_start_changed_p = 0;
1f1ff51d 8869
5f5c8ee5 8870 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 8871
5f5c8ee5
GM
8872 /* If window start is on a continuation line... Window start may be
8873 < BEGV in case there's invisible text at the start of the
8874 buffer (M-x rmail, for example). */
8875 if (CHARPOS (start_pos) > BEGV
8876 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 8877 {
5f5c8ee5
GM
8878 struct it it;
8879 struct glyph_row *row;
f3751a65
GM
8880
8881 /* Handle the case that the window start is out of range. */
8882 if (CHARPOS (start_pos) < BEGV)
8883 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
8884 else if (CHARPOS (start_pos) > ZV)
8885 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
5f5c8ee5
GM
8886
8887 /* Find the start of the continued line. This should be fast
8888 because scan_buffer is fast (newline cache). */
045dee35 8889 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
8890 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
8891 row, DEFAULT_FACE_ID);
8892 reseat_at_previous_visible_line_start (&it);
8893
8894 /* If the line start is "too far" away from the window start,
8895 say it takes too much time to compute a new window start. */
8896 if (CHARPOS (start_pos) - IT_CHARPOS (it)
8897 < XFASTINT (w->height) * XFASTINT (w->width))
8898 {
8899 int min_distance, distance;
8900
8901 /* Move forward by display lines to find the new window
8902 start. If window width was enlarged, the new start can
8903 be expected to be > the old start. If window width was
8904 decreased, the new window start will be < the old start.
8905 So, we're looking for the display line start with the
8906 minimum distance from the old window start. */
8907 pos = it.current.pos;
8908 min_distance = INFINITY;
8909 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
8910 distance < min_distance)
8911 {
8912 min_distance = distance;
8913 pos = it.current.pos;
8914 move_it_by_lines (&it, 1, 0);
8915 }
8916
8917 /* Set the window start there. */
8918 SET_MARKER_FROM_TEXT_POS (w->start, pos);
8919 window_start_changed_p = 1;
8920 }
1f1ff51d 8921 }
5f5c8ee5
GM
8922
8923 return window_start_changed_p;
1f1ff51d
KH
8924}
8925
5f5c8ee5 8926
47589c8c
GM
8927/* Try cursor movement in case text has not changes in window WINDOW,
8928 with window start STARTP. Value is
8929
8930 1 if successful
8931
8932 0 if this method cannot be used
8933
8934 -1 if we know we have to scroll the display. *SCROLL_STEP is
8935 set to 1, under certain circumstances, if we want to scroll as
8936 if scroll-step were set to 1. See the code. */
8937
8938static int
8939try_cursor_movement (window, startp, scroll_step)
8940 Lisp_Object window;
8941 struct text_pos startp;
8942 int *scroll_step;
8943{
8944 struct window *w = XWINDOW (window);
8945 struct frame *f = XFRAME (w->frame);
8946 int rc = 0;
8947
8948 /* Handle case where text has not changed, only point, and it has
8949 not moved off the frame. */
8950 if (/* Point may be in this window. */
8951 PT >= CHARPOS (startp)
8952 /* If we don't check this, we are called to move the cursor in a
8953 horizontally split window with a current matrix that doesn't
8954 fit the display. */
8955 && !windows_or_buffers_changed
8956 /* Selective display hasn't changed. */
8957 && !current_buffer->clip_changed
8958 /* If force-mode-line-update was called, really redisplay;
8959 that's how redisplay is forced after e.g. changing
8960 buffer-invisibility-spec. */
8961 && NILP (w->update_mode_line)
8962 /* Can't use this case if highlighting a region. When a
8963 region exists, cursor movement has to do more than just
8964 set the cursor. */
8965 && !(!NILP (Vtransient_mark_mode)
8966 && !NILP (current_buffer->mark_active))
8967 && NILP (w->region_showing)
8968 && NILP (Vshow_trailing_whitespace)
8969 /* Right after splitting windows, last_point may be nil. */
8970 && INTEGERP (w->last_point)
8971 /* This code is not used for mini-buffer for the sake of the case
8972 of redisplaying to replace an echo area message; since in
8973 that case the mini-buffer contents per se are usually
8974 unchanged. This code is of no real use in the mini-buffer
8975 since the handling of this_line_start_pos, etc., in redisplay
8976 handles the same cases. */
8977 && !EQ (window, minibuf_window)
8978 /* When splitting windows or for new windows, it happens that
8979 redisplay is called with a nil window_end_vpos or one being
8980 larger than the window. This should really be fixed in
8981 window.c. I don't have this on my list, now, so we do
8982 approximately the same as the old redisplay code. --gerd. */
8983 && INTEGERP (w->window_end_vpos)
8984 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
8985 && (FRAME_WINDOW_P (f)
8986 || !MARKERP (Voverlay_arrow_position)
8987 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
8988 {
8989 int this_scroll_margin;
8990 struct glyph_row *row;
8991
8992#if GLYPH_DEBUG
8993 debug_method_add (w, "cursor movement");
8994#endif
8995
8996 /* Scroll if point within this distance from the top or bottom
8997 of the window. This is a pixel value. */
8998 this_scroll_margin = max (0, scroll_margin);
8999 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
9000 this_scroll_margin *= CANON_Y_UNIT (f);
9001
9002 /* Start with the row the cursor was displayed during the last
9003 not paused redisplay. Give up if that row is not valid. */
bd9d0f3f
GM
9004 if (w->last_cursor.vpos < 0
9005 || w->last_cursor.vpos >= w->current_matrix->nrows)
47589c8c
GM
9006 rc = -1;
9007 else
9008 {
9009 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
9010 if (row->mode_line_p)
9011 ++row;
9012 if (!row->enabled_p)
9013 rc = -1;
9014 }
9015
9016 if (rc == 0)
9017 {
9018 int scroll_p = 0;
68c5d1db
GM
9019 int last_y = window_text_bottom_y (w) - this_scroll_margin;
9020
47589c8c
GM
9021
9022 if (PT > XFASTINT (w->last_point))
9023 {
9024 /* Point has moved forward. */
47589c8c
GM
9025 while (MATRIX_ROW_END_CHARPOS (row) < PT
9026 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
9027 {
9028 xassert (row->enabled_p);
9029 ++row;
9030 }
9031
9032 /* The end position of a row equals the start position
9033 of the next row. If PT is there, we would rather
cafafe0b
GM
9034 display it in the next line. */
9035 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
9036 && MATRIX_ROW_END_CHARPOS (row) == PT
9037 && !cursor_row_p (w, row))
9038 ++row;
47589c8c
GM
9039
9040 /* If within the scroll margin, scroll. Note that
9041 MATRIX_ROW_BOTTOM_Y gives the pixel position at which
9042 the next line would be drawn, and that
9043 this_scroll_margin can be zero. */
9044 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
9045 || PT > MATRIX_ROW_END_CHARPOS (row)
9046 /* Line is completely visible last line in window
9047 and PT is to be set in the next line. */
9048 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
9049 && PT == MATRIX_ROW_END_CHARPOS (row)
9050 && !row->ends_at_zv_p
9051 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
9052 scroll_p = 1;
9053 }
9054 else if (PT < XFASTINT (w->last_point))
9055 {
9056 /* Cursor has to be moved backward. Note that PT >=
9057 CHARPOS (startp) because of the outer
9058 if-statement. */
9059 while (!row->mode_line_p
9060 && (MATRIX_ROW_START_CHARPOS (row) > PT
9061 || (MATRIX_ROW_START_CHARPOS (row) == PT
9062 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
9063 && (row->y > this_scroll_margin
9064 || CHARPOS (startp) == BEGV))
9065 {
9066 xassert (row->enabled_p);
9067 --row;
9068 }
9069
9070 /* Consider the following case: Window starts at BEGV,
9071 there is invisible, intangible text at BEGV, so that
9072 display starts at some point START > BEGV. It can
9073 happen that we are called with PT somewhere between
9074 BEGV and START. Try to handle that case. */
9075 if (row < w->current_matrix->rows
9076 || row->mode_line_p)
9077 {
9078 row = w->current_matrix->rows;
9079 if (row->mode_line_p)
9080 ++row;
9081 }
9082
9083 /* Due to newlines in overlay strings, we may have to
9084 skip forward over overlay strings. */
68c5d1db
GM
9085 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
9086 && MATRIX_ROW_END_CHARPOS (row) == PT
9087 && !cursor_row_p (w, row))
47589c8c
GM
9088 ++row;
9089
9090 /* If within the scroll margin, scroll. */
9091 if (row->y < this_scroll_margin
9092 && CHARPOS (startp) != BEGV)
9093 scroll_p = 1;
9094 }
9095
9096 if (PT < MATRIX_ROW_START_CHARPOS (row)
9097 || PT > MATRIX_ROW_END_CHARPOS (row))
9098 {
9099 /* if PT is not in the glyph row, give up. */
9100 rc = -1;
9101 }
440fc135 9102 else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
47589c8c
GM
9103 {
9104 /* If we end up in a partially visible line, let's make it
9105 fully visible, except when it's taller than the window,
9106 in which case we can't do much about it. */
440fc135
GM
9107 if (row->height > window_box_height (w))
9108 {
9109 *scroll_step = 1;
9110 rc = -1;
9111 }
9112 else
9113 {
9114 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
9115 try_window (window, startp);
9116 make_cursor_line_fully_visible (w);
9117 rc = 1;
9118 }
47589c8c
GM
9119 }
9120 else if (scroll_p)
9121 rc = -1;
9122 else
9123 {
9124 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
9125 rc = 1;
9126 }
9127 }
9128 }
9129
9130 return rc;
9131}
9132
9133
5f5c8ee5
GM
9134/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
9135 selected_window is redisplayed. */
90adcf20 9136
a2889657 9137static void
5f5c8ee5 9138redisplay_window (window, just_this_one_p)
a2889657 9139 Lisp_Object window;
5f5c8ee5 9140 int just_this_one_p;
a2889657 9141{
5f5c8ee5
GM
9142 struct window *w = XWINDOW (window);
9143 struct frame *f = XFRAME (w->frame);
9144 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 9145 struct buffer *old = current_buffer;
5f5c8ee5 9146 struct text_pos lpoint, opoint, startp;
e481f960 9147 int update_mode_line;
5f5c8ee5
GM
9148 int tem;
9149 struct it it;
9150 /* Record it now because it's overwritten. */
9151 int current_matrix_up_to_date_p = 0;
5f5c8ee5 9152 int temp_scroll_step = 0;
2e54982e 9153 int count = specpdl_ptr - specpdl;
47589c8c 9154 int rc;
a2889657 9155
5f5c8ee5
GM
9156 SET_TEXT_POS (lpoint, PT, PT_BYTE);
9157 opoint = lpoint;
a2889657 9158
5f5c8ee5
GM
9159 /* W must be a leaf window here. */
9160 xassert (!NILP (w->buffer));
9161#if GLYPH_DEBUG
9162 *w->desired_matrix->method = 0;
9163#endif
2e54982e
RS
9164
9165 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
9166
9167 reconsider_clip_changes (w, buffer);
9168
5f5c8ee5
GM
9169 /* Has the mode line to be updated? */
9170 update_mode_line = (!NILP (w->update_mode_line)
9171 || update_mode_lines
9172 || buffer->clip_changed);
8de2d90b
JB
9173
9174 if (MINI_WINDOW_P (w))
9175 {
5f5c8ee5 9176 if (w == XWINDOW (echo_area_window)
c6e89d6c 9177 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
9178 {
9179 if (update_mode_line)
9180 /* We may have to update a tty frame's menu bar or a
e037b9ec 9181 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
9182 goto finish_menu_bars;
9183 else
9184 /* We've already displayed the echo area glyphs in this window. */
9185 goto finish_scroll_bars;
9186 }
73af359d 9187 else if (w != XWINDOW (minibuf_window))
8de2d90b 9188 {
5f5c8ee5
GM
9189 /* W is a mini-buffer window, but it's not the currently
9190 active one, so clear it. */
9191 int yb = window_text_bottom_y (w);
9192 struct glyph_row *row;
9193 int y;
9194
9195 for (y = 0, row = w->desired_matrix->rows;
9196 y < yb;
9197 y += row->height, ++row)
9198 blank_row (w, row, y);
88f22aff 9199 goto finish_scroll_bars;
8de2d90b
JB
9200 }
9201 }
a2889657 9202
5f5c8ee5
GM
9203 /* Otherwise set up data on this window; select its buffer and point
9204 value. */
6a93695f
GM
9205 /* Really select the buffer, for the sake of buffer-local
9206 variables. */
9207 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5
GM
9208 SET_TEXT_POS (opoint, PT, PT_BYTE);
9209
9210 current_matrix_up_to_date_p
9211 = (!NILP (w->window_end_valid)
9212 && !current_buffer->clip_changed
9213 && XFASTINT (w->last_modified) >= MODIFF
9214 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 9215
5f5c8ee5
GM
9216 /* When windows_or_buffers_changed is non-zero, we can't rely on
9217 the window end being valid, so set it to nil there. */
9218 if (windows_or_buffers_changed)
9219 {
9220 /* If window starts on a continuation line, maybe adjust the
9221 window start in case the window's width changed. */
9222 if (XMARKER (w->start)->buffer == current_buffer)
9223 compute_window_start_on_continuation_line (w);
9224
9225 w->window_end_valid = Qnil;
9226 }
12adba34 9227
5f5c8ee5
GM
9228 /* Some sanity checks. */
9229 CHECK_WINDOW_END (w);
9230 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 9231 abort ();
5f5c8ee5 9232 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 9233 abort ();
a2889657 9234
28995e67
RS
9235 /* If %c is in mode line, update it if needed. */
9236 if (!NILP (w->column_number_displayed)
9237 /* This alternative quickly identifies a common case
9238 where no change is needed. */
9239 && !(PT == XFASTINT (w->last_point)
8850a573
RS
9240 && XFASTINT (w->last_modified) >= MODIFF
9241 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
9242 && XFASTINT (w->column_number_displayed) != current_column ())
9243 update_mode_line = 1;
9244
5f5c8ee5
GM
9245 /* Count number of windows showing the selected buffer. An indirect
9246 buffer counts as its base buffer. */
9247 if (!just_this_one_p)
42640f83
RS
9248 {
9249 struct buffer *current_base, *window_base;
9250 current_base = current_buffer;
9251 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
9252 if (current_base->base_buffer)
9253 current_base = current_base->base_buffer;
9254 if (window_base->base_buffer)
9255 window_base = window_base->base_buffer;
9256 if (current_base == window_base)
9257 buffer_shared++;
9258 }
a2889657 9259
5f5c8ee5
GM
9260 /* Point refers normally to the selected window. For any other
9261 window, set up appropriate value. */
a2889657
JB
9262 if (!EQ (window, selected_window))
9263 {
12adba34
RS
9264 int new_pt = XMARKER (w->pointm)->charpos;
9265 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 9266 if (new_pt < BEGV)
a2889657 9267 {
f67a0f51 9268 new_pt = BEGV;
12adba34
RS
9269 new_pt_byte = BEGV_BYTE;
9270 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 9271 }
f67a0f51 9272 else if (new_pt > (ZV - 1))
a2889657 9273 {
f67a0f51 9274 new_pt = ZV;
12adba34
RS
9275 new_pt_byte = ZV_BYTE;
9276 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 9277 }
5f5c8ee5 9278
f67a0f51 9279 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 9280 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
9281 }
9282
f4faa47c 9283 /* If any of the character widths specified in the display table
5f5c8ee5
GM
9284 have changed, invalidate the width run cache. It's true that
9285 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
9286 redisplay goes (non-fatally) haywire when the display table is
9287 changed, so why should we worry about doing any better? */
9288 if (current_buffer->width_run_cache)
9289 {
f908610f 9290 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
9291
9292 if (! disptab_matches_widthtab (disptab,
9293 XVECTOR (current_buffer->width_table)))
9294 {
9295 invalidate_region_cache (current_buffer,
9296 current_buffer->width_run_cache,
9297 BEG, Z);
9298 recompute_width_table (current_buffer, disptab);
9299 }
9300 }
9301
a2889657 9302 /* If window-start is screwed up, choose a new one. */
a2889657
JB
9303 if (XMARKER (w->start)->buffer != current_buffer)
9304 goto recenter;
9305
5f5c8ee5 9306 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 9307
cf0df6ab
RS
9308 /* If someone specified a new starting point but did not insist,
9309 check whether it can be used. */
cfad01b4
GM
9310 if (!NILP (w->optional_new_start)
9311 && CHARPOS (startp) >= BEGV
9312 && CHARPOS (startp) <= ZV)
cf0df6ab
RS
9313 {
9314 w->optional_new_start = Qnil;
5f5c8ee5
GM
9315 start_display (&it, w, startp);
9316 move_it_to (&it, PT, 0, it.last_visible_y, -1,
9317 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
9318 if (IT_CHARPOS (it) == PT)
cf0df6ab
RS
9319 w->force_start = Qt;
9320 }
9321
8de2d90b 9322 /* Handle case where place to start displaying has been specified,
aa6d10fa 9323 unless the specified location is outside the accessible range. */
9472f927
GM
9324 if (!NILP (w->force_start)
9325 || w->frozen_window_start_p)
a2889657 9326 {
e63574d7 9327 w->force_start = Qnil;
5f5c8ee5 9328 w->vscroll = 0;
b5174a51 9329 w->window_end_valid = Qnil;
5f5c8ee5
GM
9330
9331 /* Forget any recorded base line for line number display. */
9332 if (!current_matrix_up_to_date_p
9333 || current_buffer->clip_changed)
9334 w->base_line_number = Qnil;
9335
75c43375
RS
9336 /* Redisplay the mode line. Select the buffer properly for that.
9337 Also, run the hook window-scroll-functions
9338 because we have scrolled. */
e63574d7
RS
9339 /* Note, we do this after clearing force_start because
9340 if there's an error, it is better to forget about force_start
9341 than to get into an infinite loop calling the hook functions
9342 and having them get more errors. */
75c43375
RS
9343 if (!update_mode_line
9344 || ! NILP (Vwindow_scroll_functions))
e481f960 9345 {
e481f960
RS
9346 update_mode_line = 1;
9347 w->update_mode_line = Qt;
5f5c8ee5 9348 startp = run_window_scroll_functions (window, startp);
e481f960 9349 }
5f5c8ee5 9350
c2213350 9351 XSETFASTINT (w->last_modified, 0);
8850a573 9352 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5
GM
9353 if (CHARPOS (startp) < BEGV)
9354 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
9355 else if (CHARPOS (startp) > ZV)
9356 SET_TEXT_POS (startp, ZV, ZV_BYTE);
9357
9358 /* Redisplay, then check if cursor has been set during the
9359 redisplay. Give up if new fonts were loaded. */
9360 if (!try_window (window, startp))
9361 {
9362 w->force_start = Qt;
9363 clear_glyph_matrix (w->desired_matrix);
9364 goto restore_buffers;
9365 }
9366
9472f927 9367 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5 9368 {
b28cb6ed
GM
9369 /* If point does not appear, try to move point so it does
9370 appear. The desired matrix has been built above, so we
9371 can use it here. */
9372 int window_height;
9373 struct glyph_row *row;
9374
9375 window_height = window_box_height (w) / 2;
9376 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
9377 while (MATRIX_ROW_BOTTOM_Y (row) < window_height)
5f5c8ee5
GM
9378 ++row;
9379
9380 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
9381 MATRIX_ROW_START_BYTEPOS (row));
9382
90adcf20 9383 if (w != XWINDOW (selected_window))
12adba34 9384 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
9385 else if (current_buffer == old)
9386 SET_TEXT_POS (lpoint, PT, PT_BYTE);
9387
9388 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
9389
9390 /* If we are highlighting the region, then we just changed
9391 the region, so redisplay to show it. */
df0b5ea1
RS
9392 if (!NILP (Vtransient_mark_mode)
9393 && !NILP (current_buffer->mark_active))
6f27fa9b 9394 {
5f5c8ee5
GM
9395 clear_glyph_matrix (w->desired_matrix);
9396 if (!try_window (window, startp))
9397 goto restore_buffers;
6f27fa9b 9398 }
a2889657 9399 }
5f5c8ee5
GM
9400
9401 make_cursor_line_fully_visible (w);
9402#if GLYPH_DEBUG
9403 debug_method_add (w, "forced window start");
9404#endif
a2889657
JB
9405 goto done;
9406 }
9407
5f5c8ee5
GM
9408 /* Handle case where text has not changed, only point, and it has
9409 not moved off the frame. */
9410 if (current_matrix_up_to_date_p
47589c8c
GM
9411 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
9412 rc != 0))
a2889657 9413 {
47589c8c 9414 if (rc == -1)
5f5c8ee5 9415 goto try_to_scroll;
47589c8c
GM
9416 else
9417 goto done;
a2889657
JB
9418 }
9419 /* If current starting point was originally the beginning of a line
9420 but no longer is, find a new starting point. */
265a9e55 9421 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
9422 && !(CHARPOS (startp) <= BEGV
9423 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 9424 {
5f5c8ee5
GM
9425#if GLYPH_DEBUG
9426 debug_method_add (w, "recenter 1");
9427#endif
a2889657
JB
9428 goto recenter;
9429 }
5f5c8ee5
GM
9430
9431 /* Try scrolling with try_window_id. */
9142dd5b
GM
9432 else if (/* Windows and buffers haven't changed. */
9433 !windows_or_buffers_changed
5f5c8ee5
GM
9434 /* Window must be either use window-based redisplay or
9435 be full width. */
9436 && (FRAME_WINDOW_P (f)
c59c668a 9437 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)))
5f5c8ee5
GM
9438 && !MINI_WINDOW_P (w)
9439 /* Point is not known NOT to appear in window. */
9440 && PT >= CHARPOS (startp)
a2889657 9441 && XFASTINT (w->last_modified)
5f5c8ee5
GM
9442 /* Window is not hscrolled. */
9443 && XFASTINT (w->hscroll) == 0
9444 /* Selective display has not changed. */
9445 && !current_buffer->clip_changed
9446 /* Current matrix is up to date. */
9447 && !NILP (w->window_end_valid)
9448 /* Can't use this case if highlighting a region because
9449 a cursor movement will do more than just set the cursor. */
bd66d1ba
RS
9450 && !(!NILP (Vtransient_mark_mode)
9451 && !NILP (current_buffer->mark_active))
9452 && NILP (w->region_showing)
8f897821 9453 && NILP (Vshow_trailing_whitespace)
5f5c8ee5 9454 /* Overlay arrow position and string not changed. */
d45de95b 9455 && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
a2889657 9456 && EQ (last_arrow_string, Voverlay_arrow_string)
5f5c8ee5
GM
9457 /* Value is > 0 if update has been done, it is -1 if we
9458 know that the same window start will not work. It is 0
9459 if unsuccessful for some other reason. */
9460 && (tem = try_window_id (w)) != 0)
a2889657 9461 {
5f5c8ee5 9462#if GLYPH_DEBUG
ef121659 9463 debug_method_add (w, "try_window_id %d", tem);
5f5c8ee5
GM
9464#endif
9465
9466 if (fonts_changed_p)
9467 goto restore_buffers;
a2889657
JB
9468 if (tem > 0)
9469 goto done;
ef121659 9470
5f5c8ee5
GM
9471 /* Otherwise try_window_id has returned -1 which means that we
9472 don't want the alternative below this comment to execute. */
a2889657 9473 }
5f5c8ee5
GM
9474 else if (CHARPOS (startp) >= BEGV
9475 && CHARPOS (startp) <= ZV
9476 && PT >= CHARPOS (startp)
9477 && (CHARPOS (startp) < ZV
e9874cee 9478 /* Avoid starting at end of buffer. */
5f5c8ee5 9479 || CHARPOS (startp) == BEGV
8850a573
RS
9480 || (XFASTINT (w->last_modified) >= MODIFF
9481 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 9482 {
5f5c8ee5
GM
9483#if GLYPH_DEBUG
9484 debug_method_add (w, "same window start");
9485#endif
9486
9487 /* Try to redisplay starting at same place as before.
9488 If point has not moved off frame, accept the results. */
9489 if (!current_matrix_up_to_date_p
9490 /* Don't use try_window_reusing_current_matrix in this case
15e26c76
GM
9491 because a window scroll function can have changed the
9492 buffer. */
5f5c8ee5
GM
9493 || !NILP (Vwindow_scroll_functions)
9494 || MINI_WINDOW_P (w)
9495 || !try_window_reusing_current_matrix (w))
9496 {
9497 IF_DEBUG (debug_method_add (w, "1"));
9498 try_window (window, startp);
9499 }
9500
9501 if (fonts_changed_p)
9502 goto restore_buffers;
9503
9504 if (w->cursor.vpos >= 0)
aa6d10fa 9505 {
5f5c8ee5
GM
9506 if (!just_this_one_p
9507 || current_buffer->clip_changed
9142dd5b 9508 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
9509 /* Forget any recorded base line for line number display. */
9510 w->base_line_number = Qnil;
5f5c8ee5
GM
9511
9512 make_cursor_line_fully_visible (w);
aa6d10fa
RS
9513 goto done;
9514 }
a2889657 9515 else
5f5c8ee5 9516 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
9517 }
9518
5f5c8ee5
GM
9519 try_to_scroll:
9520
c2213350 9521 XSETFASTINT (w->last_modified, 0);
8850a573 9522 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5 9523
e481f960
RS
9524 /* Redisplay the mode line. Select the buffer properly for that. */
9525 if (!update_mode_line)
9526 {
e481f960
RS
9527 update_mode_line = 1;
9528 w->update_mode_line = Qt;
9529 }
a2889657 9530
5f5c8ee5
GM
9531 /* Try to scroll by specified few lines. */
9532 if ((scroll_conservatively
9533 || scroll_step
9534 || temp_scroll_step
9535 || NUMBERP (current_buffer->scroll_up_aggressively)
9536 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 9537 && !current_buffer->clip_changed
5f5c8ee5
GM
9538 && CHARPOS (startp) >= BEGV
9539 && CHARPOS (startp) <= ZV)
0789adb2 9540 {
5f5c8ee5
GM
9541 /* The function returns -1 if new fonts were loaded, 1 if
9542 successful, 0 if not successful. */
9543 int rc = try_scrolling (window, just_this_one_p,
9544 scroll_conservatively,
9545 scroll_step,
9546 temp_scroll_step);
9547 if (rc > 0)
9548 goto done;
9549 else if (rc < 0)
9550 goto restore_buffers;
9551 }
f9c8af06 9552
5f5c8ee5 9553 /* Finally, just choose place to start which centers point */
5936754e 9554
5f5c8ee5 9555 recenter:
44173109 9556
5f5c8ee5
GM
9557#if GLYPH_DEBUG
9558 debug_method_add (w, "recenter");
9559#endif
0789adb2 9560
5f5c8ee5 9561 /* w->vscroll = 0; */
0789adb2 9562
5f5c8ee5
GM
9563 /* Forget any previously recorded base line for line number display. */
9564 if (!current_matrix_up_to_date_p
9565 || current_buffer->clip_changed)
9566 w->base_line_number = Qnil;
9567
9568 /* Move backward half the height of the window. */
9569 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
9570 it.current_y = it.last_visible_y;
9571 move_it_vertically_backward (&it, it.last_visible_y / 2);
9572 xassert (IT_CHARPOS (it) >= BEGV);
9573
9574 /* The function move_it_vertically_backward may move over more
9575 than the specified y-distance. If it->w is small, e.g. a
9576 mini-buffer window, we may end up in front of the window's
9577 display area. Start displaying at the start of the line
9578 containing PT in this case. */
9579 if (it.current_y <= 0)
9580 {
9581 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
9582 move_it_vertically (&it, 0);
9583 xassert (IT_CHARPOS (it) <= PT);
9584 it.current_y = 0;
0789adb2
RS
9585 }
9586
5f5c8ee5
GM
9587 it.current_x = it.hpos = 0;
9588
9589 /* Set startp here explicitly in case that helps avoid an infinite loop
9590 in case the window-scroll-functions functions get errors. */
9591 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
9592
9593 /* Run scroll hooks. */
9594 startp = run_window_scroll_functions (window, it.current.pos);
9595
9596 /* Redisplay the window. */
9597 if (!current_matrix_up_to_date_p
9598 || windows_or_buffers_changed
9599 /* Don't use try_window_reusing_current_matrix in this case
9600 because it can have changed the buffer. */
9601 || !NILP (Vwindow_scroll_functions)
9602 || !just_this_one_p
9603 || MINI_WINDOW_P (w)
9604 || !try_window_reusing_current_matrix (w))
9605 try_window (window, startp);
9606
9607 /* If new fonts have been loaded (due to fontsets), give up. We
9608 have to start a new redisplay since we need to re-adjust glyph
9609 matrices. */
9610 if (fonts_changed_p)
9611 goto restore_buffers;
9612
9613 /* If cursor did not appear assume that the middle of the window is
9614 in the first line of the window. Do it again with the next line.
9615 (Imagine a window of height 100, displaying two lines of height
9616 60. Moving back 50 from it->last_visible_y will end in the first
9617 line.) */
9618 if (w->cursor.vpos < 0)
a2889657 9619 {
5f5c8ee5
GM
9620 if (!NILP (w->window_end_valid)
9621 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 9622 {
5f5c8ee5
GM
9623 clear_glyph_matrix (w->desired_matrix);
9624 move_it_by_lines (&it, 1, 0);
9625 try_window (window, it.current.pos);
a2889657 9626 }
5f5c8ee5 9627 else if (PT < IT_CHARPOS (it))
a2889657 9628 {
5f5c8ee5
GM
9629 clear_glyph_matrix (w->desired_matrix);
9630 move_it_by_lines (&it, -1, 0);
9631 try_window (window, it.current.pos);
9632 }
9633 else
9634 {
9635 /* Not much we can do about it. */
a2889657 9636 }
a2889657 9637 }
010494d0 9638
5f5c8ee5
GM
9639 /* Consider the following case: Window starts at BEGV, there is
9640 invisible, intangible text at BEGV, so that display starts at
9641 some point START > BEGV. It can happen that we are called with
9642 PT somewhere between BEGV and START. Try to handle that case. */
9643 if (w->cursor.vpos < 0)
835766b6 9644 {
5f5c8ee5
GM
9645 struct glyph_row *row = w->current_matrix->rows;
9646 if (row->mode_line_p)
9647 ++row;
9648 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 9649 }
5f5c8ee5
GM
9650
9651 make_cursor_line_fully_visible (w);
b5174a51 9652
74d481ac
GM
9653 done:
9654
5f5c8ee5
GM
9655 SET_TEXT_POS_FROM_MARKER (startp, w->start);
9656 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
9657 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
9658 ? Qt : Qnil);
a2889657 9659
5f5c8ee5 9660 /* Display the mode line, if we must. */
e481f960 9661 if ((update_mode_line
aa6d10fa 9662 /* If window not full width, must redo its mode line
5f5c8ee5
GM
9663 if (a) the window to its side is being redone and
9664 (b) we do a frame-based redisplay. This is a consequence
9665 of how inverted lines are drawn in frame-based redisplay. */
9666 || (!just_this_one_p
9667 && !FRAME_WINDOW_P (f)
9668 && !WINDOW_FULL_WIDTH_P (w))
9669 /* Line number to display. */
155ef550 9670 || INTEGERP (w->base_line_pos)
5f5c8ee5 9671 /* Column number is displayed and different from the one displayed. */
155ef550
KH
9672 || (!NILP (w->column_number_displayed)
9673 && XFASTINT (w->column_number_displayed) != current_column ()))
5f5c8ee5
GM
9674 /* This means that the window has a mode line. */
9675 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 9676 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 9677 {
5da11938
GM
9678 Lisp_Object old_selected_frame;
9679
9680 old_selected_frame = selected_frame;
9681
5da11938 9682 XSETFRAME (selected_frame, f);
5f5c8ee5 9683 display_mode_lines (w);
5da11938 9684 selected_frame = old_selected_frame;
5f5c8ee5
GM
9685
9686 /* If mode line height has changed, arrange for a thorough
9687 immediate redisplay using the correct mode line height. */
9688 if (WINDOW_WANTS_MODELINE_P (w)
9689 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 9690 {
5f5c8ee5
GM
9691 fonts_changed_p = 1;
9692 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
9693 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 9694 }
5f5c8ee5
GM
9695
9696 /* If top line height has changed, arrange for a thorough
9697 immediate redisplay using the correct mode line height. */
045dee35
GM
9698 if (WINDOW_WANTS_HEADER_LINE_P (w)
9699 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
9700 {
9701 fonts_changed_p = 1;
045dee35
GM
9702 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
9703 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9704 }
9705
9706 if (fonts_changed_p)
9707 goto restore_buffers;
5ba50c51 9708 }
5f5c8ee5
GM
9709
9710 if (!line_number_displayed
9711 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
9712 {
9713 w->base_line_pos = Qnil;
9714 w->base_line_number = Qnil;
9715 }
a2889657 9716
5f5c8ee5
GM
9717 finish_menu_bars:
9718
7ce2c095 9719 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 9720 if (update_mode_line
5f5c8ee5
GM
9721 && EQ (FRAME_SELECTED_WINDOW (f), window))
9722 {
9723 int redisplay_menu_p = 0;
9724
9725 if (FRAME_WINDOW_P (f))
9726 {
1a578e9b 9727#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
5f5c8ee5 9728 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 9729#else
5f5c8ee5 9730 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 9731#endif
5f5c8ee5
GM
9732 }
9733 else
9734 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
9735
9736 if (redisplay_menu_p)
9737 display_menu_bar (w);
9738
9739#ifdef HAVE_WINDOW_SYSTEM
e037b9ec
GM
9740 if (WINDOWP (f->tool_bar_window)
9741 && (FRAME_TOOL_BAR_LINES (f) > 0
9742 || auto_resize_tool_bars_p))
9743 redisplay_tool_bar (f);
5f5c8ee5
GM
9744#endif
9745 }
7ce2c095 9746
88f22aff 9747 finish_scroll_bars:
5f5c8ee5 9748
88f22aff 9749 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 9750 {
b1d1124b 9751 int start, end, whole;
30c566e4 9752
b1d1124b 9753 /* Calculate the start and end positions for the current window.
3505ea70
JB
9754 At some point, it would be nice to choose between scrollbars
9755 which reflect the whole buffer size, with special markers
9756 indicating narrowing, and scrollbars which reflect only the
9757 visible region.
9758
5f5c8ee5 9759 Note that mini-buffers sometimes aren't displaying any text. */
c6e89d6c 9760 if (!MINI_WINDOW_P (w)
5f5c8ee5 9761 || (w == XWINDOW (minibuf_window)
c6e89d6c 9762 && NILP (echo_area_buffer[0])))
b1d1124b 9763 {
8a9311d7 9764 whole = ZV - BEGV;
4d641a15 9765 start = marker_position (w->start) - BEGV;
b1d1124b
JB
9766 /* I don't think this is guaranteed to be right. For the
9767 moment, we'll pretend it is. */
5f5c8ee5 9768 end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
3505ea70 9769
5f5c8ee5
GM
9770 if (end < start)
9771 end = start;
9772 if (whole < (end - start))
9773 whole = end - start;
b1d1124b
JB
9774 }
9775 else
9776 start = end = whole = 0;
30c566e4 9777
88f22aff 9778 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 9779 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 9780
5f5c8ee5
GM
9781 /* Note that we actually used the scroll bar attached to this
9782 window, so it shouldn't be deleted at the end of redisplay. */
88f22aff 9783 (*redeem_scroll_bar_hook) (w);
30c566e4 9784 }
b1d1124b 9785
5f5c8ee5
GM
9786 restore_buffers:
9787
9788 /* Restore current_buffer and value of point in it. */
9789 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
6a93695f 9790 set_buffer_internal_1 (old);
5f5c8ee5 9791 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
9792
9793 unbind_to (count, Qnil);
a2889657 9794}
a2889657 9795
5f5c8ee5
GM
9796
9797/* Build the complete desired matrix of WINDOW with a window start
9798 buffer position POS. Value is non-zero if successful. It is zero
9799 if fonts were loaded during redisplay which makes re-adjusting
9800 glyph matrices necessary. */
9801
9802int
a2889657
JB
9803try_window (window, pos)
9804 Lisp_Object window;
5f5c8ee5
GM
9805 struct text_pos pos;
9806{
9807 struct window *w = XWINDOW (window);
9808 struct it it;
9809 struct glyph_row *last_text_row = NULL;
9cbab4ff 9810
5f5c8ee5
GM
9811 /* Make POS the new window start. */
9812 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 9813
5f5c8ee5
GM
9814 /* Mark cursor position as unknown. No overlay arrow seen. */
9815 w->cursor.vpos = -1;
a2889657 9816 overlay_arrow_seen = 0;
642eefc6 9817
5f5c8ee5
GM
9818 /* Initialize iterator and info to start at POS. */
9819 start_display (&it, w, pos);
a2889657 9820
5f5c8ee5
GM
9821 /* Display all lines of W. */
9822 while (it.current_y < it.last_visible_y)
9823 {
9824 if (display_line (&it))
9825 last_text_row = it.glyph_row - 1;
9826 if (fonts_changed_p)
9827 return 0;
9828 }
a2889657 9829
5f5c8ee5
GM
9830 /* If bottom moved off end of frame, change mode line percentage. */
9831 if (XFASTINT (w->window_end_pos) <= 0
9832 && Z != IT_CHARPOS (it))
a2889657
JB
9833 w->update_mode_line = Qt;
9834
5f5c8ee5
GM
9835 /* Set window_end_pos to the offset of the last character displayed
9836 on the window from the end of current_buffer. Set
9837 window_end_vpos to its row number. */
9838 if (last_text_row)
9839 {
9840 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
9841 w->window_end_bytepos
9842 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9843 XSETFASTINT (w->window_end_pos,
9844 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9845 XSETFASTINT (w->window_end_vpos,
9846 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9847 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
9848 ->displays_text_p);
9849 }
9850 else
9851 {
9852 w->window_end_bytepos = 0;
9853 XSETFASTINT (w->window_end_pos, 0);
9854 XSETFASTINT (w->window_end_vpos, 0);
9855 }
9856
a2889657
JB
9857 /* But that is not valid info until redisplay finishes. */
9858 w->window_end_valid = Qnil;
5f5c8ee5 9859 return 1;
a2889657 9860}
5f5c8ee5
GM
9861
9862
a2889657 9863\f
5f5c8ee5
GM
9864/************************************************************************
9865 Window redisplay reusing current matrix when buffer has not changed
9866 ************************************************************************/
9867
9868/* Try redisplay of window W showing an unchanged buffer with a
9869 different window start than the last time it was displayed by
9870 reusing its current matrix. Value is non-zero if successful.
9871 W->start is the new window start. */
a2889657
JB
9872
9873static int
5f5c8ee5
GM
9874try_window_reusing_current_matrix (w)
9875 struct window *w;
a2889657 9876{
5f5c8ee5
GM
9877 struct frame *f = XFRAME (w->frame);
9878 struct glyph_row *row, *bottom_row;
9879 struct it it;
9880 struct run run;
9881 struct text_pos start, new_start;
9882 int nrows_scrolled, i;
9883 struct glyph_row *last_text_row;
9884 struct glyph_row *last_reused_text_row;
9885 struct glyph_row *start_row;
9886 int start_vpos, min_y, max_y;
d18354b6
GM
9887
9888 if (/* This function doesn't handle terminal frames. */
9889 !FRAME_WINDOW_P (f)
9890 /* Don't try to reuse the display if windows have been split
9891 or such. */
9892 || windows_or_buffers_changed)
5f5c8ee5 9893 return 0;
a2889657 9894
5f5c8ee5
GM
9895 /* Can't do this if region may have changed. */
9896 if ((!NILP (Vtransient_mark_mode)
9897 && !NILP (current_buffer->mark_active))
8f897821
GM
9898 || !NILP (w->region_showing)
9899 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 9900 return 0;
a2889657 9901
5f5c8ee5 9902 /* If top-line visibility has changed, give up. */
045dee35
GM
9903 if (WINDOW_WANTS_HEADER_LINE_P (w)
9904 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
9905 return 0;
9906
9907 /* Give up if old or new display is scrolled vertically. We could
9908 make this function handle this, but right now it doesn't. */
9909 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9910 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
9911 return 0;
9912
9913 /* The variable new_start now holds the new window start. The old
9914 start `start' can be determined from the current matrix. */
9915 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
9916 start = start_row->start.pos;
9917 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 9918
5f5c8ee5
GM
9919 /* Clear the desired matrix for the display below. */
9920 clear_glyph_matrix (w->desired_matrix);
9921
9922 if (CHARPOS (new_start) <= CHARPOS (start))
9923 {
9924 int first_row_y;
9925
9926 IF_DEBUG (debug_method_add (w, "twu1"));
9927
9928 /* Display up to a row that can be reused. The variable
9929 last_text_row is set to the last row displayed that displays
b48f74cb
GM
9930 text. Note that it.vpos == 0 if or if not there is a
9931 header-line; it's not the same as the MATRIX_ROW_VPOS! */
5f5c8ee5
GM
9932 start_display (&it, w, new_start);
9933 first_row_y = it.current_y;
9934 w->cursor.vpos = -1;
9935 last_text_row = last_reused_text_row = NULL;
b48f74cb 9936
5f5c8ee5
GM
9937 while (it.current_y < it.last_visible_y
9938 && IT_CHARPOS (it) < CHARPOS (start)
9939 && !fonts_changed_p)
9940 if (display_line (&it))
9941 last_text_row = it.glyph_row - 1;
9942
9943 /* A value of current_y < last_visible_y means that we stopped
9944 at the previous window start, which in turn means that we
9945 have at least one reusable row. */
9946 if (it.current_y < it.last_visible_y)
a2889657 9947 {
b48f74cb 9948 /* IT.vpos always starts from 0; it counts text lines. */
5f5c8ee5
GM
9949 nrows_scrolled = it.vpos;
9950
9951 /* Find PT if not already found in the lines displayed. */
9952 if (w->cursor.vpos < 0)
a2889657 9953 {
5f5c8ee5
GM
9954 int dy = it.current_y - first_row_y;
9955
9956 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9957 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9958 {
9959 if (PT >= MATRIX_ROW_START_CHARPOS (row)
9960 && PT < MATRIX_ROW_END_CHARPOS (row))
9961 {
9962 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
9963 dy, nrows_scrolled);
9964 break;
9965 }
9966
9967 if (MATRIX_ROW_BOTTOM_Y (row) + dy >= it.last_visible_y)
9968 break;
9969
9970 ++row;
9971 }
9972
9973 /* Give up if point was not found. This shouldn't
9974 happen often; not more often than with try_window
9975 itself. */
9976 if (w->cursor.vpos < 0)
9977 {
9978 clear_glyph_matrix (w->desired_matrix);
9979 return 0;
9980 }
a2889657 9981 }
5f5c8ee5
GM
9982
9983 /* Scroll the display. Do it before the current matrix is
9984 changed. The problem here is that update has not yet
9985 run, i.e. part of the current matrix is not up to date.
9986 scroll_run_hook will clear the cursor, and use the
9987 current matrix to get the height of the row the cursor is
9988 in. */
9989 run.current_y = first_row_y;
9990 run.desired_y = it.current_y;
9991 run.height = it.last_visible_y - it.current_y;
b48f74cb
GM
9992
9993 if (run.height > 0 && run.current_y != run.desired_y)
a2889657 9994 {
5f5c8ee5
GM
9995 update_begin (f);
9996 rif->update_window_begin_hook (w);
64d1e7d3 9997 rif->clear_mouse_face (w);
5f5c8ee5 9998 rif->scroll_run_hook (w, &run);
64d1e7d3 9999 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5 10000 update_end (f);
a2889657 10001 }
5f5c8ee5
GM
10002
10003 /* Shift current matrix down by nrows_scrolled lines. */
10004 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
10005 rotate_matrix (w->current_matrix,
10006 start_vpos,
10007 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
10008 nrows_scrolled);
10009
10010 /* Disable lines not reused. */
10011 for (i = 0; i < it.vpos; ++i)
b48f74cb 10012 (start_row + i)->enabled_p = 0;
5f5c8ee5
GM
10013
10014 /* Re-compute Y positions. */
045dee35 10015 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5 10016 max_y = it.last_visible_y;
b48f74cb
GM
10017 for (row = start_row + nrows_scrolled;
10018 row < bottom_row;
10019 ++row)
d2f84654 10020 {
5f5c8ee5
GM
10021 row->y = it.current_y;
10022
10023 if (row->y < min_y)
10024 row->visible_height = row->height - (min_y - row->y);
10025 else if (row->y + row->height > max_y)
10026 row->visible_height
10027 = row->height - (row->y + row->height - max_y);
10028 else
10029 row->visible_height = row->height;
10030
10031 it.current_y += row->height;
5f5c8ee5
GM
10032
10033 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
10034 last_reused_text_row = row;
10035 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
10036 break;
d2f84654 10037 }
a2889657 10038 }
5f5c8ee5
GM
10039
10040 /* Update window_end_pos etc.; last_reused_text_row is the last
10041 reused row from the current matrix containing text, if any.
10042 The value of last_text_row is the last displayed line
10043 containing text. */
10044 if (last_reused_text_row)
a2889657 10045 {
5f5c8ee5
GM
10046 w->window_end_bytepos
10047 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
10048 XSETFASTINT (w->window_end_pos,
10049 Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
10050 XSETFASTINT (w->window_end_vpos,
10051 MATRIX_ROW_VPOS (last_reused_text_row,
10052 w->current_matrix));
a2889657 10053 }
5f5c8ee5
GM
10054 else if (last_text_row)
10055 {
10056 w->window_end_bytepos
10057 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
10058 XSETFASTINT (w->window_end_pos,
10059 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10060 XSETFASTINT (w->window_end_vpos,
10061 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
10062 }
10063 else
10064 {
10065 /* This window must be completely empty. */
10066 w->window_end_bytepos = 0;
10067 XSETFASTINT (w->window_end_pos, 0);
10068 XSETFASTINT (w->window_end_vpos, 0);
10069 }
10070 w->window_end_valid = Qnil;
a2889657 10071
5f5c8ee5
GM
10072 /* Update hint: don't try scrolling again in update_window. */
10073 w->desired_matrix->no_scrolling_p = 1;
10074
10075#if GLYPH_DEBUG
10076 debug_method_add (w, "try_window_reusing_current_matrix 1");
10077#endif
10078 return 1;
a2889657 10079 }
5f5c8ee5
GM
10080 else if (CHARPOS (new_start) > CHARPOS (start))
10081 {
10082 struct glyph_row *pt_row, *row;
10083 struct glyph_row *first_reusable_row;
10084 struct glyph_row *first_row_to_display;
10085 int dy;
10086 int yb = window_text_bottom_y (w);
10087
10088 IF_DEBUG (debug_method_add (w, "twu2"));
10089
10090 /* Find the row starting at new_start, if there is one. Don't
10091 reuse a partially visible line at the end. */
b48f74cb 10092 first_reusable_row = start_row;
5f5c8ee5
GM
10093 while (first_reusable_row->enabled_p
10094 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
10095 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
10096 < CHARPOS (new_start)))
10097 ++first_reusable_row;
10098
10099 /* Give up if there is no row to reuse. */
10100 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
10101 || !first_reusable_row->enabled_p
10102 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
10103 != CHARPOS (new_start)))
5f5c8ee5
GM
10104 return 0;
10105
5f5c8ee5
GM
10106 /* We can reuse fully visible rows beginning with
10107 first_reusable_row to the end of the window. Set
10108 first_row_to_display to the first row that cannot be reused.
10109 Set pt_row to the row containing point, if there is any. */
10110 first_row_to_display = first_reusable_row;
10111 pt_row = NULL;
10112 while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb)
10113 {
10114 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
10115 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
10116 pt_row = first_row_to_display;
a2889657 10117
5f5c8ee5
GM
10118 ++first_row_to_display;
10119 }
a2889657 10120
5f5c8ee5
GM
10121 /* Start displaying at the start of first_row_to_display. */
10122 xassert (first_row_to_display->y < yb);
10123 init_to_row_start (&it, w, first_row_to_display);
b48f74cb
GM
10124 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
10125 - start_vpos);
5f5c8ee5
GM
10126 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
10127 - nrows_scrolled);
b48f74cb
GM
10128 it.current_y = (first_row_to_display->y - first_reusable_row->y
10129 + WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
10130
10131 /* Display lines beginning with first_row_to_display in the
10132 desired matrix. Set last_text_row to the last row displayed
10133 that displays text. */
10134 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
10135 if (pt_row == NULL)
10136 w->cursor.vpos = -1;
10137 last_text_row = NULL;
10138 while (it.current_y < it.last_visible_y && !fonts_changed_p)
10139 if (display_line (&it))
10140 last_text_row = it.glyph_row - 1;
10141
10142 /* Give up If point isn't in a row displayed or reused. */
10143 if (w->cursor.vpos < 0)
10144 {
10145 clear_glyph_matrix (w->desired_matrix);
10146 return 0;
10147 }
12adba34 10148
5f5c8ee5
GM
10149 /* If point is in a reused row, adjust y and vpos of the cursor
10150 position. */
10151 if (pt_row)
10152 {
10153 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
10154 w->current_matrix);
10155 w->cursor.y -= first_reusable_row->y;
a2889657
JB
10156 }
10157
5f5c8ee5
GM
10158 /* Scroll the display. */
10159 run.current_y = first_reusable_row->y;
045dee35 10160 run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5 10161 run.height = it.last_visible_y - run.current_y;
4da61803
GM
10162 dy = run.current_y - run.desired_y;
10163
5f5c8ee5
GM
10164 if (run.height)
10165 {
10166 struct frame *f = XFRAME (WINDOW_FRAME (w));
10167 update_begin (f);
10168 rif->update_window_begin_hook (w);
64d1e7d3 10169 rif->clear_mouse_face (w);
5f5c8ee5 10170 rif->scroll_run_hook (w, &run);
64d1e7d3 10171 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
10172 update_end (f);
10173 }
a2889657 10174
5f5c8ee5
GM
10175 /* Adjust Y positions of reused rows. */
10176 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
045dee35 10177 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5 10178 max_y = it.last_visible_y;
b48f74cb 10179 for (row = first_reusable_row; row < first_row_to_display; ++row)
5f5c8ee5
GM
10180 {
10181 row->y -= dy;
10182 if (row->y < min_y)
10183 row->visible_height = row->height - (min_y - row->y);
10184 else if (row->y + row->height > max_y)
10185 row->visible_height
10186 = row->height - (row->y + row->height - max_y);
10187 else
10188 row->visible_height = row->height;
5f5c8ee5 10189 }
a2889657 10190
5f5c8ee5
GM
10191 /* Disable rows not reused. */
10192 while (row < bottom_row)
10193 {
10194 row->enabled_p = 0;
10195 ++row;
10196 }
10197
10198 /* Scroll the current matrix. */
10199 xassert (nrows_scrolled > 0);
10200 rotate_matrix (w->current_matrix,
10201 start_vpos,
10202 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
10203 -nrows_scrolled);
10204
10205 /* Adjust window end. A null value of last_text_row means that
10206 the window end is in reused rows which in turn means that
10207 only its vpos can have changed. */
10208 if (last_text_row)
10209 {
10210 w->window_end_bytepos
10211 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
10212 XSETFASTINT (w->window_end_pos,
10213 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10214 XSETFASTINT (w->window_end_vpos,
10215 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
10216 }
10217 else
a2889657 10218 {
e8e536a9 10219 XSETFASTINT (w->window_end_vpos,
5f5c8ee5 10220 XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 10221 }
5f5c8ee5
GM
10222
10223 w->window_end_valid = Qnil;
10224 w->desired_matrix->no_scrolling_p = 1;
10225
10226#if GLYPH_DEBUG
10227 debug_method_add (w, "try_window_reusing_current_matrix 2");
10228#endif
10229 return 1;
a2889657 10230 }
5f5c8ee5
GM
10231
10232 return 0;
10233}
a2889657 10234
a2889657 10235
5f5c8ee5
GM
10236\f
10237/************************************************************************
10238 Window redisplay reusing current matrix when buffer has changed
10239 ************************************************************************/
10240
1ec185cb
GM
10241static struct glyph_row *find_last_unchanged_at_beg_row P_ ((struct window *));
10242static struct glyph_row *find_first_unchanged_at_end_row P_ ((struct window *,
5f5c8ee5
GM
10243 int *, int *));
10244static struct glyph_row *
10245find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
10246 struct glyph_row *));
10247
10248
10249/* Return the last row in MATRIX displaying text. If row START is
10250 non-null, start searching with that row. IT gives the dimensions
10251 of the display. Value is null if matrix is empty; otherwise it is
10252 a pointer to the row found. */
10253
10254static struct glyph_row *
10255find_last_row_displaying_text (matrix, it, start)
10256 struct glyph_matrix *matrix;
10257 struct it *it;
10258 struct glyph_row *start;
10259{
10260 struct glyph_row *row, *row_found;
10261
10262 /* Set row_found to the last row in IT->w's current matrix
10263 displaying text. The loop looks funny but think of partially
10264 visible lines. */
10265 row_found = NULL;
10266 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
10267 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
10268 {
10269 xassert (row->enabled_p);
10270 row_found = row;
10271 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
10272 break;
10273 ++row;
a2889657 10274 }
5f5c8ee5
GM
10275
10276 return row_found;
10277}
10278
a2889657 10279
5f5c8ee5
GM
10280/* Return the last row in the current matrix of W that is not affected
10281 by changes at the start of current_buffer that occurred since the
10282 last time W was redisplayed. Value is null if no such row exists.
a2889657 10283
5f5c8ee5
GM
10284 The global variable beg_unchanged has to contain the number of
10285 bytes unchanged at the start of current_buffer. BEG +
10286 beg_unchanged is the buffer position of the first changed byte in
10287 current_buffer. Characters at positions < BEG + beg_unchanged are
10288 at the same buffer positions as they were when the current matrix
10289 was built. */
10290
10291static struct glyph_row *
1ec185cb 10292find_last_unchanged_at_beg_row (w)
5f5c8ee5
GM
10293 struct window *w;
10294{
9142dd5b 10295 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
10296 struct glyph_row *row;
10297 struct glyph_row *row_found = NULL;
10298 int yb = window_text_bottom_y (w);
10299
10300 /* Find the last row displaying unchanged text. */
10301 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10302 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
10303 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 10304 {
5f5c8ee5
GM
10305 if (/* If row ends before first_changed_pos, it is unchanged,
10306 except in some case. */
10307 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
10308 /* When row ends in ZV and we write at ZV it is not
10309 unchanged. */
10310 && !row->ends_at_zv_p
10311 /* When first_changed_pos is the end of a continued line,
10312 row is not unchanged because it may be no longer
10313 continued. */
10314 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
10315 && row->continued_p))
10316 row_found = row;
10317
10318 /* Stop if last visible row. */
10319 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
10320 break;
10321
10322 ++row;
a2889657
JB
10323 }
10324
5f5c8ee5 10325 return row_found;
a2889657 10326}
5f5c8ee5
GM
10327
10328
10329/* Find the first glyph row in the current matrix of W that is not
10330 affected by changes at the end of current_buffer since the last
10331 time the window was redisplayed. Return in *DELTA the number of
c59c668a
GM
10332 chars by which buffer positions in unchanged text at the end of
10333 current_buffer must be adjusted. Return in *DELTA_BYTES the
10334 corresponding number of bytes. Value is null if no such row
10335 exists, i.e. all rows are affected by changes. */
5f5c8ee5
GM
10336
10337static struct glyph_row *
1ec185cb 10338find_first_unchanged_at_end_row (w, delta, delta_bytes)
5f5c8ee5
GM
10339 struct window *w;
10340 int *delta, *delta_bytes;
a2889657 10341{
5f5c8ee5
GM
10342 struct glyph_row *row;
10343 struct glyph_row *row_found = NULL;
c581d710 10344
5f5c8ee5 10345 *delta = *delta_bytes = 0;
b2a76982 10346
1ec185cb
GM
10347 /* Display must not have been paused, otherwise the current matrix
10348 is not up to date. */
10349 if (NILP (w->window_end_valid))
10350 abort ();
10351
10352 /* A value of window_end_pos >= END_UNCHANGED means that the window
5f5c8ee5
GM
10353 end is in the range of changed text. If so, there is no
10354 unchanged row at the end of W's current matrix. */
9142dd5b 10355 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
10356 return NULL;
10357
10358 /* Set row to the last row in W's current matrix displaying text. */
10359 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
10360
5f5c8ee5
GM
10361 /* If matrix is entirely empty, no unchanged row exists. */
10362 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
10363 {
10364 /* The value of row is the last glyph row in the matrix having a
10365 meaningful buffer position in it. The end position of row
10366 corresponds to window_end_pos. This allows us to translate
10367 buffer positions in the current matrix to current buffer
10368 positions for characters not in changed text. */
10369 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
10370 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
10371 int last_unchanged_pos, last_unchanged_pos_old;
10372 struct glyph_row *first_text_row
10373 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10374
10375 *delta = Z - Z_old;
10376 *delta_bytes = Z_BYTE - Z_BYTE_old;
10377
10378 /* Set last_unchanged_pos to the buffer position of the last
10379 character in the buffer that has not been changed. Z is the
10380 index + 1 of the last byte in current_buffer, i.e. by
10381 subtracting end_unchanged we get the index of the last
10382 unchanged character, and we have to add BEG to get its buffer
10383 position. */
9142dd5b 10384 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5
GM
10385 last_unchanged_pos_old = last_unchanged_pos - *delta;
10386
10387 /* Search backward from ROW for a row displaying a line that
10388 starts at a minimum position >= last_unchanged_pos_old. */
1ec185cb 10389 for (; row > first_text_row; --row)
5f5c8ee5 10390 {
1ec185cb
GM
10391 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
10392 abort ();
5f5c8ee5
GM
10393
10394 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
10395 row_found = row;
5f5c8ee5
GM
10396 }
10397 }
10398
1ec185cb
GM
10399 if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
10400 abort ();
10401
5f5c8ee5 10402 return row_found;
c581d710
RS
10403}
10404
c581d710 10405
5f5c8ee5
GM
10406/* Make sure that glyph rows in the current matrix of window W
10407 reference the same glyph memory as corresponding rows in the
10408 frame's frame matrix. This function is called after scrolling W's
10409 current matrix on a terminal frame in try_window_id and
10410 try_window_reusing_current_matrix. */
10411
10412static void
10413sync_frame_with_window_matrix_rows (w)
10414 struct window *w;
c581d710 10415{
5f5c8ee5
GM
10416 struct frame *f = XFRAME (w->frame);
10417 struct glyph_row *window_row, *window_row_end, *frame_row;
10418
10419 /* Preconditions: W must be a leaf window and full-width. Its frame
10420 must have a frame matrix. */
10421 xassert (NILP (w->hchild) && NILP (w->vchild));
10422 xassert (WINDOW_FULL_WIDTH_P (w));
10423 xassert (!FRAME_WINDOW_P (f));
10424
10425 /* If W is a full-width window, glyph pointers in W's current matrix
10426 have, by definition, to be the same as glyph pointers in the
10427 corresponding frame matrix. */
10428 window_row = w->current_matrix->rows;
10429 window_row_end = window_row + w->current_matrix->nrows;
10430 frame_row = f->current_matrix->rows + XFASTINT (w->top);
10431 while (window_row < window_row_end)
659a218f 10432 {
5f5c8ee5 10433 int area;
f002db93 10434
5f5c8ee5
GM
10435 for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
10436 frame_row->glyphs[area] = window_row->glyphs[area];
f002db93
GM
10437
10438 /* Disable frame rows whose corresponding window rows have
10439 been disabled in try_window_id. */
10440 if (!window_row->enabled_p)
10441 frame_row->enabled_p = 0;
10442
5f5c8ee5 10443 ++window_row, ++frame_row;
659a218f 10444 }
a2889657 10445}
5f5c8ee5
GM
10446
10447
e037b9ec
GM
10448/* Find the glyph row in window W containing CHARPOS. Consider all
10449 rows between START and END (not inclusive). END null means search
10450 all rows to the end of the display area of W. Value is the row
10451 containing CHARPOS or null. */
10452
10453static struct glyph_row *
10454row_containing_pos (w, charpos, start, end)
10455 struct window *w;
10456 int charpos;
10457 struct glyph_row *start, *end;
10458{
10459 struct glyph_row *row = start;
10460 int last_y;
10461
10462 /* If we happen to start on a header-line, skip that. */
10463 if (row->mode_line_p)
10464 ++row;
10465
10466 if ((end && row >= end) || !row->enabled_p)
10467 return NULL;
10468
10469 last_y = window_text_bottom_y (w);
10470
10471 while ((end == NULL || row < end)
10472 && (MATRIX_ROW_END_CHARPOS (row) < charpos
10473 /* The end position of a row equals the start
10474 position of the next row. If CHARPOS is there, we
10475 would rather display it in the next line, except
10476 when this line ends in ZV. */
10477 || (MATRIX_ROW_END_CHARPOS (row) == charpos
10478 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
10479 || !row->ends_at_zv_p)))
10480 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
10481 ++row;
10482
10483 /* Give up if CHARPOS not found. */
10484 if ((end && row >= end)
10485 || charpos < MATRIX_ROW_START_CHARPOS (row)
10486 || charpos > MATRIX_ROW_END_CHARPOS (row))
10487 row = NULL;
10488
10489 return row;
10490}
10491
10492
5f5c8ee5
GM
10493/* Try to redisplay window W by reusing its existing display. W's
10494 current matrix must be up to date when this function is called,
10495 i.e. window_end_valid must not be nil.
10496
10497 Value is
10498
10499 1 if display has been updated
10500 0 if otherwise unsuccessful
10501 -1 if redisplay with same window start is known not to succeed
10502
10503 The following steps are performed:
10504
10505 1. Find the last row in the current matrix of W that is not
10506 affected by changes at the start of current_buffer. If no such row
10507 is found, give up.
10508
10509 2. Find the first row in W's current matrix that is not affected by
10510 changes at the end of current_buffer. Maybe there is no such row.
10511
10512 3. Display lines beginning with the row + 1 found in step 1 to the
10513 row found in step 2 or, if step 2 didn't find a row, to the end of
10514 the window.
10515
10516 4. If cursor is not known to appear on the window, give up.
10517
10518 5. If display stopped at the row found in step 2, scroll the
10519 display and current matrix as needed.
10520
10521 6. Maybe display some lines at the end of W, if we must. This can
10522 happen under various circumstances, like a partially visible line
10523 becoming fully visible, or because newly displayed lines are displayed
10524 in smaller font sizes.
10525
10526 7. Update W's window end information. */
10527
10528 /* Check that window end is what we expect it to be. */
12adba34
RS
10529
10530static int
5f5c8ee5 10531try_window_id (w)
12adba34 10532 struct window *w;
12adba34 10533{
5f5c8ee5
GM
10534 struct frame *f = XFRAME (w->frame);
10535 struct glyph_matrix *current_matrix = w->current_matrix;
10536 struct glyph_matrix *desired_matrix = w->desired_matrix;
10537 struct glyph_row *last_unchanged_at_beg_row;
10538 struct glyph_row *first_unchanged_at_end_row;
10539 struct glyph_row *row;
10540 struct glyph_row *bottom_row;
10541 int bottom_vpos;
10542 struct it it;
10543 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
10544 struct text_pos start_pos;
10545 struct run run;
10546 int first_unchanged_at_end_vpos = 0;
10547 struct glyph_row *last_text_row, *last_text_row_at_end;
10548 struct text_pos start;
10549
10550 SET_TEXT_POS_FROM_MARKER (start, w->start);
10551
10552 /* Check pre-conditions. Window end must be valid, otherwise
10553 the current matrix would not be up to date. */
10554 xassert (!NILP (w->window_end_valid));
10555 xassert (FRAME_WINDOW_P (XFRAME (w->frame))
10556 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)));
10557
10558 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
10559 only if buffer has really changed. The reason is that the gap is
10560 initially at Z for freshly visited files. The code below would
10561 set end_unchanged to 0 in that case. */
28ee91c0
GM
10562 if (MODIFF > SAVE_MODIFF
10563 /* This seems to happen sometimes after saving a buffer. */
10564 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
5f5c8ee5 10565 {
9142dd5b
GM
10566 if (GPT - BEG < BEG_UNCHANGED)
10567 BEG_UNCHANGED = GPT - BEG;
10568 if (Z - GPT < END_UNCHANGED)
10569 END_UNCHANGED = Z - GPT;
5f5c8ee5 10570 }
bf9249e3 10571
5f5c8ee5
GM
10572 /* If window starts after a line end, and the last change is in
10573 front of that newline, then changes don't affect the display.
f2d86d7a
GM
10574 This case happens with stealth-fontification. Note that although
10575 the display is unchanged, glyph positions in the matrix have to
10576 be adjusted, of course. */
5f5c8ee5
GM
10577 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
10578 if (CHARPOS (start) > BEGV
9142dd5b 10579 && Z - END_UNCHANGED < CHARPOS (start) - 1
5f5c8ee5
GM
10580 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
10581 && PT < MATRIX_ROW_END_CHARPOS (row))
10582 {
f2d86d7a
GM
10583 struct glyph_row *r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
10584 int delta = CHARPOS (start) - MATRIX_ROW_START_CHARPOS (r0);
10585
10586 if (delta)
10587 {
10588 struct glyph_row *r1 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
10589 int delta_bytes = BYTEPOS (start) - MATRIX_ROW_START_BYTEPOS (r0);
10590
10591 increment_matrix_positions (w->current_matrix,
10592 MATRIX_ROW_VPOS (r0, current_matrix),
10593 MATRIX_ROW_VPOS (r1, current_matrix),
10594 delta, delta_bytes);
10595 }
10596
10597#if 0 /* If changes are all in front of the window start, the
10598 distance of the last displayed glyph from Z hasn't
10599 changed. */
5f5c8ee5
GM
10600 w->window_end_pos
10601 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
10602 w->window_end_bytepos
6fc556fd 10603 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
f2d86d7a
GM
10604#endif
10605
5f5c8ee5
GM
10606 return 1;
10607 }
10608
10609 /* Return quickly if changes are all below what is displayed in the
10610 window, and if PT is in the window. */
9142dd5b 10611 if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row)
5f5c8ee5
GM
10612 && PT < MATRIX_ROW_END_CHARPOS (row))
10613 {
10614 /* We have to update window end positions because the buffer's
10615 size has changed. */
10616 w->window_end_pos
10617 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
10618 w->window_end_bytepos
6fc556fd 10619 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
ef121659
GM
10620
10621 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10622 row = row_containing_pos (w, PT, row, NULL);
10623 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
10624 return 2;
5f5c8ee5
GM
10625 }
10626
10627 /* Check that window start agrees with the start of the first glyph
10628 row in its current matrix. Check this after we know the window
10629 start is not in changed text, otherwise positions would not be
10630 comparable. */
10631 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10632 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
10633 return 0;
10634
5f5c8ee5
GM
10635 /* Compute the position at which we have to start displaying new
10636 lines. Some of the lines at the top of the window might be
10637 reusable because they are not displaying changed text. Find the
10638 last row in W's current matrix not affected by changes at the
10639 start of current_buffer. Value is null if changes start in the
10640 first line of window. */
1ec185cb 10641 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
5f5c8ee5
GM
10642 if (last_unchanged_at_beg_row)
10643 {
10644 init_to_row_end (&it, w, last_unchanged_at_beg_row);
10645 start_pos = it.current.pos;
10646
10647 /* Start displaying new lines in the desired matrix at the same
10648 vpos we would use in the current matrix, i.e. below
10649 last_unchanged_at_beg_row. */
10650 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
10651 current_matrix);
10652 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10653 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
10654
10655 xassert (it.hpos == 0 && it.current_x == 0);
10656 }
10657 else
10658 {
10659 /* There are no reusable lines at the start of the window.
10660 Start displaying in the first line. */
10661 start_display (&it, w, start);
10662 start_pos = it.current.pos;
10663 }
10664
5f5c8ee5
GM
10665 /* Find the first row that is not affected by changes at the end of
10666 the buffer. Value will be null if there is no unchanged row, in
10667 which case we must redisplay to the end of the window. delta
10668 will be set to the value by which buffer positions beginning with
10669 first_unchanged_at_end_row have to be adjusted due to text
10670 changes. */
10671 first_unchanged_at_end_row
1ec185cb 10672 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
5f5c8ee5
GM
10673 IF_DEBUG (debug_delta = delta);
10674 IF_DEBUG (debug_delta_bytes = delta_bytes);
10675
10676 /* Set stop_pos to the buffer position up to which we will have to
10677 display new lines. If first_unchanged_at_end_row != NULL, this
10678 is the buffer position of the start of the line displayed in that
10679 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
10680 that we don't stop at a buffer position. */
10681 stop_pos = 0;
10682 if (first_unchanged_at_end_row)
10683 {
10684 xassert (last_unchanged_at_beg_row == NULL
10685 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
10686
10687 /* If this is a continuation line, move forward to the next one
10688 that isn't. Changes in lines above affect this line.
10689 Caution: this may move first_unchanged_at_end_row to a row
10690 not displaying text. */
10691 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
10692 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
10693 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
10694 < it.last_visible_y))
10695 ++first_unchanged_at_end_row;
10696
10697 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
10698 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
10699 >= it.last_visible_y))
10700 first_unchanged_at_end_row = NULL;
10701 else
10702 {
10703 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
10704 + delta);
10705 first_unchanged_at_end_vpos
10706 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 10707 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
10708 }
10709 }
10710 else if (last_unchanged_at_beg_row == NULL)
10711 return 0;
10712
10713
10714#if GLYPH_DEBUG
10715
10716 /* Either there is no unchanged row at the end, or the one we have
10717 now displays text. This is a necessary condition for the window
10718 end pos calculation at the end of this function. */
10719 xassert (first_unchanged_at_end_row == NULL
10720 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
10721
10722 debug_last_unchanged_at_beg_vpos
10723 = (last_unchanged_at_beg_row
10724 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
10725 : -1);
10726 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
10727
10728#endif /* GLYPH_DEBUG != 0 */
10729
10730
10731 /* Display new lines. Set last_text_row to the last new line
10732 displayed which has text on it, i.e. might end up as being the
10733 line where the window_end_vpos is. */
10734 w->cursor.vpos = -1;
10735 last_text_row = NULL;
10736 overlay_arrow_seen = 0;
10737 while (it.current_y < it.last_visible_y
10738 && !fonts_changed_p
10739 && (first_unchanged_at_end_row == NULL
10740 || IT_CHARPOS (it) < stop_pos))
10741 {
10742 if (display_line (&it))
10743 last_text_row = it.glyph_row - 1;
10744 }
10745
10746 if (fonts_changed_p)
10747 return -1;
10748
10749
10750 /* Compute differences in buffer positions, y-positions etc. for
10751 lines reused at the bottom of the window. Compute what we can
10752 scroll. */
ca42b2e8
GM
10753 if (first_unchanged_at_end_row
10754 /* No lines reused because we displayed everything up to the
10755 bottom of the window. */
10756 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
10757 {
10758 dvpos = (it.vpos
10759 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
10760 current_matrix));
10761 dy = it.current_y - first_unchanged_at_end_row->y;
10762 run.current_y = first_unchanged_at_end_row->y;
10763 run.desired_y = run.current_y + dy;
10764 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
10765 }
10766 else
ca42b2e8
GM
10767 {
10768 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
10769 first_unchanged_at_end_row = NULL;
10770 }
5f5c8ee5
GM
10771 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
10772
8f8ba186 10773
5f5c8ee5
GM
10774 /* Find the cursor if not already found. We have to decide whether
10775 PT will appear on this window (it sometimes doesn't, but this is
10776 not a very frequent case.) This decision has to be made before
10777 the current matrix is altered. A value of cursor.vpos < 0 means
10778 that PT is either in one of the lines beginning at
10779 first_unchanged_at_end_row or below the window. Don't care for
10780 lines that might be displayed later at the window end; as
10781 mentioned, this is not a frequent case. */
10782 if (w->cursor.vpos < 0)
10783 {
5f5c8ee5
GM
10784 /* Cursor in unchanged rows at the top? */
10785 if (PT < CHARPOS (start_pos)
10786 && last_unchanged_at_beg_row)
10787 {
e037b9ec
GM
10788 row = row_containing_pos (w, PT,
10789 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
10790 last_unchanged_at_beg_row + 1);
bfe0ee88
GM
10791 if (row)
10792 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
10793 }
10794
10795 /* Start from first_unchanged_at_end_row looking for PT. */
10796 else if (first_unchanged_at_end_row)
10797 {
e037b9ec
GM
10798 row = row_containing_pos (w, PT - delta,
10799 first_unchanged_at_end_row, NULL);
10800 if (row)
468155d7
GM
10801 set_cursor_from_row (w, row, w->current_matrix, delta,
10802 delta_bytes, dy, dvpos);
5f5c8ee5
GM
10803 }
10804
10805 /* Give up if cursor was not found. */
10806 if (w->cursor.vpos < 0)
10807 {
10808 clear_glyph_matrix (w->desired_matrix);
10809 return -1;
10810 }
10811 }
10812
10813 /* Don't let the cursor end in the scroll margins. */
10814 {
10815 int this_scroll_margin, cursor_height;
10816
10817 this_scroll_margin = max (0, scroll_margin);
10818 this_scroll_margin = min (this_scroll_margin,
10819 XFASTINT (w->height) / 4);
10820 this_scroll_margin *= CANON_Y_UNIT (it.f);
10821 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
10822
10823 if ((w->cursor.y < this_scroll_margin
10824 && CHARPOS (start) > BEGV)
10825 /* Don't take scroll margin into account at the bottom because
10826 old redisplay didn't do it either. */
10827 || w->cursor.y + cursor_height > it.last_visible_y)
10828 {
10829 w->cursor.vpos = -1;
10830 clear_glyph_matrix (w->desired_matrix);
10831 return -1;
10832 }
10833 }
10834
10835 /* Scroll the display. Do it before changing the current matrix so
10836 that xterm.c doesn't get confused about where the cursor glyph is
10837 found. */
fa77249f 10838 if (dy && run.height)
5f5c8ee5
GM
10839 {
10840 update_begin (f);
10841
10842 if (FRAME_WINDOW_P (f))
10843 {
10844 rif->update_window_begin_hook (w);
64d1e7d3 10845 rif->clear_mouse_face (w);
5f5c8ee5 10846 rif->scroll_run_hook (w, &run);
64d1e7d3 10847 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
10848 }
10849 else
10850 {
10851 /* Terminal frame. In this case, dvpos gives the number of
10852 lines to scroll by; dvpos < 0 means scroll up. */
10853 int first_unchanged_at_end_vpos
10854 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
10855 int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
10856 int end = XFASTINT (w->top) + window_internal_height (w);
10857
10858 /* Perform the operation on the screen. */
10859 if (dvpos > 0)
10860 {
10861 /* Scroll last_unchanged_at_beg_row to the end of the
10862 window down dvpos lines. */
10863 set_terminal_window (end);
10864
10865 /* On dumb terminals delete dvpos lines at the end
10866 before inserting dvpos empty lines. */
10867 if (!scroll_region_ok)
10868 ins_del_lines (end - dvpos, -dvpos);
10869
10870 /* Insert dvpos empty lines in front of
10871 last_unchanged_at_beg_row. */
10872 ins_del_lines (from, dvpos);
10873 }
10874 else if (dvpos < 0)
10875 {
10876 /* Scroll up last_unchanged_at_beg_vpos to the end of
10877 the window to last_unchanged_at_beg_vpos - |dvpos|. */
10878 set_terminal_window (end);
10879
10880 /* Delete dvpos lines in front of
10881 last_unchanged_at_beg_vpos. ins_del_lines will set
10882 the cursor to the given vpos and emit |dvpos| delete
10883 line sequences. */
10884 ins_del_lines (from + dvpos, dvpos);
10885
10886 /* On a dumb terminal insert dvpos empty lines at the
10887 end. */
10888 if (!scroll_region_ok)
10889 ins_del_lines (end + dvpos, -dvpos);
10890 }
10891
10892 set_terminal_window (0);
10893 }
10894
10895 update_end (f);
10896 }
10897
ca42b2e8
GM
10898 /* Shift reused rows of the current matrix to the right position.
10899 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
10900 text. */
10901 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
10902 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
10903 if (dvpos < 0)
10904 {
10905 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
10906 bottom_vpos, dvpos);
10907 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
10908 bottom_vpos, 0);
10909 }
10910 else if (dvpos > 0)
10911 {
10912 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
10913 bottom_vpos, dvpos);
10914 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
10915 first_unchanged_at_end_vpos + dvpos, 0);
10916 }
10917
10918 /* For frame-based redisplay, make sure that current frame and window
10919 matrix are in sync with respect to glyph memory. */
10920 if (!FRAME_WINDOW_P (f))
10921 sync_frame_with_window_matrix_rows (w);
10922
10923 /* Adjust buffer positions in reused rows. */
10924 if (delta)
f2d86d7a
GM
10925 increment_matrix_positions (current_matrix,
10926 first_unchanged_at_end_vpos + dvpos,
10927 bottom_vpos, delta, delta_bytes);
5f5c8ee5
GM
10928
10929 /* Adjust Y positions. */
10930 if (dy)
10931 shift_glyph_matrix (w, current_matrix,
10932 first_unchanged_at_end_vpos + dvpos,
10933 bottom_vpos, dy);
10934
10935 if (first_unchanged_at_end_row)
10936 first_unchanged_at_end_row += dvpos;
10937
10938 /* If scrolling up, there may be some lines to display at the end of
10939 the window. */
10940 last_text_row_at_end = NULL;
10941 if (dy < 0)
10942 {
10943 /* Set last_row to the glyph row in the current matrix where the
10944 window end line is found. It has been moved up or down in
10945 the matrix by dvpos. */
10946 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
10947 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
10948
10949 /* If last_row is the window end line, it should display text. */
10950 xassert (last_row->displays_text_p);
10951
10952 /* If window end line was partially visible before, begin
10953 displaying at that line. Otherwise begin displaying with the
10954 line following it. */
10955 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
10956 {
10957 init_to_row_start (&it, w, last_row);
10958 it.vpos = last_vpos;
10959 it.current_y = last_row->y;
10960 }
10961 else
10962 {
10963 init_to_row_end (&it, w, last_row);
10964 it.vpos = 1 + last_vpos;
10965 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
10966 ++last_row;
10967 }
12adba34 10968
5f5c8ee5
GM
10969 /* We may start in a continuation line. If so, we have to get
10970 the right continuation_lines_width and current_x. */
10971 it.continuation_lines_width = last_row->continuation_lines_width;
10972 it.hpos = it.current_x = 0;
10973
10974 /* Display the rest of the lines at the window end. */
10975 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10976 while (it.current_y < it.last_visible_y
10977 && !fonts_changed_p)
10978 {
10979 /* Is it always sure that the display agrees with lines in
10980 the current matrix? I don't think so, so we mark rows
10981 displayed invalid in the current matrix by setting their
10982 enabled_p flag to zero. */
10983 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
10984 if (display_line (&it))
10985 last_text_row_at_end = it.glyph_row - 1;
10986 }
10987 }
12adba34 10988
5f5c8ee5
GM
10989 /* Update window_end_pos and window_end_vpos. */
10990 if (first_unchanged_at_end_row
10991 && first_unchanged_at_end_row->y < it.last_visible_y
10992 && !last_text_row_at_end)
10993 {
10994 /* Window end line if one of the preserved rows from the current
10995 matrix. Set row to the last row displaying text in current
10996 matrix starting at first_unchanged_at_end_row, after
10997 scrolling. */
10998 xassert (first_unchanged_at_end_row->displays_text_p);
10999 row = find_last_row_displaying_text (w->current_matrix, &it,
11000 first_unchanged_at_end_row);
11001 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
11002
11003 XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row));
11004 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
11005 XSETFASTINT (w->window_end_vpos,
11006 MATRIX_ROW_VPOS (row, w->current_matrix));
11007 }
11008 else if (last_text_row_at_end)
11009 {
11010 XSETFASTINT (w->window_end_pos,
11011 Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
11012 w->window_end_bytepos
11013 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
11014 XSETFASTINT (w->window_end_vpos,
11015 MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
11016 }
11017 else if (last_text_row)
11018 {
11019 /* We have displayed either to the end of the window or at the
11020 end of the window, i.e. the last row with text is to be found
11021 in the desired matrix. */
11022 XSETFASTINT (w->window_end_pos,
11023 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
11024 w->window_end_bytepos
11025 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
11026 XSETFASTINT (w->window_end_vpos,
11027 MATRIX_ROW_VPOS (last_text_row, desired_matrix));
11028 }
11029 else if (first_unchanged_at_end_row == NULL
11030 && last_text_row == NULL
11031 && last_text_row_at_end == NULL)
11032 {
11033 /* Displayed to end of window, but no line containing text was
11034 displayed. Lines were deleted at the end of the window. */
11035 int vpos;
045dee35 11036 int header_line_p = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
11037
11038 for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
045dee35
GM
11039 if ((w->desired_matrix->rows[vpos + header_line_p].enabled_p
11040 && w->desired_matrix->rows[vpos + header_line_p].displays_text_p)
11041 || (!w->desired_matrix->rows[vpos + header_line_p].enabled_p
11042 && w->current_matrix->rows[vpos + header_line_p].displays_text_p))
5f5c8ee5 11043 break;
12adba34 11044
5f5c8ee5
GM
11045 w->window_end_vpos = make_number (vpos);
11046 }
11047 else
11048 abort ();
11049
11050 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
11051 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 11052
5f5c8ee5
GM
11053 /* Record that display has not been completed. */
11054 w->window_end_valid = Qnil;
11055 w->desired_matrix->no_scrolling_p = 1;
ef121659 11056 return 3;
12adba34 11057}
0f9c0ff0 11058
a2889657 11059
5f5c8ee5
GM
11060\f
11061/***********************************************************************
11062 More debugging support
11063 ***********************************************************************/
a2889657 11064
5f5c8ee5 11065#if GLYPH_DEBUG
a2889657 11066
5f5c8ee5
GM
11067 void dump_glyph_row P_ ((struct glyph_matrix *, int, int));
11068static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
1c9241f5 11069
31b24551 11070
5f5c8ee5
GM
11071/* Dump the contents of glyph matrix MATRIX on stderr. If
11072 WITH_GLYPHS_P is non-zero, dump glyph contents as well. */
ca26e1c8 11073
5f85fa4e 11074static void
5f5c8ee5
GM
11075dump_glyph_matrix (matrix, with_glyphs_p)
11076 struct glyph_matrix *matrix;
11077 int with_glyphs_p;
11078{
efc63ef0 11079 int i;
5f5c8ee5
GM
11080 for (i = 0; i < matrix->nrows; ++i)
11081 dump_glyph_row (matrix, i, with_glyphs_p);
11082}
31b24551 11083
68a37fa8 11084
5f5c8ee5
GM
11085/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
11086 WITH_GLYPH_SP non-zero means dump glyph contents, too. */
a2889657 11087
5f5c8ee5
GM
11088void
11089dump_glyph_row (matrix, vpos, with_glyphs_p)
11090 struct glyph_matrix *matrix;
11091 int vpos, with_glyphs_p;
11092{
11093 struct glyph_row *row;
11094
11095 if (vpos < 0 || vpos >= matrix->nrows)
11096 return;
11097
11098 row = MATRIX_ROW (matrix, vpos);
11099
b28cb6ed
GM
11100 fprintf (stderr, "Row Start End Used oEI><O\\CTZFes X Y W H V A P\n");
11101 fprintf (stderr, "=======================================================================\n");
5f5c8ee5 11102
ae26e27d
GM
11103 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d\
11104%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
5f5c8ee5
GM
11105 row - matrix->rows,
11106 MATRIX_ROW_START_CHARPOS (row),
11107 MATRIX_ROW_END_CHARPOS (row),
11108 row->used[TEXT_AREA],
11109 row->contains_overlapping_glyphs_p,
11110 row->enabled_p,
11111 row->inverse_p,
11112 row->truncated_on_left_p,
11113 row->truncated_on_right_p,
11114 row->overlay_arrow_p,
11115 row->continued_p,
11116 MATRIX_ROW_CONTINUATION_LINE_P (row),
11117 row->displays_text_p,
11118 row->ends_at_zv_p,
11119 row->fill_line_p,
91004049
GM
11120 row->ends_in_middle_of_char_p,
11121 row->starts_in_middle_of_char_p,
5f5c8ee5
GM
11122 row->x,
11123 row->y,
b28cb6ed
GM
11124 row->pixel_width,
11125 row->height,
11126 row->visible_height,
11127 row->ascent,
11128 row->phys_ascent);
5f5c8ee5
GM
11129 fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
11130 row->end.overlay_string_index);
11131 fprintf (stderr, "%9d %5d\n",
11132 CHARPOS (row->start.string_pos),
11133 CHARPOS (row->end.string_pos));
11134 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
11135 row->end.dpvec_index);
11136
11137 if (with_glyphs_p)
bd66d1ba 11138 {
5f5c8ee5
GM
11139 struct glyph *glyph, *glyph_end;
11140 int prev_had_glyphs_p;
11141
11142 glyph = row->glyphs[TEXT_AREA];
11143 glyph_end = glyph + row->used[TEXT_AREA];
11144
11145 /* Glyph for a line end in text. */
11146 if (glyph == glyph_end && glyph->charpos > 0)
11147 ++glyph_end;
11148
11149 if (glyph < glyph_end)
bd66d1ba 11150 {
06568bbf 11151 fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
5f5c8ee5 11152 prev_had_glyphs_p = 1;
bd66d1ba
RS
11153 }
11154 else
5f5c8ee5
GM
11155 prev_had_glyphs_p = 0;
11156
11157 while (glyph < glyph_end)
f7b4b63a 11158 {
5f5c8ee5
GM
11159 if (glyph->type == CHAR_GLYPH)
11160 {
11161 fprintf (stderr,
06568bbf 11162 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
5f5c8ee5
GM
11163 glyph - row->glyphs[TEXT_AREA],
11164 'C',
11165 glyph->charpos,
06568bbf
GM
11166 (BUFFERP (glyph->object)
11167 ? 'B'
11168 : (STRINGP (glyph->object)
11169 ? 'S'
11170 : '-')),
5f5c8ee5 11171 glyph->pixel_width,
43d120d8
KH
11172 glyph->u.ch,
11173 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
11174 ? glyph->u.ch
5f5c8ee5 11175 : '.'),
43d120d8 11176 glyph->face_id,
5f5c8ee5
GM
11177 glyph->left_box_line_p,
11178 glyph->right_box_line_p);
11179 }
11180 else if (glyph->type == STRETCH_GLYPH)
11181 {
11182 fprintf (stderr,
06568bbf 11183 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
5f5c8ee5
GM
11184 glyph - row->glyphs[TEXT_AREA],
11185 'S',
11186 glyph->charpos,
06568bbf
GM
11187 (BUFFERP (glyph->object)
11188 ? 'B'
11189 : (STRINGP (glyph->object)
11190 ? 'S'
11191 : '-')),
5f5c8ee5
GM
11192 glyph->pixel_width,
11193 0,
11194 '.',
bcdda9a4 11195 glyph->face_id,
5f5c8ee5
GM
11196 glyph->left_box_line_p,
11197 glyph->right_box_line_p);
11198 }
11199 else if (glyph->type == IMAGE_GLYPH)
11200 {
11201 fprintf (stderr,
06568bbf 11202 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
5f5c8ee5
GM
11203 glyph - row->glyphs[TEXT_AREA],
11204 'I',
11205 glyph->charpos,
06568bbf
GM
11206 (BUFFERP (glyph->object)
11207 ? 'B'
11208 : (STRINGP (glyph->object)
11209 ? 'S'
11210 : '-')),
5f5c8ee5 11211 glyph->pixel_width,
43d120d8 11212 glyph->u.img_id,
5f5c8ee5 11213 '.',
bcdda9a4 11214 glyph->face_id,
5f5c8ee5
GM
11215 glyph->left_box_line_p,
11216 glyph->right_box_line_p);
11217 }
11218 ++glyph;
f7b4b63a 11219 }
f4faa47c 11220 }
5f5c8ee5 11221}
f4faa47c 11222
a2889657 11223
5f5c8ee5
GM
11224DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
11225 Sdump_glyph_matrix, 0, 1, "p",
11226 "Dump the current matrix of the selected window to stderr.\n\
11227Shows contents of glyph row structures. With non-nil optional\n\
11228parameter WITH-GLYPHS-P, dump glyphs as well.")
11229 (with_glyphs_p)
02513cdd 11230 Lisp_Object with_glyphs_p;
5f5c8ee5
GM
11231{
11232 struct window *w = XWINDOW (selected_window);
11233 struct buffer *buffer = XBUFFER (w->buffer);
11234
11235 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
11236 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
11237 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
11238 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
11239 fprintf (stderr, "=============================================\n");
11240 dump_glyph_matrix (w->current_matrix, !NILP (with_glyphs_p));
11241 return Qnil;
11242}
1c2250c2 11243
1fca3fae 11244
5f5c8ee5
GM
11245DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "",
11246 "Dump glyph row ROW to stderr.")
11247 (row)
11248 Lisp_Object row;
11249{
11250 CHECK_NUMBER (row, 0);
11251 dump_glyph_row (XWINDOW (selected_window)->current_matrix, XINT (row), 1);
11252 return Qnil;
11253}
1fca3fae 11254
67481ae5 11255
e037b9ec 11256DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row,
5f5c8ee5
GM
11257 0, 0, "", "")
11258 ()
11259{
886bd6f2
GM
11260 struct frame *sf = SELECTED_FRAME ();
11261 struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)
5f5c8ee5
GM
11262 ->current_matrix);
11263 dump_glyph_row (m, 0, 1);
11264 return Qnil;
11265}
ca26e1c8 11266
0f9c0ff0 11267
5f5c8ee5
GM
11268DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
11269 Strace_redisplay_toggle, 0, 0, "",
11270 "Toggle tracing of redisplay.")
11271 ()
11272{
11273 trace_redisplay_p = !trace_redisplay_p;
11274 return Qnil;
11275}
bf9249e3
GM
11276
11277
11278DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, 1, "",
11279 "Print STRING to stderr.")
11280 (string)
11281 Lisp_Object string;
11282{
11283 CHECK_STRING (string, 0);
11284 fprintf (stderr, "%s", XSTRING (string)->data);
11285 return Qnil;
11286}
5f5c8ee5
GM
11287
11288#endif /* GLYPH_DEBUG */
ca26e1c8 11289
ca26e1c8 11290
5f5c8ee5
GM
11291\f
11292/***********************************************************************
11293 Building Desired Matrix Rows
11294 ***********************************************************************/
a2889657 11295
5f5c8ee5
GM
11296/* Return a temporary glyph row holding the glyphs of an overlay
11297 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 11298
5f5c8ee5
GM
11299static struct glyph_row *
11300get_overlay_arrow_glyph_row (w)
11301 struct window *w;
11302{
11303 struct frame *f = XFRAME (WINDOW_FRAME (w));
11304 struct buffer *buffer = XBUFFER (w->buffer);
11305 struct buffer *old = current_buffer;
11306 unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data;
11307 int arrow_len = XSTRING (Voverlay_arrow_string)->size;
11308 unsigned char *arrow_end = arrow_string + arrow_len;
11309 unsigned char *p;
11310 struct it it;
11311 int multibyte_p;
11312 int n_glyphs_before;
11313
11314 set_buffer_temp (buffer);
11315 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
11316 it.glyph_row->used[TEXT_AREA] = 0;
11317 SET_TEXT_POS (it.position, 0, 0);
11318
11319 multibyte_p = !NILP (buffer->enable_multibyte_characters);
11320 p = arrow_string;
11321 while (p < arrow_end)
11322 {
11323 Lisp_Object face, ilisp;
11324
11325 /* Get the next character. */
11326 if (multibyte_p)
4fdb80f2 11327 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
11328 else
11329 it.c = *p, it.len = 1;
11330 p += it.len;
11331
11332 /* Get its face. */
11333 XSETFASTINT (ilisp, p - arrow_string);
11334 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
11335 it.face_id = compute_char_face (f, it.c, face);
11336
11337 /* Compute its width, get its glyphs. */
11338 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 11339 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
11340 PRODUCE_GLYPHS (&it);
11341
11342 /* If this character doesn't fit any more in the line, we have
11343 to remove some glyphs. */
11344 if (it.current_x > it.last_visible_x)
11345 {
11346 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
11347 break;
11348 }
11349 }
11350
11351 set_buffer_temp (old);
11352 return it.glyph_row;
11353}
ca26e1c8 11354
b0a0fbda 11355
5f5c8ee5
GM
11356/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
11357 glyphs are only inserted for terminal frames since we can't really
11358 win with truncation glyphs when partially visible glyphs are
11359 involved. Which glyphs to insert is determined by
11360 produce_special_glyphs. */
67481ae5 11361
5f5c8ee5
GM
11362static void
11363insert_left_trunc_glyphs (it)
11364 struct it *it;
11365{
11366 struct it truncate_it;
11367 struct glyph *from, *end, *to, *toend;
11368
11369 xassert (!FRAME_WINDOW_P (it->f));
11370
11371 /* Get the truncation glyphs. */
11372 truncate_it = *it;
5f5c8ee5
GM
11373 truncate_it.current_x = 0;
11374 truncate_it.face_id = DEFAULT_FACE_ID;
11375 truncate_it.glyph_row = &scratch_glyph_row;
11376 truncate_it.glyph_row->used[TEXT_AREA] = 0;
11377 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
6fc556fd 11378 truncate_it.object = make_number (0);
5f5c8ee5
GM
11379 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
11380
11381 /* Overwrite glyphs from IT with truncation glyphs. */
11382 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
11383 end = from + truncate_it.glyph_row->used[TEXT_AREA];
11384 to = it->glyph_row->glyphs[TEXT_AREA];
11385 toend = to + it->glyph_row->used[TEXT_AREA];
11386
11387 while (from < end)
11388 *to++ = *from++;
11389
11390 /* There may be padding glyphs left over. Remove them. */
11391 from = to;
11392 while (from < toend && CHAR_GLYPH_PADDING_P (*from))
11393 ++from;
11394 while (from < toend)
11395 *to++ = *from++;
11396
11397 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
11398}
e0bfbde6 11399
e0bfbde6 11400
5f5c8ee5 11401/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 11402
5f5c8ee5
GM
11403 Most of the time, ascent and height of a display line will be equal
11404 to the max_ascent and max_height values of the display iterator
11405 structure. This is not the case if
67481ae5 11406
5f5c8ee5
GM
11407 1. We hit ZV without displaying anything. In this case, max_ascent
11408 and max_height will be zero.
1c9241f5 11409
5f5c8ee5
GM
11410 2. We have some glyphs that don't contribute to the line height.
11411 (The glyph row flag contributes_to_line_height_p is for future
11412 pixmap extensions).
f6fd109b 11413
5f5c8ee5
GM
11414 The first case is easily covered by using default values because in
11415 these cases, the line height does not really matter, except that it
11416 must not be zero. */
67481ae5 11417
5f5c8ee5
GM
11418static void
11419compute_line_metrics (it)
11420 struct it *it;
11421{
11422 struct glyph_row *row = it->glyph_row;
11423 int area, i;
1c2250c2 11424
5f5c8ee5
GM
11425 if (FRAME_WINDOW_P (it->f))
11426 {
045dee35 11427 int i, header_line_height;
1c2250c2 11428
5f5c8ee5
GM
11429 /* The line may consist of one space only, that was added to
11430 place the cursor on it. If so, the row's height hasn't been
11431 computed yet. */
11432 if (row->height == 0)
11433 {
11434 if (it->max_ascent + it->max_descent == 0)
312246d1 11435 it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
5f5c8ee5
GM
11436 row->ascent = it->max_ascent;
11437 row->height = it->max_ascent + it->max_descent;
312246d1
GM
11438 row->phys_ascent = it->max_phys_ascent;
11439 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
11440 }
11441
11442 /* Compute the width of this line. */
11443 row->pixel_width = row->x;
11444 for (i = 0; i < row->used[TEXT_AREA]; ++i)
11445 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
11446
11447 xassert (row->pixel_width >= 0);
11448 xassert (row->ascent >= 0 && row->height > 0);
11449
312246d1
GM
11450 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
11451 || MATRIX_ROW_OVERLAPS_PRED_P (row));
11452
11453 /* If first line's physical ascent is larger than its logical
11454 ascent, use the physical ascent, and make the row taller.
11455 This makes accented characters fully visible. */
b28cb6ed 11456 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
312246d1
GM
11457 && row->phys_ascent > row->ascent)
11458 {
11459 row->height += row->phys_ascent - row->ascent;
11460 row->ascent = row->phys_ascent;
11461 }
11462
5f5c8ee5
GM
11463 /* Compute how much of the line is visible. */
11464 row->visible_height = row->height;
11465
045dee35
GM
11466 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
11467 if (row->y < header_line_height)
11468 row->visible_height -= header_line_height - row->y;
5f5c8ee5
GM
11469 else
11470 {
11471 int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
11472 if (row->y + row->height > max_y)
11473 row->visible_height -= row->y + row->height - max_y;
11474 }
11475 }
11476 else
11477 {
11478 row->pixel_width = row->used[TEXT_AREA];
312246d1
GM
11479 row->ascent = row->phys_ascent = 0;
11480 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 11481 }
67481ae5 11482
5f5c8ee5
GM
11483 /* Compute a hash code for this row. */
11484 row->hash = 0;
11485 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
11486 for (i = 0; i < row->used[area]; ++i)
11487 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
11488 + row->glyphs[area][i].u.val
43d120d8
KH
11489 + row->glyphs[area][i].face_id
11490 + row->glyphs[area][i].padding_p
5f5c8ee5 11491 + (row->glyphs[area][i].type << 2));
a2889657 11492
5f5c8ee5 11493 it->max_ascent = it->max_descent = 0;
312246d1 11494 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 11495}
12adba34 11496
ca26e1c8 11497
5f5c8ee5
GM
11498/* Append one space to the glyph row of iterator IT if doing a
11499 window-based redisplay. DEFAULT_FACE_P non-zero means let the
11500 space have the default face, otherwise let it have the same face as
80c6cb1f 11501 IT->face_id. Value is non-zero if a space was added.
c6e89d6c
GM
11502
11503 This function is called to make sure that there is always one glyph
11504 at the end of a glyph row that the cursor can be set on under
11505 window-systems. (If there weren't such a glyph we would not know
11506 how wide and tall a box cursor should be displayed).
11507
11508 At the same time this space let's a nicely handle clearing to the
11509 end of the line if the row ends in italic text. */
ca26e1c8 11510
80c6cb1f 11511static int
5f5c8ee5
GM
11512append_space (it, default_face_p)
11513 struct it *it;
11514 int default_face_p;
11515{
11516 if (FRAME_WINDOW_P (it->f))
11517 {
11518 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 11519
5f5c8ee5
GM
11520 if (it->glyph_row->glyphs[TEXT_AREA] + n
11521 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 11522 {
cafafe0b
GM
11523 /* Save some values that must not be changed.
11524 Must save IT->c and IT->len because otherwise
11525 ITERATOR_AT_END_P wouldn't work anymore after
11526 append_space has been called. */
5f5c8ee5 11527 int saved_what = it->what;
cafafe0b
GM
11528 int saved_c = it->c, saved_len = it->len;
11529 int saved_x = it->current_x;
5f5c8ee5 11530 int saved_face_id = it->face_id;
cafafe0b 11531 struct text_pos saved_pos;
5f5c8ee5 11532 Lisp_Object saved_object;
980806b6 11533 struct face *face;
5f5c8ee5
GM
11534
11535 saved_object = it->object;
11536 saved_pos = it->position;
11537
11538 it->what = IT_CHARACTER;
11539 bzero (&it->position, sizeof it->position);
6fc556fd 11540 it->object = make_number (0);
5f5c8ee5
GM
11541 it->c = ' ';
11542 it->len = 1;
5f5c8ee5
GM
11543
11544 if (default_face_p)
11545 it->face_id = DEFAULT_FACE_ID;
980806b6
KH
11546 face = FACE_FROM_ID (it->f, it->face_id);
11547 it->face_id = FACE_FOR_CHAR (it->f, face, 0);
1842fc1a 11548
5f5c8ee5
GM
11549 PRODUCE_GLYPHS (it);
11550
11551 it->current_x = saved_x;
11552 it->object = saved_object;
11553 it->position = saved_pos;
11554 it->what = saved_what;
11555 it->face_id = saved_face_id;
cafafe0b
GM
11556 it->len = saved_len;
11557 it->c = saved_c;
80c6cb1f 11558 return 1;
5f5c8ee5
GM
11559 }
11560 }
80c6cb1f
GM
11561
11562 return 0;
5f5c8ee5 11563}
12adba34 11564
1842fc1a 11565
5f5c8ee5
GM
11566/* Extend the face of the last glyph in the text area of IT->glyph_row
11567 to the end of the display line. Called from display_line.
11568 If the glyph row is empty, add a space glyph to it so that we
11569 know the face to draw. Set the glyph row flag fill_line_p. */
11570
11571static void
11572extend_face_to_end_of_line (it)
11573 struct it *it;
11574{
11575 struct face *face;
11576 struct frame *f = it->f;
1842fc1a 11577
5f5c8ee5
GM
11578 /* If line is already filled, do nothing. */
11579 if (it->current_x >= it->last_visible_x)
11580 return;
11581
11582 /* Face extension extends the background and box of IT->face_id
11583 to the end of the line. If the background equals the background
11584 of the frame, we haven't to do anything. */
11585 face = FACE_FROM_ID (f, it->face_id);
11586 if (FRAME_WINDOW_P (f)
11587 && face->box == FACE_NO_BOX
11588 && face->background == FRAME_BACKGROUND_PIXEL (f)
11589 && !face->stipple)
11590 return;
1842fc1a 11591
5f5c8ee5
GM
11592 /* Set the glyph row flag indicating that the face of the last glyph
11593 in the text area has to be drawn to the end of the text area. */
11594 it->glyph_row->fill_line_p = 1;
545e04f6 11595
980806b6
KH
11596 /* If current character of IT is not ASCII, make sure we have the
11597 ASCII face. This will be automatically undone the next time
11598 get_next_display_element returns a multibyte character. Note
11599 that the character will always be single byte in unibyte text. */
11600 if (!SINGLE_BYTE_CHAR_P (it->c))
5f5c8ee5 11601 {
980806b6 11602 it->face_id = FACE_FOR_CHAR (f, face, 0);
5f5c8ee5 11603 }
545e04f6 11604
5f5c8ee5
GM
11605 if (FRAME_WINDOW_P (f))
11606 {
11607 /* If the row is empty, add a space with the current face of IT,
11608 so that we know which face to draw. */
11609 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 11610 {
5f5c8ee5 11611 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
43d120d8 11612 it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
5f5c8ee5 11613 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 11614 }
5f5c8ee5
GM
11615 }
11616 else
11617 {
11618 /* Save some values that must not be changed. */
11619 int saved_x = it->current_x;
11620 struct text_pos saved_pos;
11621 Lisp_Object saved_object;
11622 int saved_what = it->what;
11623
11624 saved_object = it->object;
11625 saved_pos = it->position;
11626
11627 it->what = IT_CHARACTER;
11628 bzero (&it->position, sizeof it->position);
6fc556fd 11629 it->object = make_number (0);
5f5c8ee5
GM
11630 it->c = ' ';
11631 it->len = 1;
11632
11633 PRODUCE_GLYPHS (it);
11634
11635 while (it->current_x <= it->last_visible_x)
11636 PRODUCE_GLYPHS (it);
11637
11638 /* Don't count these blanks really. It would let us insert a left
11639 truncation glyph below and make us set the cursor on them, maybe. */
11640 it->current_x = saved_x;
11641 it->object = saved_object;
11642 it->position = saved_pos;
11643 it->what = saved_what;
11644 }
11645}
12adba34 11646
545e04f6 11647
5f5c8ee5
GM
11648/* Value is non-zero if text starting at CHARPOS in current_buffer is
11649 trailing whitespace. */
1c9241f5 11650
5f5c8ee5
GM
11651static int
11652trailing_whitespace_p (charpos)
11653 int charpos;
11654{
11655 int bytepos = CHAR_TO_BYTE (charpos);
11656 int c = 0;
7bbe686f 11657
5f5c8ee5
GM
11658 while (bytepos < ZV_BYTE
11659 && (c = FETCH_CHAR (bytepos),
11660 c == ' ' || c == '\t'))
11661 ++bytepos;
0d09d1e6 11662
8f897821
GM
11663 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
11664 {
11665 if (bytepos != PT_BYTE)
11666 return 1;
11667 }
11668 return 0;
5f5c8ee5 11669}
31b24551 11670
545e04f6 11671
5f5c8ee5 11672/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 11673
5f5c8ee5
GM
11674void
11675highlight_trailing_whitespace (f, row)
11676 struct frame *f;
11677 struct glyph_row *row;
11678{
11679 int used = row->used[TEXT_AREA];
11680
11681 if (used)
11682 {
11683 struct glyph *start = row->glyphs[TEXT_AREA];
11684 struct glyph *glyph = start + used - 1;
11685
11686 /* Skip over the space glyph inserted to display the
11687 cursor at the end of a line. */
11688 if (glyph->type == CHAR_GLYPH
43d120d8 11689 && glyph->u.ch == ' '
6fc556fd 11690 && INTEGERP (glyph->object))
5f5c8ee5
GM
11691 --glyph;
11692
11693 /* If last glyph is a space or stretch, and it's trailing
11694 whitespace, set the face of all trailing whitespace glyphs in
11695 IT->glyph_row to `trailing-whitespace'. */
11696 if (glyph >= start
11697 && BUFFERP (glyph->object)
11698 && (glyph->type == STRETCH_GLYPH
11699 || (glyph->type == CHAR_GLYPH
43d120d8 11700 && glyph->u.ch == ' '))
5f5c8ee5 11701 && trailing_whitespace_p (glyph->charpos))
545e04f6 11702 {
980806b6 11703 int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
5f5c8ee5
GM
11704
11705 while (glyph >= start
11706 && BUFFERP (glyph->object)
11707 && (glyph->type == STRETCH_GLYPH
11708 || (glyph->type == CHAR_GLYPH
43d120d8
KH
11709 && glyph->u.ch == ' ')))
11710 (glyph--)->face_id = face_id;
545e04f6 11711 }
a2889657 11712 }
5f5c8ee5 11713}
a2889657 11714
5fcbb24d 11715
cafafe0b
GM
11716/* Value is non-zero if glyph row ROW in window W should be
11717 used to put the cursor on. */
11718
11719static int
11720cursor_row_p (w, row)
11721 struct window *w;
11722 struct glyph_row *row;
11723{
9a038881
GM
11724 int cursor_row_p = 1;
11725
cafafe0b
GM
11726 if (PT == MATRIX_ROW_END_CHARPOS (row))
11727 {
9a038881
GM
11728 /* If the row ends with a newline from a string, we don't want
11729 the cursor there (if the row is continued it doesn't end in a
11730 newline). */
11731 if (CHARPOS (row->end.string_pos) >= 0
11732 || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
11733 cursor_row_p = row->continued_p;
11734
11735 /* If the row ends at ZV, display the cursor at the end of that
11736 row instead of at the start of the row below. */
11737 else if (row->ends_at_zv_p)
11738 cursor_row_p = 1;
11739 else
11740 cursor_row_p = 0;
cafafe0b
GM
11741 }
11742
9a038881 11743 return cursor_row_p;
cafafe0b
GM
11744}
11745
11746
5f5c8ee5
GM
11747/* Construct the glyph row IT->glyph_row in the desired matrix of
11748 IT->w from text at the current position of IT. See dispextern.h
11749 for an overview of struct it. Value is non-zero if
11750 IT->glyph_row displays text, as opposed to a line displaying ZV
11751 only. */
11752
11753static int
11754display_line (it)
11755 struct it *it;
11756{
11757 struct glyph_row *row = it->glyph_row;
11758
11759 /* We always start displaying at hpos zero even if hscrolled. */
11760 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 11761
5f5c8ee5
GM
11762 /* We must not display in a row that's not a text row. */
11763 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
11764 < it->w->desired_matrix->nrows);
12adba34 11765
5f5c8ee5
GM
11766 /* Is IT->w showing the region? */
11767 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 11768
5f5c8ee5
GM
11769 /* Clear the result glyph row and enable it. */
11770 prepare_desired_row (row);
12adba34 11771
5f5c8ee5
GM
11772 row->y = it->current_y;
11773 row->start = it->current;
11774 row->continuation_lines_width = it->continuation_lines_width;
11775 row->displays_text_p = 1;
91004049
GM
11776 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
11777 it->starts_in_middle_of_char_p = 0;
5f5c8ee5
GM
11778
11779 /* Arrange the overlays nicely for our purposes. Usually, we call
11780 display_line on only one line at a time, in which case this
11781 can't really hurt too much, or we call it on lines which appear
11782 one after another in the buffer, in which case all calls to
11783 recenter_overlay_lists but the first will be pretty cheap. */
11784 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
11785
5f5c8ee5
GM
11786 /* Move over display elements that are not visible because we are
11787 hscrolled. This may stop at an x-position < IT->first_visible_x
11788 if the first glyph is partially visible or if we hit a line end. */
11789 if (it->current_x < it->first_visible_x)
11790 move_it_in_display_line_to (it, ZV, it->first_visible_x,
11791 MOVE_TO_POS | MOVE_TO_X);
11792
11793 /* Get the initial row height. This is either the height of the
11794 text hscrolled, if there is any, or zero. */
11795 row->ascent = it->max_ascent;
11796 row->height = it->max_ascent + it->max_descent;
312246d1
GM
11797 row->phys_ascent = it->max_phys_ascent;
11798 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
11799
11800 /* Loop generating characters. The loop is left with IT on the next
11801 character to display. */
11802 while (1)
11803 {
11804 int n_glyphs_before, hpos_before, x_before;
11805 int x, i, nglyphs;
ae26e27d 11806 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
b28cb6ed 11807
5f5c8ee5
GM
11808 /* Retrieve the next thing to display. Value is zero if end of
11809 buffer reached. */
11810 if (!get_next_display_element (it))
11811 {
11812 /* Maybe add a space at the end of this line that is used to
1b335865
GM
11813 display the cursor there under X. Set the charpos of the
11814 first glyph of blank lines not corresponding to any text
11815 to -1. */
11816 if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
11817 || row->used[TEXT_AREA] == 0)
a2889657 11818 {
5f5c8ee5
GM
11819 row->glyphs[TEXT_AREA]->charpos = -1;
11820 row->displays_text_p = 0;
11821
11822 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines))
11823 row->indicate_empty_line_p = 1;
a2889657 11824 }
5f5c8ee5
GM
11825
11826 it->continuation_lines_width = 0;
11827 row->ends_at_zv_p = 1;
11828 break;
a2889657 11829 }
a2889657 11830
5f5c8ee5
GM
11831 /* Now, get the metrics of what we want to display. This also
11832 generates glyphs in `row' (which is IT->glyph_row). */
11833 n_glyphs_before = row->used[TEXT_AREA];
11834 x = it->current_x;
e6819faf
GM
11835
11836 /* Remember the line height so far in case the next element doesn't
11837 fit on the line. */
11838 if (!it->truncate_lines_p)
11839 {
11840 ascent = it->max_ascent;
11841 descent = it->max_descent;
11842 phys_ascent = it->max_phys_ascent;
11843 phys_descent = it->max_phys_descent;
11844 }
11845
5f5c8ee5 11846 PRODUCE_GLYPHS (it);
a2889657 11847
5f5c8ee5
GM
11848 /* If this display element was in marginal areas, continue with
11849 the next one. */
11850 if (it->area != TEXT_AREA)
a2889657 11851 {
5f5c8ee5
GM
11852 row->ascent = max (row->ascent, it->max_ascent);
11853 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11854 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11855 row->phys_height = max (row->phys_height,
11856 it->max_phys_ascent + it->max_phys_descent);
cafafe0b 11857 set_iterator_to_next (it, 1);
5f5c8ee5
GM
11858 continue;
11859 }
5936754e 11860
5f5c8ee5
GM
11861 /* Does the display element fit on the line? If we truncate
11862 lines, we should draw past the right edge of the window. If
11863 we don't truncate, we want to stop so that we can display the
11864 continuation glyph before the right margin. If lines are
11865 continued, there are two possible strategies for characters
11866 resulting in more than 1 glyph (e.g. tabs): Display as many
11867 glyphs as possible in this line and leave the rest for the
11868 continuation line, or display the whole element in the next
11869 line. Original redisplay did the former, so we do it also. */
11870 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
11871 hpos_before = it->hpos;
11872 x_before = x;
11873
11874 if (nglyphs == 1
11875 && it->current_x < it->last_visible_x)
11876 {
11877 ++it->hpos;
11878 row->ascent = max (row->ascent, it->max_ascent);
11879 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11880 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11881 row->phys_height = max (row->phys_height,
11882 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11883 if (it->current_x - it->pixel_width < it->first_visible_x)
11884 row->x = x - it->first_visible_x;
11885 }
11886 else
11887 {
11888 int new_x;
11889 struct glyph *glyph;
11890
11891 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 11892 {
5f5c8ee5
GM
11893 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
11894 new_x = x + glyph->pixel_width;
11895
11896 if (/* Lines are continued. */
11897 !it->truncate_lines_p
11898 && (/* Glyph doesn't fit on the line. */
11899 new_x > it->last_visible_x
11900 /* Or it fits exactly on a window system frame. */
11901 || (new_x == it->last_visible_x
11902 && FRAME_WINDOW_P (it->f))))
a2889657 11903 {
5f5c8ee5
GM
11904 /* End of a continued line. */
11905
11906 if (it->hpos == 0
11907 || (new_x == it->last_visible_x
11908 && FRAME_WINDOW_P (it->f)))
11909 {
e6819faf
GM
11910 /* Current glyph is the only one on the line or
11911 fits exactly on the line. We must continue
11912 the line because we can't draw the cursor
11913 after the glyph. */
5f5c8ee5
GM
11914 row->continued_p = 1;
11915 it->current_x = new_x;
11916 it->continuation_lines_width += new_x;
11917 ++it->hpos;
11918 if (i == nglyphs - 1)
cafafe0b 11919 set_iterator_to_next (it, 1);
5f5c8ee5 11920 }
3b3c4bf0
GM
11921 else if (CHAR_GLYPH_PADDING_P (*glyph)
11922 && !FRAME_WINDOW_P (it->f))
11923 {
11924 /* A padding glyph that doesn't fit on this line.
11925 This means the whole character doesn't fit
11926 on the line. */
11927 row->used[TEXT_AREA] = n_glyphs_before;
11928
11929 /* Fill the rest of the row with continuation
11930 glyphs like in 20.x. */
11931 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
11932 < row->glyphs[1 + TEXT_AREA])
11933 produce_special_glyphs (it, IT_CONTINUATION);
11934
11935 row->continued_p = 1;
11936 it->current_x = x_before;
11937 it->continuation_lines_width += x_before;
11938
11939 /* Restore the height to what it was before the
11940 element not fitting on the line. */
11941 it->max_ascent = ascent;
11942 it->max_descent = descent;
11943 it->max_phys_ascent = phys_ascent;
11944 it->max_phys_descent = phys_descent;
11945 }
5f5c8ee5 11946 else
5936754e 11947 {
5f5c8ee5
GM
11948 /* Display element draws past the right edge of
11949 the window. Restore positions to values
11950 before the element. The next line starts
11951 with current_x before the glyph that could
11952 not be displayed, so that TAB works right. */
11953 row->used[TEXT_AREA] = n_glyphs_before + i;
11954
11955 /* Display continuation glyphs. */
11956 if (!FRAME_WINDOW_P (it->f))
11957 produce_special_glyphs (it, IT_CONTINUATION);
11958 row->continued_p = 1;
11959
11960 it->current_x = x;
11961 it->continuation_lines_width += x;
91004049
GM
11962 if (nglyphs > 1 && i > 0)
11963 {
11964 row->ends_in_middle_of_char_p = 1;
11965 it->starts_in_middle_of_char_p = 1;
11966 }
e6819faf
GM
11967
11968 /* Restore the height to what it was before the
11969 element not fitting on the line. */
11970 it->max_ascent = ascent;
11971 it->max_descent = descent;
11972 it->max_phys_ascent = phys_ascent;
11973 it->max_phys_descent = phys_descent;
5936754e 11974 }
e6819faf 11975
5f5c8ee5
GM
11976 break;
11977 }
11978 else if (new_x > it->first_visible_x)
11979 {
11980 /* Increment number of glyphs actually displayed. */
11981 ++it->hpos;
11982
11983 if (x < it->first_visible_x)
11984 /* Glyph is partially visible, i.e. row starts at
11985 negative X position. */
11986 row->x = x - it->first_visible_x;
11987 }
11988 else
11989 {
11990 /* Glyph is completely off the left margin of the
11991 window. This should not happen because of the
11992 move_it_in_display_line at the start of
11993 this function. */
11994 abort ();
a2889657 11995 }
a2889657 11996 }
5f5c8ee5
GM
11997
11998 row->ascent = max (row->ascent, it->max_ascent);
11999 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
12000 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
12001 row->phys_height = max (row->phys_height,
12002 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
12003
12004 /* End of this display line if row is continued. */
12005 if (row->continued_p)
12006 break;
a2889657 12007 }
a2889657 12008
5f5c8ee5
GM
12009 /* Is this a line end? If yes, we're also done, after making
12010 sure that a non-default face is extended up to the right
12011 margin of the window. */
12012 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 12013 {
5f5c8ee5
GM
12014 int used_before = row->used[TEXT_AREA];
12015
12016 /* Add a space at the end of the line that is used to
12017 display the cursor there. */
12018 append_space (it, 0);
12019
12020 /* Extend the face to the end of the line. */
12021 extend_face_to_end_of_line (it);
12022
12023 /* Make sure we have the position. */
12024 if (used_before == 0)
12025 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
12026
12027 /* Consume the line end. This skips over invisible lines. */
cafafe0b 12028 set_iterator_to_next (it, 1);
5f5c8ee5
GM
12029 it->continuation_lines_width = 0;
12030 break;
1c9241f5 12031 }
a2889657 12032
5f5c8ee5
GM
12033 /* Proceed with next display element. Note that this skips
12034 over lines invisible because of selective display. */
cafafe0b 12035 set_iterator_to_next (it, 1);
b1d1124b 12036
5f5c8ee5
GM
12037 /* If we truncate lines, we are done when the last displayed
12038 glyphs reach past the right margin of the window. */
12039 if (it->truncate_lines_p
12040 && (FRAME_WINDOW_P (it->f)
12041 ? (it->current_x >= it->last_visible_x)
12042 : (it->current_x > it->last_visible_x)))
75d13c64 12043 {
5f5c8ee5
GM
12044 /* Maybe add truncation glyphs. */
12045 if (!FRAME_WINDOW_P (it->f))
12046 {
12047 --it->glyph_row->used[TEXT_AREA];
12048 produce_special_glyphs (it, IT_TRUNCATION);
12049 }
12050
12051 row->truncated_on_right_p = 1;
12052 it->continuation_lines_width = 0;
312246d1 12053 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
12054 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
12055 it->hpos = hpos_before;
12056 it->current_x = x_before;
12057 break;
75d13c64 12058 }
a2889657 12059 }
a2889657 12060
5f5c8ee5
GM
12061 /* If line is not empty and hscrolled, maybe insert truncation glyphs
12062 at the left window margin. */
12063 if (it->first_visible_x
12064 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
12065 {
12066 if (!FRAME_WINDOW_P (it->f))
12067 insert_left_trunc_glyphs (it);
12068 row->truncated_on_left_p = 1;
12069 }
a2889657 12070
5f5c8ee5
GM
12071 /* If the start of this line is the overlay arrow-position, then
12072 mark this glyph row as the one containing the overlay arrow.
12073 This is clearly a mess with variable size fonts. It would be
12074 better to let it be displayed like cursors under X. */
e24c997d 12075 if (MARKERP (Voverlay_arrow_position)
a2889657 12076 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
12077 && (MATRIX_ROW_START_CHARPOS (row)
12078 == marker_position (Voverlay_arrow_position))
e24c997d 12079 && STRINGP (Voverlay_arrow_string)
a2889657
JB
12080 && ! overlay_arrow_seen)
12081 {
5f5c8ee5
GM
12082 /* Overlay arrow in window redisplay is a bitmap. */
12083 if (!FRAME_WINDOW_P (it->f))
c4628384 12084 {
5f5c8ee5
GM
12085 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
12086 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
12087 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
12088 struct glyph *p = row->glyphs[TEXT_AREA];
12089 struct glyph *p2, *end;
12090
12091 /* Copy the arrow glyphs. */
12092 while (glyph < arrow_end)
12093 *p++ = *glyph++;
12094
12095 /* Throw away padding glyphs. */
12096 p2 = p;
12097 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
12098 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
12099 ++p2;
12100 if (p2 > p)
212e4f87 12101 {
5f5c8ee5
GM
12102 while (p2 < end)
12103 *p++ = *p2++;
12104 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 12105 }
c4628384 12106 }
5f5c8ee5 12107
a2889657 12108 overlay_arrow_seen = 1;
5f5c8ee5 12109 row->overlay_arrow_p = 1;
a2889657
JB
12110 }
12111
5f5c8ee5
GM
12112 /* Compute pixel dimensions of this line. */
12113 compute_line_metrics (it);
12114
12115 /* Remember the position at which this line ends. */
12116 row->end = it->current;
12117
173cbca8 12118 /* Maybe set the cursor. */
5f5c8ee5
GM
12119 if (it->w->cursor.vpos < 0
12120 && PT >= MATRIX_ROW_START_CHARPOS (row)
cafafe0b
GM
12121 && PT <= MATRIX_ROW_END_CHARPOS (row)
12122 && cursor_row_p (it->w, row))
12123 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
12124
12125 /* Highlight trailing whitespace. */
8f897821 12126 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
12127 highlight_trailing_whitespace (it->f, it->glyph_row);
12128
12129 /* Prepare for the next line. This line starts horizontally at (X
12130 HPOS) = (0 0). Vertical positions are incremented. As a
12131 convenience for the caller, IT->glyph_row is set to the next
12132 row to be used. */
12133 it->current_x = it->hpos = 0;
12134 it->current_y += row->height;
12135 ++it->vpos;
12136 ++it->glyph_row;
12137 return row->displays_text_p;
a2889657 12138}
5f5c8ee5
GM
12139
12140
a2889657 12141\f
5f5c8ee5
GM
12142/***********************************************************************
12143 Menu Bar
12144 ***********************************************************************/
12145
12146/* Redisplay the menu bar in the frame for window W.
12147
12148 The menu bar of X frames that don't have X toolkit support is
12149 displayed in a special window W->frame->menu_bar_window.
12150
12151 The menu bar of terminal frames is treated specially as far as
12152 glyph matrices are concerned. Menu bar lines are not part of
12153 windows, so the update is done directly on the frame matrix rows
12154 for the menu bar. */
7ce2c095
RS
12155
12156static void
12157display_menu_bar (w)
12158 struct window *w;
12159{
5f5c8ee5
GM
12160 struct frame *f = XFRAME (WINDOW_FRAME (w));
12161 struct it it;
12162 Lisp_Object items;
8351baf2 12163 int i;
7ce2c095 12164
5f5c8ee5 12165 /* Don't do all this for graphical frames. */
dc937613 12166#ifdef HAVE_NTGUI
d129c4c2
KH
12167 if (!NILP (Vwindow_system))
12168 return;
dc937613 12169#endif
dc937613 12170#ifdef USE_X_TOOLKIT
d3413a53 12171 if (FRAME_X_P (f))
7ce2c095 12172 return;
5f5c8ee5 12173#endif
1a578e9b
AC
12174#ifdef macintosh
12175 if (FRAME_MAC_P (f))
12176 return;
12177#endif
5f5c8ee5
GM
12178
12179#ifdef USE_X_TOOLKIT
12180 xassert (!FRAME_WINDOW_P (f));
52377a47 12181 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5
GM
12182 it.first_visible_x = 0;
12183 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
12184#else /* not USE_X_TOOLKIT */
12185 if (FRAME_WINDOW_P (f))
12186 {
12187 /* Menu bar lines are displayed in the desired matrix of the
12188 dummy window menu_bar_window. */
12189 struct window *menu_w;
12190 xassert (WINDOWP (f->menu_bar_window));
12191 menu_w = XWINDOW (f->menu_bar_window);
12192 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 12193 MENU_FACE_ID);
5f5c8ee5
GM
12194 it.first_visible_x = 0;
12195 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
12196 }
12197 else
12198 {
12199 /* This is a TTY frame, i.e. character hpos/vpos are used as
12200 pixel x/y. */
12201 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 12202 MENU_FACE_ID);
5f5c8ee5
GM
12203 it.first_visible_x = 0;
12204 it.last_visible_x = FRAME_WIDTH (f);
12205 }
12206#endif /* not USE_X_TOOLKIT */
12207
12208 /* Clear all rows of the menu bar. */
12209 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
12210 {
12211 struct glyph_row *row = it.glyph_row + i;
12212 clear_glyph_row (row);
12213 row->enabled_p = 1;
12214 row->full_width_p = 1;
12215 }
7ce2c095 12216
5f5c8ee5
GM
12217 /* Make the first line of the menu bar appear in reverse video. */
12218 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
7ce2c095 12219
5f5c8ee5
GM
12220 /* Display all items of the menu bar. */
12221 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 12222 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 12223 {
5f5c8ee5
GM
12224 Lisp_Object string;
12225
12226 /* Stop at nil string. */
8351baf2
RS
12227 string = XVECTOR (items)->contents[i + 1];
12228 if (NILP (string))
12229 break;
2d66ad19 12230
5f5c8ee5
GM
12231 /* Remember where item was displayed. */
12232 XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos);
7ce2c095 12233
5f5c8ee5
GM
12234 /* Display the item, pad with one space. */
12235 if (it.current_x < it.last_visible_x)
12236 display_string (NULL, string, Qnil, 0, 0, &it,
12237 XSTRING (string)->size + 1, 0, 0, -1);
7ce2c095
RS
12238 }
12239
2d66ad19 12240 /* Fill out the line with spaces. */
5f5c8ee5
GM
12241 if (it.current_x < it.last_visible_x)
12242 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 12243
5f5c8ee5
GM
12244 /* Compute the total height of the lines. */
12245 compute_line_metrics (&it);
7ce2c095 12246}
5f5c8ee5
GM
12247
12248
7ce2c095 12249\f
5f5c8ee5
GM
12250/***********************************************************************
12251 Mode Line
12252 ***********************************************************************/
12253
715e84c9
GM
12254/* Redisplay mode lines in the window tree whose root is WINDOW. If
12255 FORCE is non-zero, redisplay mode lines unconditionally.
12256 Otherwise, redisplay only mode lines that are garbaged. Value is
12257 the number of windows whose mode lines were redisplayed. */
a2889657 12258
715e84c9
GM
12259static int
12260redisplay_mode_lines (window, force)
12261 Lisp_Object window;
12262 int force;
12263{
12264 int nwindows = 0;
12265
12266 while (!NILP (window))
12267 {
12268 struct window *w = XWINDOW (window);
12269
12270 if (WINDOWP (w->hchild))
12271 nwindows += redisplay_mode_lines (w->hchild, force);
12272 else if (WINDOWP (w->vchild))
12273 nwindows += redisplay_mode_lines (w->vchild, force);
12274 else if (force
12275 || FRAME_GARBAGED_P (XFRAME (w->frame))
12276 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
12277 {
12278 Lisp_Object old_selected_frame;
12279 struct text_pos lpoint;
12280 struct buffer *old = current_buffer;
12281
12282 /* Set the window's buffer for the mode line display. */
12283 SET_TEXT_POS (lpoint, PT, PT_BYTE);
12284 set_buffer_internal_1 (XBUFFER (w->buffer));
12285
12286 /* Point refers normally to the selected window. For any
12287 other window, set up appropriate value. */
12288 if (!EQ (window, selected_window))
12289 {
12290 struct text_pos pt;
12291
12292 SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
12293 if (CHARPOS (pt) < BEGV)
12294 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
12295 else if (CHARPOS (pt) > (ZV - 1))
12296 TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
12297 else
12298 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
12299 }
12300
12301 /* Temporarily set up the selected frame. */
12302 old_selected_frame = selected_frame;
12303 selected_frame = w->frame;
12304
12305 /* Display mode lines. */
12306 clear_glyph_matrix (w->desired_matrix);
12307 if (display_mode_lines (w))
12308 {
12309 ++nwindows;
12310 w->must_be_updated_p = 1;
12311 }
12312
12313 /* Restore old settings. */
12314 selected_frame = old_selected_frame;
12315 set_buffer_internal_1 (old);
12316 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
12317 }
12318
12319 window = w->next;
12320 }
12321
12322 return nwindows;
12323}
12324
12325
12326/* Display the mode and/or top line of window W. Value is the number
12327 of mode lines displayed. */
12328
12329static int
5f5c8ee5 12330display_mode_lines (w)
a2889657
JB
12331 struct window *w;
12332{
715e84c9
GM
12333 int n = 0;
12334
5f5c8ee5 12335 /* These will be set while the mode line specs are processed. */
aa6d10fa 12336 line_number_displayed = 0;
155ef550 12337 w->column_number_displayed = Qnil;
aa6d10fa 12338
5f5c8ee5 12339 if (WINDOW_WANTS_MODELINE_P (w))
715e84c9
GM
12340 {
12341 display_mode_line (w, MODE_LINE_FACE_ID,
12342 current_buffer->mode_line_format);
12343 ++n;
12344 }
5f5c8ee5 12345
045dee35 12346 if (WINDOW_WANTS_HEADER_LINE_P (w))
715e84c9
GM
12347 {
12348 display_mode_line (w, HEADER_LINE_FACE_ID,
12349 current_buffer->header_line_format);
12350 ++n;
12351 }
12352
12353 return n;
5f5c8ee5 12354}
03b294dc 12355
03b294dc 12356
5f5c8ee5 12357/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 12358 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
5f5c8ee5 12359 FORMAT is the mode line format to display. */
03b294dc 12360
5f5c8ee5
GM
12361static void
12362display_mode_line (w, face_id, format)
12363 struct window *w;
12364 enum face_id face_id;
12365 Lisp_Object format;
12366{
12367 struct it it;
12368 struct face *face;
03b294dc 12369
5f5c8ee5
GM
12370 init_iterator (&it, w, -1, -1, NULL, face_id);
12371 prepare_desired_row (it.glyph_row);
12372
12373 /* Temporarily make frame's keyboard the current kboard so that
12374 kboard-local variables in the mode_line_format will get the right
12375 values. */
12376 push_frame_kboard (it.f);
12377 display_mode_element (&it, 0, 0, 0, format);
12378 pop_frame_kboard ();
a2889657 12379
5f5c8ee5
GM
12380 /* Fill up with spaces. */
12381 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
12382
12383 compute_line_metrics (&it);
12384 it.glyph_row->full_width_p = 1;
12385 it.glyph_row->mode_line_p = 1;
12386 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
12387 it.glyph_row->continued_p = 0;
12388 it.glyph_row->truncated_on_left_p = 0;
12389 it.glyph_row->truncated_on_right_p = 0;
12390
12391 /* Make a 3D mode-line have a shadow at its right end. */
12392 face = FACE_FROM_ID (it.f, face_id);
12393 extend_face_to_end_of_line (&it);
12394 if (face->box != FACE_NO_BOX)
d7eb09a0 12395 {
5f5c8ee5
GM
12396 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
12397 + it.glyph_row->used[TEXT_AREA] - 1);
12398 last->right_box_line_p = 1;
d7eb09a0 12399 }
a2889657
JB
12400}
12401
a2889657 12402
5f5c8ee5
GM
12403/* Contribute ELT to the mode line for window IT->w. How it
12404 translates into text depends on its data type.
a2889657 12405
5f5c8ee5 12406 IT describes the display environment in which we display, as usual.
a2889657
JB
12407
12408 DEPTH is the depth in recursion. It is used to prevent
12409 infinite recursion here.
12410
5f5c8ee5
GM
12411 FIELD_WIDTH is the number of characters the display of ELT should
12412 occupy in the mode line, and PRECISION is the maximum number of
12413 characters to display from ELT's representation. See
12414 display_string for details. *
a2889657 12415
5f5c8ee5 12416 Returns the hpos of the end of the text generated by ELT. */
a2889657
JB
12417
12418static int
5f5c8ee5
GM
12419display_mode_element (it, depth, field_width, precision, elt)
12420 struct it *it;
a2889657 12421 int depth;
5f5c8ee5
GM
12422 int field_width, precision;
12423 Lisp_Object elt;
a2889657 12424{
5f5c8ee5
GM
12425 int n = 0, field, prec;
12426
a2889657
JB
12427 tail_recurse:
12428 if (depth > 10)
12429 goto invalid;
12430
12431 depth++;
12432
0220c518 12433 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
12434 {
12435 case Lisp_String:
12436 {
12437 /* A string: output it and check for %-constructs within it. */
5f5c8ee5
GM
12438 unsigned char c;
12439 unsigned char *this = XSTRING (elt)->data;
12440 unsigned char *lisp_string = this;
12441
12442 while ((precision <= 0 || n < precision)
12443 && *this
12444 && (frame_title_ptr
12445 || it->current_x < it->last_visible_x))
a2889657
JB
12446 {
12447 unsigned char *last = this;
5f5c8ee5
GM
12448
12449 /* Advance to end of string or next format specifier. */
a2889657
JB
12450 while ((c = *this++) != '\0' && c != '%')
12451 ;
5f5c8ee5 12452
a2889657
JB
12453 if (this - 1 != last)
12454 {
5f5c8ee5
GM
12455 /* Output to end of string or up to '%'. Field width
12456 is length of string. Don't output more than
12457 PRECISION allows us. */
12458 prec = --this - last;
12459 if (precision > 0 && prec > precision - n)
12460 prec = precision - n;
12461
d39b6696 12462 if (frame_title_ptr)
5f5c8ee5 12463 n += store_frame_title (last, prec, prec);
d39b6696 12464 else
5f5c8ee5
GM
12465 n += display_string (NULL, elt, Qnil, 0, last - lisp_string,
12466 it, 0, prec, 0, -1);
a2889657
JB
12467 }
12468 else /* c == '%' */
12469 {
5f5c8ee5
GM
12470 unsigned char *percent_position = this;
12471
12472 /* Get the specified minimum width. Zero means
12473 don't pad. */
12474 field = 0;
a2889657 12475 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 12476 field = field * 10 + c - '0';
a2889657 12477
5f5c8ee5
GM
12478 /* Don't pad beyond the total padding allowed. */
12479 if (field_width - n > 0 && field > field_width - n)
12480 field = field_width - n;
a2889657 12481
5f5c8ee5
GM
12482 /* Note that either PRECISION <= 0 or N < PRECISION. */
12483 prec = precision - n;
12484
a2889657 12485 if (c == 'M')
5f5c8ee5
GM
12486 n += display_mode_element (it, depth, field, prec,
12487 Vglobal_mode_string);
a2889657 12488 else if (c != 0)
d39b6696 12489 {
5f5c8ee5
GM
12490 unsigned char *spec
12491 = decode_mode_spec (it->w, c, field, prec);
12492
d39b6696 12493 if (frame_title_ptr)
5f5c8ee5 12494 n += store_frame_title (spec, field, prec);
d39b6696 12495 else
5f5c8ee5
GM
12496 {
12497 int nglyphs_before
12498 = it->glyph_row->used[TEXT_AREA];
12499 int charpos
12500 = percent_position - XSTRING (elt)->data;
12501 int nwritten
12502 = display_string (spec, Qnil, elt, charpos, 0, it,
12503 field, prec, 0, -1);
12504
12505 /* Assign to the glyphs written above the
12506 string where the `%x' came from, position
12507 of the `%'. */
12508 if (nwritten > 0)
12509 {
12510 struct glyph *glyph
12511 = (it->glyph_row->glyphs[TEXT_AREA]
12512 + nglyphs_before);
12513 int i;
12514
12515 for (i = 0; i < nwritten; ++i)
12516 {
12517 glyph[i].object = elt;
12518 glyph[i].charpos = charpos;
12519 }
12520
12521 n += nwritten;
12522 }
12523 }
d39b6696 12524 }
a2889657
JB
12525 }
12526 }
12527 }
12528 break;
12529
12530 case Lisp_Symbol:
12531 /* A symbol: process the value of the symbol recursively
12532 as if it appeared here directly. Avoid error if symbol void.
12533 Special case: if value of symbol is a string, output the string
12534 literally. */
12535 {
12536 register Lisp_Object tem;
12537 tem = Fboundp (elt);
265a9e55 12538 if (!NILP (tem))
a2889657
JB
12539 {
12540 tem = Fsymbol_value (elt);
12541 /* If value is a string, output that string literally:
12542 don't check for % within it. */
e24c997d 12543 if (STRINGP (tem))
d39b6696 12544 {
5f5c8ee5
GM
12545 prec = XSTRING (tem)->size;
12546 if (precision > 0 && prec > precision - n)
12547 prec = precision - n;
d39b6696 12548 if (frame_title_ptr)
5f5c8ee5 12549 n += store_frame_title (XSTRING (tem)->data, -1, prec);
d39b6696 12550 else
5f5c8ee5
GM
12551 n += display_string (NULL, tem, Qnil, 0, 0, it,
12552 0, prec, 0, -1);
d39b6696 12553 }
a2889657 12554 else if (!EQ (tem, elt))
5f5c8ee5
GM
12555 {
12556 /* Give up right away for nil or t. */
12557 elt = tem;
12558 goto tail_recurse;
12559 }
a2889657
JB
12560 }
12561 }
12562 break;
12563
12564 case Lisp_Cons:
12565 {
12566 register Lisp_Object car, tem;
12567
12568 /* A cons cell: three distinct cases.
12569 If first element is a string or a cons, process all the elements
12570 and effectively concatenate them.
12571 If first element is a negative number, truncate displaying cdr to
12572 at most that many characters. If positive, pad (with spaces)
12573 to at least that many characters.
12574 If first element is a symbol, process the cadr or caddr recursively
12575 according to whether the symbol's value is non-nil or nil. */
9472f927 12576 car = XCAR (elt);
5f5c8ee5
GM
12577 if (EQ (car, QCeval) && CONSP (XCDR (elt)))
12578 {
12579 /* An element of the form (:eval FORM) means evaluate FORM
12580 and use the result as mode line elements. */
12581 struct gcpro gcpro1;
12582 Lisp_Object spec;
12583
116d6f5c 12584 spec = safe_eval (XCAR (XCDR (elt)));
5f5c8ee5
GM
12585 GCPRO1 (spec);
12586 n += display_mode_element (it, depth, field_width - n,
12587 precision - n, spec);
12588 UNGCPRO;
12589 }
12590 else if (SYMBOLP (car))
a2889657
JB
12591 {
12592 tem = Fboundp (car);
9472f927 12593 elt = XCDR (elt);
e24c997d 12594 if (!CONSP (elt))
a2889657
JB
12595 goto invalid;
12596 /* elt is now the cdr, and we know it is a cons cell.
12597 Use its car if CAR has a non-nil value. */
265a9e55 12598 if (!NILP (tem))
a2889657
JB
12599 {
12600 tem = Fsymbol_value (car);
265a9e55 12601 if (!NILP (tem))
9472f927
GM
12602 {
12603 elt = XCAR (elt);
12604 goto tail_recurse;
12605 }
a2889657
JB
12606 }
12607 /* Symbol's value is nil (or symbol is unbound)
12608 Get the cddr of the original list
12609 and if possible find the caddr and use that. */
9472f927 12610 elt = XCDR (elt);
265a9e55 12611 if (NILP (elt))
a2889657 12612 break;
e24c997d 12613 else if (!CONSP (elt))
a2889657 12614 goto invalid;
9472f927 12615 elt = XCAR (elt);
a2889657
JB
12616 goto tail_recurse;
12617 }
e24c997d 12618 else if (INTEGERP (car))
a2889657
JB
12619 {
12620 register int lim = XINT (car);
9472f927 12621 elt = XCDR (elt);
a2889657 12622 if (lim < 0)
5f5c8ee5
GM
12623 {
12624 /* Negative int means reduce maximum width. */
12625 if (precision <= 0)
12626 precision = -lim;
12627 else
12628 precision = min (precision, -lim);
12629 }
a2889657
JB
12630 else if (lim > 0)
12631 {
12632 /* Padding specified. Don't let it be more than
12633 current maximum. */
5f5c8ee5
GM
12634 if (precision > 0)
12635 lim = min (precision, lim);
12636
a2889657
JB
12637 /* If that's more padding than already wanted, queue it.
12638 But don't reduce padding already specified even if
12639 that is beyond the current truncation point. */
5f5c8ee5 12640 field_width = max (lim, field_width);
a2889657
JB
12641 }
12642 goto tail_recurse;
12643 }
e24c997d 12644 else if (STRINGP (car) || CONSP (car))
a2889657
JB
12645 {
12646 register int limit = 50;
5f5c8ee5
GM
12647 /* Limit is to protect against circular lists. */
12648 while (CONSP (elt)
12649 && --limit > 0
12650 && (precision <= 0 || n < precision))
a2889657 12651 {
5f5c8ee5 12652 n += display_mode_element (it, depth, field_width - n,
9472f927
GM
12653 precision - n, XCAR (elt));
12654 elt = XCDR (elt);
a2889657
JB
12655 }
12656 }
12657 }
12658 break;
12659
12660 default:
12661 invalid:
d39b6696 12662 if (frame_title_ptr)
5f5c8ee5 12663 n += store_frame_title ("*invalid*", 0, precision - n);
d39b6696 12664 else
5f5c8ee5
GM
12665 n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
12666 precision - n, 0, 0);
12667 return n;
a2889657
JB
12668 }
12669
5f5c8ee5
GM
12670 /* Pad to FIELD_WIDTH. */
12671 if (field_width > 0 && n < field_width)
12672 {
12673 if (frame_title_ptr)
12674 n += store_frame_title ("", field_width - n, 0);
12675 else
12676 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
12677 0, 0, 0);
12678 }
12679
12680 return n;
a2889657 12681}
5f5c8ee5
GM
12682
12683
766525bc
RS
12684/* Write a null-terminated, right justified decimal representation of
12685 the positive integer D to BUF using a minimal field width WIDTH. */
12686
12687static void
12688pint2str (buf, width, d)
12689 register char *buf;
12690 register int width;
12691 register int d;
12692{
12693 register char *p = buf;
12694
12695 if (d <= 0)
5f5c8ee5 12696 *p++ = '0';
766525bc 12697 else
5f5c8ee5 12698 {
766525bc 12699 while (d > 0)
5f5c8ee5 12700 {
766525bc
RS
12701 *p++ = d % 10 + '0';
12702 d /= 10;
5f5c8ee5
GM
12703 }
12704 }
12705
12706 for (width -= (int) (p - buf); width > 0; --width)
12707 *p++ = ' ';
766525bc
RS
12708 *p-- = '\0';
12709 while (p > buf)
5f5c8ee5 12710 {
766525bc
RS
12711 d = *buf;
12712 *buf++ = *p;
12713 *p-- = d;
5f5c8ee5 12714 }
766525bc
RS
12715}
12716
5f5c8ee5 12717/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
12718 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
12719 type of CODING_SYSTEM. Return updated pointer into BUF. */
12720
6693a99a 12721static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 12722
1c9241f5
KH
12723static char *
12724decode_mode_spec_coding (coding_system, buf, eol_flag)
12725 Lisp_Object coding_system;
12726 register char *buf;
12727 int eol_flag;
12728{
1e1078d6 12729 Lisp_Object val;
916848d8 12730 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
302f2b38
EZ
12731 unsigned char *eol_str;
12732 int eol_str_len;
12733 /* The EOL conversion we are using. */
12734 Lisp_Object eoltype;
1e1078d6 12735
4a09dee0 12736 val = Fget (coding_system, Qcoding_system);
085536c2 12737 eoltype = Qnil;
1c9241f5 12738
4a09dee0 12739 if (!VECTORP (val)) /* Not yet decided. */
1c9241f5 12740 {
916848d8
RS
12741 if (multibyte)
12742 *buf++ = '-';
21e989e3 12743 if (eol_flag)
302f2b38 12744 eoltype = eol_mnemonic_undecided;
1e1078d6 12745 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
12746 }
12747 else
12748 {
1e1078d6
RS
12749 Lisp_Object eolvalue;
12750
12751 eolvalue = Fget (coding_system, Qeol_type);
12752
916848d8
RS
12753 if (multibyte)
12754 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
12755
1c9241f5
KH
12756 if (eol_flag)
12757 {
1e1078d6
RS
12758 /* The EOL conversion that is normal on this system. */
12759
12760 if (NILP (eolvalue)) /* Not yet decided. */
12761 eoltype = eol_mnemonic_undecided;
12762 else if (VECTORP (eolvalue)) /* Not yet decided. */
12763 eoltype = eol_mnemonic_undecided;
12764 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
12765 eoltype = (XFASTINT (eolvalue) == 0
12766 ? eol_mnemonic_unix
12767 : (XFASTINT (eolvalue) == 1
12768 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
12769 }
12770 }
5f5c8ee5 12771
302f2b38
EZ
12772 if (eol_flag)
12773 {
12774 /* Mention the EOL conversion if it is not the usual one. */
12775 if (STRINGP (eoltype))
12776 {
12777 eol_str = XSTRING (eoltype)->data;
12778 eol_str_len = XSTRING (eoltype)->size;
12779 }
f30b3499
KH
12780 else if (INTEGERP (eoltype)
12781 && CHAR_VALID_P (XINT (eoltype), 0))
12782 {
4a09dee0 12783 eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
260a86a0 12784 eol_str_len = CHAR_STRING (XINT (eoltype), eol_str);
f30b3499 12785 }
302f2b38
EZ
12786 else
12787 {
12788 eol_str = invalid_eol_type;
12789 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 12790 }
f30b3499 12791 bcopy (eol_str, buf, eol_str_len);
302f2b38 12792 buf += eol_str_len;
1c9241f5 12793 }
302f2b38 12794
1c9241f5
KH
12795 return buf;
12796}
12797
a2889657 12798/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
12799 generated by character C. PRECISION >= 0 means don't return a
12800 string longer than that value. FIELD_WIDTH > 0 means pad the
12801 string returned with spaces to that value. */
a2889657 12802
11e82b76
JB
12803static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
12804
a2889657 12805static char *
5f5c8ee5 12806decode_mode_spec (w, c, field_width, precision)
a2889657 12807 struct window *w;
68c45bf0 12808 register int c;
5f5c8ee5 12809 int field_width, precision;
a2889657 12810{
0b67772d 12811 Lisp_Object obj;
5f5c8ee5
GM
12812 struct frame *f = XFRAME (WINDOW_FRAME (w));
12813 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 12814 struct buffer *b = XBUFFER (w->buffer);
a2889657 12815
0b67772d 12816 obj = Qnil;
a2889657
JB
12817
12818 switch (c)
12819 {
1af9f229
RS
12820 case '*':
12821 if (!NILP (b->read_only))
12822 return "%";
12823 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12824 return "*";
12825 return "-";
12826
12827 case '+':
12828 /* This differs from %* only for a modified read-only buffer. */
12829 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12830 return "*";
12831 if (!NILP (b->read_only))
12832 return "%";
12833 return "-";
12834
12835 case '&':
12836 /* This differs from %* in ignoring read-only-ness. */
12837 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12838 return "*";
12839 return "-";
12840
12841 case '%':
12842 return "%";
12843
12844 case '[':
12845 {
12846 int i;
12847 char *p;
12848
12849 if (command_loop_level > 5)
12850 return "[[[... ";
12851 p = decode_mode_spec_buf;
12852 for (i = 0; i < command_loop_level; i++)
12853 *p++ = '[';
12854 *p = 0;
12855 return decode_mode_spec_buf;
12856 }
12857
12858 case ']':
12859 {
12860 int i;
12861 char *p;
12862
12863 if (command_loop_level > 5)
12864 return " ...]]]";
12865 p = decode_mode_spec_buf;
12866 for (i = 0; i < command_loop_level; i++)
12867 *p++ = ']';
12868 *p = 0;
12869 return decode_mode_spec_buf;
12870 }
12871
12872 case '-':
12873 {
1af9f229 12874 register int i;
5f5c8ee5
GM
12875
12876 /* Let lots_of_dashes be a string of infinite length. */
12877 if (field_width <= 0
12878 || field_width > sizeof (lots_of_dashes))
1af9f229 12879 {
5f5c8ee5
GM
12880 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
12881 decode_mode_spec_buf[i] = '-';
12882 decode_mode_spec_buf[i] = '\0';
12883 return decode_mode_spec_buf;
1af9f229 12884 }
5f5c8ee5
GM
12885 else
12886 return lots_of_dashes;
1af9f229
RS
12887 }
12888
a2889657 12889 case 'b':
d39b6696 12890 obj = b->name;
a2889657
JB
12891 break;
12892
1af9f229
RS
12893 case 'c':
12894 {
12895 int col = current_column ();
12896 XSETFASTINT (w->column_number_displayed, col);
5f5c8ee5 12897 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
12898 return decode_mode_spec_buf;
12899 }
12900
12901 case 'F':
12902 /* %F displays the frame name. */
5f5c8ee5 12903 if (!NILP (f->title))
95184b48 12904 return (char *) XSTRING (f->title)->data;
fd8ff63d 12905 if (f->explicit_name || ! FRAME_WINDOW_P (f))
95184b48 12906 return (char *) XSTRING (f->name)->data;
9c6da96f 12907 return "Emacs";
1af9f229 12908
a2889657 12909 case 'f':
d39b6696 12910 obj = b->filename;
a2889657
JB
12911 break;
12912
aa6d10fa
RS
12913 case 'l':
12914 {
12adba34
RS
12915 int startpos = XMARKER (w->start)->charpos;
12916 int startpos_byte = marker_byte_position (w->start);
12917 int line, linepos, linepos_byte, topline;
aa6d10fa 12918 int nlines, junk;
aa6d10fa
RS
12919 int height = XFASTINT (w->height);
12920
12921 /* If we decided that this buffer isn't suitable for line numbers,
12922 don't forget that too fast. */
12923 if (EQ (w->base_line_pos, w->buffer))
766525bc 12924 goto no_value;
5300fd39
RS
12925 /* But do forget it, if the window shows a different buffer now. */
12926 else if (BUFFERP (w->base_line_pos))
12927 w->base_line_pos = Qnil;
aa6d10fa
RS
12928
12929 /* If the buffer is very big, don't waste time. */
37d034d3 12930 if (INTEGERP (Vline_number_display_limit)
090703f4 12931 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
aa6d10fa
RS
12932 {
12933 w->base_line_pos = Qnil;
12934 w->base_line_number = Qnil;
766525bc 12935 goto no_value;
aa6d10fa
RS
12936 }
12937
12938 if (!NILP (w->base_line_number)
12939 && !NILP (w->base_line_pos)
12adba34 12940 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
12941 {
12942 line = XFASTINT (w->base_line_number);
12943 linepos = XFASTINT (w->base_line_pos);
12adba34 12944 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
12945 }
12946 else
12947 {
12948 line = 1;
d39b6696 12949 linepos = BUF_BEGV (b);
12adba34 12950 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
12951 }
12952
12953 /* Count lines from base line to window start position. */
12adba34
RS
12954 nlines = display_count_lines (linepos, linepos_byte,
12955 startpos_byte,
12956 startpos, &junk);
aa6d10fa
RS
12957
12958 topline = nlines + line;
12959
12960 /* Determine a new base line, if the old one is too close
12961 or too far away, or if we did not have one.
12962 "Too close" means it's plausible a scroll-down would
12963 go back past it. */
d39b6696 12964 if (startpos == BUF_BEGV (b))
aa6d10fa 12965 {
c2213350
KH
12966 XSETFASTINT (w->base_line_number, topline);
12967 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
12968 }
12969 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 12970 || linepos == BUF_BEGV (b))
aa6d10fa 12971 {
d39b6696 12972 int limit = BUF_BEGV (b);
12adba34 12973 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 12974 int position;
5d121aec 12975 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
12976
12977 if (startpos - distance > limit)
12adba34
RS
12978 {
12979 limit = startpos - distance;
12980 limit_byte = CHAR_TO_BYTE (limit);
12981 }
aa6d10fa 12982
12adba34
RS
12983 nlines = display_count_lines (startpos, startpos_byte,
12984 limit_byte,
12985 - (height * 2 + 30),
aa6d10fa
RS
12986 &position);
12987 /* If we couldn't find the lines we wanted within
5d121aec 12988 line_number_display_limit_width chars per line,
aa6d10fa 12989 give up on line numbers for this window. */
12adba34 12990 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
12991 {
12992 w->base_line_pos = w->buffer;
12993 w->base_line_number = Qnil;
766525bc 12994 goto no_value;
aa6d10fa
RS
12995 }
12996
c2213350 12997 XSETFASTINT (w->base_line_number, topline - nlines);
12adba34 12998 XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
aa6d10fa
RS
12999 }
13000
13001 /* Now count lines from the start pos to point. */
12adba34
RS
13002 nlines = display_count_lines (startpos, startpos_byte,
13003 PT_BYTE, PT, &junk);
aa6d10fa
RS
13004
13005 /* Record that we did display the line number. */
13006 line_number_displayed = 1;
13007
13008 /* Make the string to show. */
5f5c8ee5 13009 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 13010 return decode_mode_spec_buf;
766525bc
RS
13011 no_value:
13012 {
13013 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
13014 int pad = field_width - 2;
13015 while (pad-- > 0)
13016 *p++ = ' ';
13017 *p++ = '?';
b357b9d4
KR
13018 *p++ = '?';
13019 *p = '\0';
766525bc
RS
13020 return decode_mode_spec_buf;
13021 }
aa6d10fa
RS
13022 }
13023 break;
13024
a2889657 13025 case 'm':
d39b6696 13026 obj = b->mode_name;
a2889657
JB
13027 break;
13028
13029 case 'n':
d39b6696 13030 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
13031 return " Narrow";
13032 break;
13033
a2889657
JB
13034 case 'p':
13035 {
13036 int pos = marker_position (w->start);
d39b6696 13037 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 13038
d39b6696 13039 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 13040 {
d39b6696 13041 if (pos <= BUF_BEGV (b))
a2889657
JB
13042 return "All";
13043 else
13044 return "Bottom";
13045 }
d39b6696 13046 else if (pos <= BUF_BEGV (b))
a2889657
JB
13047 return "Top";
13048 else
13049 {
3c7d31b9
RS
13050 if (total > 1000000)
13051 /* Do it differently for a large value, to avoid overflow. */
13052 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
13053 else
13054 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
13055 /* We can't normally display a 3-digit number,
13056 so get us a 2-digit number that is close. */
13057 if (total == 100)
13058 total = 99;
13059 sprintf (decode_mode_spec_buf, "%2d%%", total);
13060 return decode_mode_spec_buf;
13061 }
13062 }
13063
8ffcb79f
RS
13064 /* Display percentage of size above the bottom of the screen. */
13065 case 'P':
13066 {
13067 int toppos = marker_position (w->start);
d39b6696
KH
13068 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
13069 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 13070
d39b6696 13071 if (botpos >= BUF_ZV (b))
8ffcb79f 13072 {
d39b6696 13073 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
13074 return "All";
13075 else
13076 return "Bottom";
13077 }
13078 else
13079 {
3c7d31b9
RS
13080 if (total > 1000000)
13081 /* Do it differently for a large value, to avoid overflow. */
13082 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
13083 else
13084 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
13085 /* We can't normally display a 3-digit number,
13086 so get us a 2-digit number that is close. */
13087 if (total == 100)
13088 total = 99;
d39b6696 13089 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
13090 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
13091 else
13092 sprintf (decode_mode_spec_buf, "%2d%%", total);
13093 return decode_mode_spec_buf;
13094 }
13095 }
13096
1af9f229
RS
13097 case 's':
13098 /* status of process */
13099 obj = Fget_buffer_process (w->buffer);
13100 if (NILP (obj))
13101 return "no process";
13102#ifdef subprocesses
13103 obj = Fsymbol_name (Fprocess_status (obj));
13104#endif
13105 break;
d39b6696 13106
1af9f229
RS
13107 case 't': /* indicate TEXT or BINARY */
13108#ifdef MODE_LINE_BINARY_TEXT
13109 return MODE_LINE_BINARY_TEXT (b);
13110#else
13111 return "T";
13112#endif
1c9241f5
KH
13113
13114 case 'z':
13115 /* coding-system (not including end-of-line format) */
13116 case 'Z':
13117 /* coding-system (including end-of-line type) */
13118 {
13119 int eol_flag = (c == 'Z');
539b4d41 13120 char *p = decode_mode_spec_buf;
1c9241f5 13121
d30e754b 13122 if (! FRAME_WINDOW_P (f))
1c9241f5 13123 {
11c52c4f
RS
13124 /* No need to mention EOL here--the terminal never needs
13125 to do EOL conversion. */
13126 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
13127 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 13128 }
f13c925f 13129 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 13130 p, eol_flag);
f13c925f 13131
11c52c4f 13132#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
13133#ifdef subprocesses
13134 obj = Fget_buffer_process (Fcurrent_buffer ());
13135 if (PROCESSP (obj))
13136 {
13137 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
13138 p, eol_flag);
13139 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
13140 p, eol_flag);
13141 }
13142#endif /* subprocesses */
11c52c4f 13143#endif /* 0 */
1c9241f5
KH
13144 *p = 0;
13145 return decode_mode_spec_buf;
13146 }
a2889657 13147 }
d39b6696 13148
e24c997d 13149 if (STRINGP (obj))
a2889657
JB
13150 return (char *) XSTRING (obj)->data;
13151 else
13152 return "";
13153}
5f5c8ee5
GM
13154
13155
12adba34
RS
13156/* Count up to COUNT lines starting from START / START_BYTE.
13157 But don't go beyond LIMIT_BYTE.
13158 Return the number of lines thus found (always nonnegative).
59b49f63 13159
12adba34 13160 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
13161
13162static int
12adba34
RS
13163display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
13164 int start, start_byte, limit_byte, count;
13165 int *byte_pos_ptr;
59b49f63 13166{
59b49f63
RS
13167 register unsigned char *cursor;
13168 unsigned char *base;
13169
13170 register int ceiling;
13171 register unsigned char *ceiling_addr;
12adba34 13172 int orig_count = count;
59b49f63
RS
13173
13174 /* If we are not in selective display mode,
13175 check only for newlines. */
12adba34
RS
13176 int selective_display = (!NILP (current_buffer->selective_display)
13177 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
13178
13179 if (count > 0)
12adba34
RS
13180 {
13181 while (start_byte < limit_byte)
13182 {
13183 ceiling = BUFFER_CEILING_OF (start_byte);
13184 ceiling = min (limit_byte - 1, ceiling);
13185 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
13186 base = (cursor = BYTE_POS_ADDR (start_byte));
13187 while (1)
13188 {
13189 if (selective_display)
13190 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
13191 ;
13192 else
13193 while (*cursor != '\n' && ++cursor != ceiling_addr)
13194 ;
13195
13196 if (cursor != ceiling_addr)
13197 {
13198 if (--count == 0)
13199 {
13200 start_byte += cursor - base + 1;
13201 *byte_pos_ptr = start_byte;
13202 return orig_count;
13203 }
13204 else
13205 if (++cursor == ceiling_addr)
13206 break;
13207 }
13208 else
13209 break;
13210 }
13211 start_byte += cursor - base;
13212 }
13213 }
59b49f63
RS
13214 else
13215 {
12adba34
RS
13216 while (start_byte > limit_byte)
13217 {
13218 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
13219 ceiling = max (limit_byte, ceiling);
13220 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
13221 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
13222 while (1)
13223 {
12adba34
RS
13224 if (selective_display)
13225 while (--cursor != ceiling_addr
13226 && *cursor != '\n' && *cursor != 015)
13227 ;
13228 else
13229 while (--cursor != ceiling_addr && *cursor != '\n')
13230 ;
13231
59b49f63
RS
13232 if (cursor != ceiling_addr)
13233 {
13234 if (++count == 0)
13235 {
12adba34
RS
13236 start_byte += cursor - base + 1;
13237 *byte_pos_ptr = start_byte;
13238 /* When scanning backwards, we should
13239 not count the newline posterior to which we stop. */
13240 return - orig_count - 1;
59b49f63
RS
13241 }
13242 }
13243 else
13244 break;
13245 }
12adba34
RS
13246 /* Here we add 1 to compensate for the last decrement
13247 of CURSOR, which took it past the valid range. */
13248 start_byte += cursor - base + 1;
59b49f63
RS
13249 }
13250 }
13251
12adba34 13252 *byte_pos_ptr = limit_byte;
aa6d10fa 13253
12adba34
RS
13254 if (count < 0)
13255 return - orig_count + count;
13256 return orig_count - count;
aa6d10fa 13257
12adba34 13258}
a2889657 13259
a2889657 13260
5f5c8ee5
GM
13261\f
13262/***********************************************************************
13263 Displaying strings
13264 ***********************************************************************/
278feba9 13265
5f5c8ee5 13266/* Display a NUL-terminated string, starting with index START.
a3788d53 13267
5f5c8ee5
GM
13268 If STRING is non-null, display that C string. Otherwise, the Lisp
13269 string LISP_STRING is displayed.
a2889657 13270
5f5c8ee5
GM
13271 If FACE_STRING is not nil, FACE_STRING_POS is a position in
13272 FACE_STRING. Display STRING or LISP_STRING with the face at
13273 FACE_STRING_POS in FACE_STRING:
a2889657 13274
5f5c8ee5
GM
13275 Display the string in the environment given by IT, but use the
13276 standard display table, temporarily.
a3788d53 13277
5f5c8ee5
GM
13278 FIELD_WIDTH is the minimum number of output glyphs to produce.
13279 If STRING has fewer characters than FIELD_WIDTH, pad to the right
13280 with spaces. If STRING has more characters, more than FIELD_WIDTH
13281 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
13282
13283 PRECISION is the maximum number of characters to output from
13284 STRING. PRECISION < 0 means don't truncate the string.
a2889657 13285
5f5c8ee5 13286 This is roughly equivalent to printf format specifiers:
a2889657 13287
5f5c8ee5
GM
13288 FIELD_WIDTH PRECISION PRINTF
13289 ----------------------------------------
13290 -1 -1 %s
13291 -1 10 %.10s
13292 10 -1 %10s
13293 20 10 %20.10s
a2889657 13294
5f5c8ee5
GM
13295 MULTIBYTE zero means do not display multibyte chars, > 0 means do
13296 display them, and < 0 means obey the current buffer's value of
13297 enable_multibyte_characters.
278feba9 13298
5f5c8ee5 13299 Value is the number of glyphs produced. */
b1d1124b 13300
5f5c8ee5
GM
13301static int
13302display_string (string, lisp_string, face_string, face_string_pos,
13303 start, it, field_width, precision, max_x, multibyte)
13304 unsigned char *string;
13305 Lisp_Object lisp_string;
68c45bf0
PE
13306 Lisp_Object face_string;
13307 int face_string_pos;
5f5c8ee5
GM
13308 int start;
13309 struct it *it;
13310 int field_width, precision, max_x;
13311 int multibyte;
13312{
13313 int hpos_at_start = it->hpos;
13314 int saved_face_id = it->face_id;
13315 struct glyph_row *row = it->glyph_row;
13316
13317 /* Initialize the iterator IT for iteration over STRING beginning
13318 with index START. We assume that IT may be modified here (which
13319 means that display_line has to do something when displaying a
13320 mini-buffer prompt, which it does). */
13321 reseat_to_string (it, string, lisp_string, start,
13322 precision, field_width, multibyte);
13323
13324 /* If displaying STRING, set up the face of the iterator
13325 from LISP_STRING, if that's given. */
13326 if (STRINGP (face_string))
13327 {
13328 int endptr;
13329 struct face *face;
13330
13331 it->face_id
13332 = face_at_string_position (it->w, face_string, face_string_pos,
13333 0, it->region_beg_charpos,
13334 it->region_end_charpos,
13335 &endptr, it->base_face_id);
13336 face = FACE_FROM_ID (it->f, it->face_id);
13337 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 13338 }
a2889657 13339
5f5c8ee5
GM
13340 /* Set max_x to the maximum allowed X position. Don't let it go
13341 beyond the right edge of the window. */
13342 if (max_x <= 0)
13343 max_x = it->last_visible_x;
13344 else
13345 max_x = min (max_x, it->last_visible_x);
efc63ef0 13346
5f5c8ee5
GM
13347 /* Skip over display elements that are not visible. because IT->w is
13348 hscrolled. */
13349 if (it->current_x < it->first_visible_x)
13350 move_it_in_display_line_to (it, 100000, it->first_visible_x,
13351 MOVE_TO_POS | MOVE_TO_X);
a2889657 13352
5f5c8ee5
GM
13353 row->ascent = it->max_ascent;
13354 row->height = it->max_ascent + it->max_descent;
312246d1
GM
13355 row->phys_ascent = it->max_phys_ascent;
13356 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 13357
5f5c8ee5
GM
13358 /* This condition is for the case that we are called with current_x
13359 past last_visible_x. */
13360 while (it->current_x < max_x)
a2889657 13361 {
5f5c8ee5 13362 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 13363
5f5c8ee5
GM
13364 /* Get the next display element. */
13365 if (!get_next_display_element (it))
90adcf20 13366 break;
1c9241f5 13367
5f5c8ee5
GM
13368 /* Produce glyphs. */
13369 x_before = it->current_x;
13370 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
13371 PRODUCE_GLYPHS (it);
90adcf20 13372
5f5c8ee5
GM
13373 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
13374 i = 0;
13375 x = x_before;
13376 while (i < nglyphs)
a2889657 13377 {
5f5c8ee5
GM
13378 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
13379
13380 if (!it->truncate_lines_p
13381 && x + glyph->pixel_width > max_x)
13382 {
13383 /* End of continued line or max_x reached. */
13384 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
13385 it->current_x = x;
13386 break;
13387 }
13388 else if (x + glyph->pixel_width > it->first_visible_x)
13389 {
13390 /* Glyph is at least partially visible. */
13391 ++it->hpos;
13392 if (x < it->first_visible_x)
13393 it->glyph_row->x = x - it->first_visible_x;
13394 }
13395 else
a2889657 13396 {
5f5c8ee5
GM
13397 /* Glyph is off the left margin of the display area.
13398 Should not happen. */
13399 abort ();
a2889657 13400 }
5f5c8ee5
GM
13401
13402 row->ascent = max (row->ascent, it->max_ascent);
13403 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
13404 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
13405 row->phys_height = max (row->phys_height,
13406 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
13407 x += glyph->pixel_width;
13408 ++i;
a2889657 13409 }
5f5c8ee5
GM
13410
13411 /* Stop if max_x reached. */
13412 if (i < nglyphs)
13413 break;
13414
13415 /* Stop at line ends. */
13416 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 13417 {
5f5c8ee5
GM
13418 it->continuation_lines_width = 0;
13419 break;
a2889657 13420 }
1c9241f5 13421
cafafe0b 13422 set_iterator_to_next (it, 1);
a688bb24 13423
5f5c8ee5
GM
13424 /* Stop if truncating at the right edge. */
13425 if (it->truncate_lines_p
13426 && it->current_x >= it->last_visible_x)
13427 {
13428 /* Add truncation mark, but don't do it if the line is
13429 truncated at a padding space. */
13430 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 13431 {
5f5c8ee5
GM
13432 if (!FRAME_WINDOW_P (it->f))
13433 produce_special_glyphs (it, IT_TRUNCATION);
13434 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 13435 }
5f5c8ee5 13436 break;
1c9241f5 13437 }
a2889657
JB
13438 }
13439
5f5c8ee5
GM
13440 /* Maybe insert a truncation at the left. */
13441 if (it->first_visible_x
13442 && IT_CHARPOS (*it) > 0)
a2889657 13443 {
5f5c8ee5
GM
13444 if (!FRAME_WINDOW_P (it->f))
13445 insert_left_trunc_glyphs (it);
13446 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
13447 }
13448
5f5c8ee5
GM
13449 it->face_id = saved_face_id;
13450
13451 /* Value is number of columns displayed. */
13452 return it->hpos - hpos_at_start;
13453}
a2889657 13454
a2889657 13455
a2889657 13456\f
5f5c8ee5
GM
13457/* This is like a combination of memq and assq. Return 1 if PROPVAL
13458 appears as an element of LIST or as the car of an element of LIST.
13459 If PROPVAL is a list, compare each element against LIST in that
13460 way, and return 1 if any element of PROPVAL is found in LIST.
13461 Otherwise return 0. This function cannot quit. */
642eefc6
RS
13462
13463int
13464invisible_p (propval, list)
13465 register Lisp_Object propval;
13466 Lisp_Object list;
13467{
af460d46 13468 register Lisp_Object tail, proptail;
715e84c9 13469
9472f927 13470 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
13471 {
13472 register Lisp_Object tem;
9472f927 13473 tem = XCAR (tail);
642eefc6
RS
13474 if (EQ (propval, tem))
13475 return 1;
9472f927 13476 if (CONSP (tem) && EQ (propval, XCAR (tem)))
642eefc6
RS
13477 return 1;
13478 }
715e84c9 13479
af460d46 13480 if (CONSP (propval))
715e84c9
GM
13481 {
13482 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
13483 {
13484 Lisp_Object propelt;
13485 propelt = XCAR (proptail);
13486 for (tail = list; CONSP (tail); tail = XCDR (tail))
13487 {
13488 register Lisp_Object tem;
13489 tem = XCAR (tail);
13490 if (EQ (propelt, tem))
13491 return 1;
13492 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
13493 return 1;
13494 }
13495 }
13496 }
13497
642eefc6
RS
13498 return 0;
13499}
13500
5f5c8ee5
GM
13501
13502/* Return 1 if PROPVAL appears as the car of an element of LIST and
13503 the cdr of that element is non-nil. If PROPVAL is a list, check
13504 each element of PROPVAL in that way, and the first time some
13505 element is found, return 1 if the cdr of that element is non-nil.
13506 Otherwise return 0. This function cannot quit. */
642eefc6
RS
13507
13508int
13509invisible_ellipsis_p (propval, list)
13510 register Lisp_Object propval;
13511 Lisp_Object list;
13512{
af460d46 13513 register Lisp_Object tail, proptail;
9472f927
GM
13514
13515 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
13516 {
13517 register Lisp_Object tem;
9472f927
GM
13518 tem = XCAR (tail);
13519 if (CONSP (tem) && EQ (propval, XCAR (tem)))
13520 return ! NILP (XCDR (tem));
642eefc6 13521 }
9472f927 13522
af460d46 13523 if (CONSP (propval))
9472f927 13524 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
af460d46
RS
13525 {
13526 Lisp_Object propelt;
9472f927
GM
13527 propelt = XCAR (proptail);
13528 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
13529 {
13530 register Lisp_Object tem;
9472f927
GM
13531 tem = XCAR (tail);
13532 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
13533 return ! NILP (XCDR (tem));
af460d46
RS
13534 }
13535 }
9472f927 13536
642eefc6
RS
13537 return 0;
13538}
5f5c8ee5
GM
13539
13540
642eefc6 13541\f
5f5c8ee5
GM
13542/***********************************************************************
13543 Initialization
13544 ***********************************************************************/
13545
a2889657
JB
13546void
13547syms_of_xdisp ()
13548{
c6e89d6c
GM
13549 Vwith_echo_area_save_vector = Qnil;
13550 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 13551
c6e89d6c
GM
13552 Vmessage_stack = Qnil;
13553 staticpro (&Vmessage_stack);
13554
735c094c 13555 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 13556 staticpro (&Qinhibit_redisplay);
735c094c 13557
5f5c8ee5
GM
13558#if GLYPH_DEBUG
13559 defsubr (&Sdump_glyph_matrix);
13560 defsubr (&Sdump_glyph_row);
e037b9ec 13561 defsubr (&Sdump_tool_bar_row);
5f5c8ee5 13562 defsubr (&Strace_redisplay_toggle);
bf9249e3 13563 defsubr (&Strace_to_stderr);
5f5c8ee5
GM
13564#endif
13565
cf074754
RS
13566 staticpro (&Qmenu_bar_update_hook);
13567 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
13568
d46fb96a 13569 staticpro (&Qoverriding_terminal_local_map);
7079aefa 13570 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 13571
399164b4
KH
13572 staticpro (&Qoverriding_local_map);
13573 Qoverriding_local_map = intern ("overriding-local-map");
13574
75c43375
RS
13575 staticpro (&Qwindow_scroll_functions);
13576 Qwindow_scroll_functions = intern ("window-scroll-functions");
13577
e0bfbde6
RS
13578 staticpro (&Qredisplay_end_trigger_functions);
13579 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
5f5c8ee5 13580
2e54982e
RS
13581 staticpro (&Qinhibit_point_motion_hooks);
13582 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
13583
9499d71b
GM
13584 QCdata = intern (":data");
13585 staticpro (&QCdata);
5f5c8ee5 13586 Qdisplay = intern ("display");
f3751a65 13587 staticpro (&Qdisplay);
5f5c8ee5
GM
13588 Qspace_width = intern ("space-width");
13589 staticpro (&Qspace_width);
5f5c8ee5
GM
13590 Qraise = intern ("raise");
13591 staticpro (&Qraise);
13592 Qspace = intern ("space");
13593 staticpro (&Qspace);
f3751a65
GM
13594 Qmargin = intern ("margin");
13595 staticpro (&Qmargin);
5f5c8ee5 13596 Qleft_margin = intern ("left-margin");
f3751a65 13597 staticpro (&Qleft_margin);
5f5c8ee5 13598 Qright_margin = intern ("right-margin");
f3751a65 13599 staticpro (&Qright_margin);
5f5c8ee5
GM
13600 Qalign_to = intern ("align-to");
13601 staticpro (&Qalign_to);
13602 QCalign_to = intern (":align-to");
13603 staticpro (&QCalign_to);
5f5c8ee5
GM
13604 Qrelative_width = intern ("relative-width");
13605 staticpro (&Qrelative_width);
13606 QCrelative_width = intern (":relative-width");
13607 staticpro (&QCrelative_width);
13608 QCrelative_height = intern (":relative-height");
13609 staticpro (&QCrelative_height);
13610 QCeval = intern (":eval");
13611 staticpro (&QCeval);
d3acf96b 13612 Qwhen = intern ("when");
f3751a65 13613 staticpro (&Qwhen);
886bd6f2
GM
13614 QCfile = intern (":file");
13615 staticpro (&QCfile);
5f5c8ee5
GM
13616 Qfontified = intern ("fontified");
13617 staticpro (&Qfontified);
13618 Qfontification_functions = intern ("fontification-functions");
13619 staticpro (&Qfontification_functions);
5f5c8ee5
GM
13620 Qtrailing_whitespace = intern ("trailing-whitespace");
13621 staticpro (&Qtrailing_whitespace);
13622 Qimage = intern ("image");
13623 staticpro (&Qimage);
ad4f174e
GM
13624 Qmessage_truncate_lines = intern ("message-truncate-lines");
13625 staticpro (&Qmessage_truncate_lines);
5f5c8ee5 13626
a2889657
JB
13627 last_arrow_position = Qnil;
13628 last_arrow_string = Qnil;
f3751a65
GM
13629 staticpro (&last_arrow_position);
13630 staticpro (&last_arrow_string);
c6e89d6c
GM
13631
13632 echo_buffer[0] = echo_buffer[1] = Qnil;
13633 staticpro (&echo_buffer[0]);
13634 staticpro (&echo_buffer[1]);
13635
13636 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
13637 staticpro (&echo_area_buffer[0]);
13638 staticpro (&echo_area_buffer[1]);
a2889657 13639
6a94510a
GM
13640 Vmessages_buffer_name = build_string ("*Messages*");
13641 staticpro (&Vmessages_buffer_name);
13642
8f897821
GM
13643 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
13644 "Non-nil means highlight trailing whitespace.\n\
13645The face used for trailing whitespace is `trailing-whitespace'.");
13646 Vshow_trailing_whitespace = Qnil;
13647
735c094c
KH
13648 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
13649 "Non-nil means don't actually do any redisplay.\n\
13650This is used for internal purposes.");
13651 Vinhibit_redisplay = Qnil;
13652
a2889657 13653 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 13654 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
13655 Vglobal_mode_string = Qnil;
13656
13657 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
13658 "Marker for where to display an arrow on top of the buffer text.\n\
13659This must be the beginning of a line in order to work.\n\
13660See also `overlay-arrow-string'.");
13661 Voverlay_arrow_position = Qnil;
13662
13663 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
13664 "String to display as an arrow. See also `overlay-arrow-position'.");
13665 Voverlay_arrow_string = Qnil;
13666
13667 DEFVAR_INT ("scroll-step", &scroll_step,
13668 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
13669If that fails to bring point back on frame, point is centered instead.\n\
13670If this is zero, point is always centered after it moves off frame.");
a2889657 13671
0789adb2 13672 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
090f7baa
GM
13673 "*Scroll up to this many lines, to bring point back on screen.\n\
13674A value of zero means to scroll the text to center point vertically\n\
13675in the window.");
0789adb2
RS
13676 scroll_conservatively = 0;
13677
9afd2168
RS
13678 DEFVAR_INT ("scroll-margin", &scroll_margin,
13679 "*Number of lines of margin at the top and bottom of a window.\n\
13680Recenter the window whenever point gets within this many lines\n\
13681of the top or bottom of the window.");
13682 scroll_margin = 0;
13683
5f5c8ee5 13684#if GLYPH_DEBUG
a2889657 13685 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
5f5c8ee5 13686#endif
a2889657
JB
13687
13688 DEFVAR_BOOL ("truncate-partial-width-windows",
13689 &truncate_partial_width_windows,
44fa5b1e 13690 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
13691 truncate_partial_width_windows = 1;
13692
13693 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
13694 "*Non-nil means use inverse video for the mode line.");
13695 mode_line_inverse_video = 1;
aa6d10fa 13696
090703f4 13697 DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
5f5c8ee5 13698 "*Maximum buffer size for which line number should be displayed.\n\
db4f2bfa 13699If the buffer is bigger than this, the line number does not appear\n\
090703f4
GM
13700in the mode line. A value of nil means no limit.");
13701 Vline_number_display_limit = Qnil;
fba9ce76 13702
090703f4
GM
13703 DEFVAR_INT ("line-number-display-limit-width",
13704 &line_number_display_limit_width,
5d121aec
KH
13705 "*Maximum line width (in characters) for line number display.\n\
13706If the average length of the lines near point is bigger than this, then the\n\
13707line number may be omitted from the mode line.");
13708 line_number_display_limit_width = 200;
13709
fba9ce76
RS
13710 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
13711 "*Non-nil means highlight region even in nonselected windows.");
293a54ce 13712 highlight_nonselected_windows = 0;
d39b6696
KH
13713
13714 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
13715 "Non-nil if more than one frame is visible on this display.\n\
13716Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
13717This variable is not guaranteed to be accurate except while processing\n\
13718`frame-title-format' and `icon-title-format'.");
d39b6696
KH
13719
13720 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
5f5c8ee5 13721 "Template for displaying the title bar of visible frames.\n\
d39b6696
KH
13722\(Assuming the window manager supports this feature.)\n\
13723This variable has the same structure as `mode-line-format' (which see),\n\
13724and is used only on frames for which no explicit name has been set\n\
13725\(see `modify-frame-parameters').");
13726 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
5f5c8ee5 13727 "Template for displaying the title bar of an iconified frame.\n\
d39b6696
KH
13728\(Assuming the window manager supports this feature.)\n\
13729This variable has the same structure as `mode-line-format' (which see),\n\
13730and is used only on frames for which no explicit name has been set\n\
13731\(see `modify-frame-parameters').");
13732 Vicon_title_format
13733 = Vframe_title_format
13734 = Fcons (intern ("multiple-frames"),
13735 Fcons (build_string ("%b"),
13736 Fcons (Fcons (build_string (""),
13737 Fcons (intern ("invocation-name"),
13738 Fcons (build_string ("@"),
13739 Fcons (intern ("system-name"),
13740 Qnil)))),
13741 Qnil)));
5992c4f7
KH
13742
13743 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
13744 "Maximum number of lines to keep in the message log buffer.\n\
13745If nil, disable message logging. If t, log messages but don't truncate\n\
13746the buffer when it becomes large.");
13747 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
13748
13749 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
13750 "Functions called before redisplay, if window sizes have changed.\n\
13751The value should be a list of functions that take one argument.\n\
13752Just before redisplay, for each frame, if any of its windows have changed\n\
13753size since the last redisplay, or have been split or deleted,\n\
13754all the functions in the list are called, with the frame as argument.");
13755 Vwindow_size_change_functions = Qnil;
75c43375
RS
13756
13757 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
5f5c8ee5 13758 "List of Functions to call before redisplaying a window with scrolling.\n\
75c43375 13759Each function is called with two arguments, the window\n\
8d9583b0
RS
13760and its new display-start position. Note that the value of `window-end'\n\
13761is not valid when these functions are called.");
75c43375 13762 Vwindow_scroll_functions = Qnil;
5f5c8ee5 13763
e037b9ec
GM
13764 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
13765 "*Non-nil means automatically resize tool-bars.\n\
13766This increases a tool-bar's height if not all tool-bar items are visible.\n\
13767It decreases a tool-bar's height when it would display blank lines\n\
5f5c8ee5 13768otherwise.");
e037b9ec 13769 auto_resize_tool_bars_p = 1;
5f5c8ee5 13770
e037b9ec
GM
13771 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
13772 "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
13773 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 13774
e037b9ec
GM
13775 DEFVAR_INT ("tool-bar-button-margin", &tool_bar_button_margin,
13776 "*Margin around tool-bar buttons in pixels.");
13777 tool_bar_button_margin = 1;
5f5c8ee5 13778
e037b9ec
GM
13779 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
13780 "Relief thickness of tool-bar buttons.");
13781 tool_bar_button_relief = 3;
5f5c8ee5
GM
13782
13783 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
13784 "List of functions to call to fontify regions of text.\n\
13785Each function is called with one argument POS. Functions must\n\
13786fontify a region starting at POS in the current buffer, and give\n\
13787fontified regions the property `fontified'.\n\
13788This variable automatically becomes buffer-local when set.");
13789 Vfontification_functions = Qnil;
13790 Fmake_local_variable (Qfontification_functions);
7bbe686f
AI
13791
13792 DEFVAR_BOOL ("unibyte-display-via-language-environment",
5f5c8ee5
GM
13793 &unibyte_display_via_language_environment,
13794 "*Non-nil means display unibyte text according to language environment.\n\
7bbe686f
AI
13795Specifically this means that unibyte non-ASCII characters\n\
13796are displayed by converting them to the equivalent multibyte characters\n\
13797according to the current language environment. As a result, they are\n\
13798displayed according to the current fontset.");
13799 unibyte_display_via_language_environment = 0;
c6e89d6c
GM
13800
13801 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
13802 "*Maximum height for resizing mini-windows.\n\
13803If a float, it specifies a fraction of the mini-window frame's height.\n\
97cafc0f
GM
13804If an integer, it specifies a number of lines.\n\
13805If nil, don't resize.");
c6e89d6c 13806 Vmax_mini_window_height = make_float (0.25);
d6d26ed3
GM
13807
13808 DEFVAR_BOOL ("cursor-in-non-selected-windows",
13809 &cursor_in_non_selected_windows,
13810 "*Non-nil means display a hollow cursor in non-selected windows.\n\
13811Nil means don't display a cursor there.");
13812 cursor_in_non_selected_windows = 1;
d475bcb8
GM
13813
13814 DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p,
13815 "*Non-nil means scroll the display automatically to make point visible.");
13816 automatic_hscrolling_p = 1;
e00daaa0
GM
13817
13818 DEFVAR_LISP ("image-types", &Vimage_types,
ad4f174e 13819 "List of supported image types.\n\
e00daaa0
GM
13820Each element of the list is a symbol for a supported image type.");
13821 Vimage_types = Qnil;
ad4f174e
GM
13822
13823 DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
13824 "If non-nil, messages are truncated instead of resizing the echo area.\n\
13825Bind this around calls to `message' to let it take effect.");
13826 message_truncate_lines = 0;
0bca8940
DL
13827
13828 DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
13829 "Normal hook run for clicks on menu bar, before displaying a submenu.\n\
13830Can be used to update submenus whose contents should vary.");
13831
a2889657
JB
13832}
13833
5f5c8ee5
GM
13834
13835/* Initialize this module when Emacs starts. */
13836
dfcf069d 13837void
a2889657
JB
13838init_xdisp ()
13839{
13840 Lisp_Object root_window;
5f5c8ee5 13841 struct window *mini_w;
a2889657 13842
5f5c8ee5 13843 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
13844
13845 mini_w = XWINDOW (minibuf_window);
11e82b76 13846 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 13847
a2889657
JB
13848 if (!noninteractive)
13849 {
5f5c8ee5
GM
13850 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
13851 int i;
13852
13853 XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f));
12c226c5 13854 set_window_height (root_window,
5f5c8ee5 13855 FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 13856 0);
c2213350 13857 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
13858 set_window_height (minibuf_window, 1, 0);
13859
c2213350
KH
13860 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
13861 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
5f5c8ee5
GM
13862
13863 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
13864 scratch_glyph_row.glyphs[TEXT_AREA + 1]
13865 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
13866
13867 /* The default ellipsis glyphs `...'. */
13868 for (i = 0; i < 3; ++i)
13869 XSETFASTINT (default_invis_vector[i], '.');
a2889657 13870 }
5f5c8ee5
GM
13871
13872#ifdef HAVE_WINDOW_SYSTEM
13873 {
13874 /* Allocate the buffer for frame titles. */
13875 int size = 100;
13876 frame_title_buf = (char *) xmalloc (size);
13877 frame_title_buf_end = frame_title_buf + size;
13878 frame_title_ptr = NULL;
13879 }
13880#endif /* HAVE_WINDOW_SYSTEM */
21fdfb65
GM
13881
13882 help_echo_showing_p = 0;
a2889657 13883}
5f5c8ee5
GM
13884
13885