*** empty log message ***
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
5f5c8ee5
GM
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 99
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"
44fa5b1e 173#include "frame.h"
a2889657
JB
174#include "window.h"
175#include "termchar.h"
176#include "dispextern.h"
177#include "buffer.h"
1c9241f5 178#include "charset.h"
a2889657
JB
179#include "indent.h"
180#include "commands.h"
181#include "macros.h"
182#include "disptab.h"
30c566e4 183#include "termhooks.h"
b0a0fbda 184#include "intervals.h"
fe8b0cf8 185#include "keyboard.h"
1c9241f5
KH
186#include "coding.h"
187#include "process.h"
dfcf069d
AS
188#include "region-cache.h"
189
6d55d620 190#ifdef HAVE_X_WINDOWS
dfcf069d
AS
191#include "xterm.h"
192#endif
a75dfea0
AI
193#ifdef WINDOWSNT
194#include "w32term.h"
195#endif
a2889657 196
5f5c8ee5
GM
197#define min(a, b) ((a) < (b) ? (a) : (b))
198#define max(a, b) ((a) > (b) ? (a) : (b))
199
200#define INFINITY 10000000
201
8f3343d0 202#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
76412d64 203extern void set_frame_menubar ();
cd6dfed6 204extern int pending_menu_activation;
76412d64
RS
205#endif
206
a2889657
JB
207extern int interrupt_input;
208extern int command_loop_level;
209
b6436d4e
RS
210extern int minibuffer_auto_raise;
211
c4628384
RS
212extern Lisp_Object Qface;
213
399164b4
KH
214extern Lisp_Object Voverriding_local_map;
215extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 216extern Lisp_Object Qmenu_item;
399164b4 217
d46fb96a 218Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 219Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 220Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 221Lisp_Object Qinhibit_point_motion_hooks;
886bd6f2 222Lisp_Object QCeval, Qwhen, QCfile;
5f5c8ee5
GM
223Lisp_Object Qfontified;
224
225/* Functions called to fontify regions of text. */
226
227Lisp_Object Vfontification_functions;
228Lisp_Object Qfontification_functions;
229
e037b9ec 230/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
231 over them. */
232
e037b9ec 233int auto_raise_tool_bar_buttons_p;
5f5c8ee5 234
e037b9ec 235/* Margin around tool bar buttons in pixels. */
5f5c8ee5 236
e037b9ec 237int tool_bar_button_margin;
5f5c8ee5 238
e037b9ec 239/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 240
e037b9ec 241int tool_bar_button_relief;
5f5c8ee5 242
e037b9ec 243/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
244 items are visible, and no blank lines remain. */
245
e037b9ec 246int auto_resize_tool_bars_p;
399164b4 247
735c094c
KH
248/* Non-nil means don't actually do any redisplay. */
249
250Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
251
5f5c8ee5
GM
252/* Names of text properties relevant for redisplay. */
253
a7e27ef7
DL
254Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
255extern Lisp_Object Qface, Qinvisible, Qimage, Qwidth;
5f5c8ee5
GM
256
257/* Symbols used in text property values. */
258
259Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
a7e27ef7 260Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
f3751a65 261Lisp_Object Qmargin;
a7e27ef7 262extern Lisp_Object Qheight;
5f5c8ee5 263
8f897821 264/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 265
8f897821 266Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5
GM
267
268/* Name of the face used to highlight trailing whitespace. */
269
270Lisp_Object Qtrailing_whitespace;
271
272/* The symbol `image' which is the car of the lists used to represent
273 images in Lisp. */
274
275Lisp_Object Qimage;
276
277/* Non-zero means print newline to stdout before next mini-buffer
278 message. */
a2889657
JB
279
280int noninteractive_need_newline;
281
5f5c8ee5 282/* Non-zero means print newline to message log before next message. */
f88eb0b6 283
3c6595e0 284static int message_log_need_newline;
f88eb0b6 285
5f5c8ee5
GM
286\f
287/* The buffer position of the first character appearing entirely or
288 partially on the line of the selected window which contains the
289 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
290 redisplay optimization in redisplay_internal. */
a2889657 291
5f5c8ee5 292static struct text_pos this_line_start_pos;
a2889657 293
5f5c8ee5
GM
294/* Number of characters past the end of the line above, including the
295 terminating newline. */
296
297static struct text_pos this_line_end_pos;
298
299/* The vertical positions and the height of this line. */
a2889657 300
a2889657 301static int this_line_vpos;
5f5c8ee5
GM
302static int this_line_y;
303static int this_line_pixel_height;
304
305/* X position at which this display line starts. Usually zero;
306 negative if first character is partially visible. */
307
308static int this_line_start_x;
a2889657 309
5f5c8ee5 310/* Buffer that this_line_.* variables are referring to. */
a2889657 311
a2889657
JB
312static struct buffer *this_line_buffer;
313
5f5c8ee5
GM
314/* Nonzero means truncate lines in all windows less wide than the
315 frame. */
a2889657 316
a2889657
JB
317int truncate_partial_width_windows;
318
7bbe686f 319/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 320
7bbe686f 321int unibyte_display_via_language_environment;
5f5c8ee5
GM
322
323/* Nonzero means we have more than one non-mini-buffer-only frame.
324 Not guaranteed to be accurate except while parsing
325 frame-title-format. */
7bbe686f 326
d39b6696
KH
327int multiple_frames;
328
a2889657
JB
329Lisp_Object Vglobal_mode_string;
330
331/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 332
a2889657
JB
333Lisp_Object Voverlay_arrow_position;
334
5f5c8ee5
GM
335/* String to display for the arrow. Only used on terminal frames. */
336
a2889657
JB
337Lisp_Object Voverlay_arrow_string;
338
5f5c8ee5
GM
339/* Values of those variables at last redisplay. However, if
340 Voverlay_arrow_position is a marker, last_arrow_position is its
341 numerical position. */
342
d45de95b
RS
343static Lisp_Object last_arrow_position, last_arrow_string;
344
5f5c8ee5
GM
345/* Like mode-line-format, but for the title bar on a visible frame. */
346
d39b6696
KH
347Lisp_Object Vframe_title_format;
348
5f5c8ee5
GM
349/* Like mode-line-format, but for the title bar on an iconified frame. */
350
d39b6696
KH
351Lisp_Object Vicon_title_format;
352
08b610e4
RS
353/* List of functions to call when a window's size changes. These
354 functions get one arg, a frame on which one or more windows' sizes
355 have changed. */
5f5c8ee5 356
08b610e4
RS
357static Lisp_Object Vwindow_size_change_functions;
358
cf074754
RS
359Lisp_Object Qmenu_bar_update_hook;
360
a2889657 361/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 362
5f5c8ee5 363static int overlay_arrow_seen;
ca26e1c8 364
fba9ce76 365/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 366
5f5c8ee5
GM
367int highlight_nonselected_windows;
368
369/* If cursor motion alone moves point off frame, try scrolling this
370 many lines up or down if that will bring it back. */
371
14510fee 372static int scroll_step;
a2889657 373
5f5c8ee5
GM
374/* Non-0 means scroll just far enough to bring point back on the
375 screen, when appropriate. */
376
0789adb2
RS
377static int scroll_conservatively;
378
5f5c8ee5
GM
379/* Recenter the window whenever point gets within this many lines of
380 the top or bottom of the window. This value is translated into a
381 pixel value by multiplying it with CANON_Y_UNIT, which means that
382 there is really a fixed pixel height scroll margin. */
383
9afd2168
RS
384int scroll_margin;
385
5f5c8ee5
GM
386/* Number of windows showing the buffer of the selected window (or
387 another buffer with the same base buffer). keyboard.c refers to
388 this. */
a2889657 389
a2889657
JB
390int buffer_shared;
391
5f5c8ee5 392/* Vector containing glyphs for an ellipsis `...'. */
a2889657 393
5f5c8ee5 394static Lisp_Object default_invis_vector[3];
a2889657 395
5f5c8ee5 396/* Nonzero means display mode line highlighted. */
a2889657 397
a2889657
JB
398int mode_line_inverse_video;
399
5f5c8ee5
GM
400/* Prompt to display in front of the mini-buffer contents. */
401
8c5b6a0a 402Lisp_Object minibuf_prompt;
a2889657 403
5f5c8ee5
GM
404/* Width of current mini-buffer prompt. Only set after display_line
405 of the line that contains the prompt. */
406
a2889657 407int minibuf_prompt_width;
5f5c8ee5
GM
408int minibuf_prompt_pixel_width;
409
5f5c8ee5
GM
410/* This is the window where the echo area message was displayed. It
411 is always a mini-buffer window, but it may not be the same window
412 currently active as a mini-buffer. */
413
73af359d
RS
414Lisp_Object echo_area_window;
415
c6e89d6c
GM
416/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
417 pushes the current message and the value of
418 message_enable_multibyte on the stack, the function restore_message
419 pops the stack and displays MESSAGE again. */
420
421Lisp_Object Vmessage_stack;
422
a3788d53
RS
423/* Nonzero means multibyte characters were enabled when the echo area
424 message was specified. */
5f5c8ee5 425
a3788d53
RS
426int message_enable_multibyte;
427
5f5c8ee5
GM
428/* True if we should redraw the mode lines on the next redisplay. */
429
a2889657
JB
430int update_mode_lines;
431
5f5c8ee5
GM
432/* Nonzero if window sizes or contents have changed since last
433 redisplay that finished */
434
a2889657
JB
435int windows_or_buffers_changed;
436
5f5c8ee5
GM
437/* Nonzero after display_mode_line if %l was used and it displayed a
438 line number. */
439
aa6d10fa
RS
440int line_number_displayed;
441
442/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 443
14510fee 444static int line_number_display_limit;
5992c4f7 445
5d121aec
KH
446/* line width to consider when repostioning for line number display */
447
448static int line_number_display_limit_width;
449
5f5c8ee5
GM
450/* Number of lines to keep in the message log buffer. t means
451 infinite. nil means don't log at all. */
452
5992c4f7 453Lisp_Object Vmessage_log_max;
d45de95b 454
c6e89d6c
GM
455/* Current, index 0, and last displayed echo area message. Either
456 buffers from echo_buffers, or nil to indicate no message. */
457
458Lisp_Object echo_area_buffer[2];
459
460/* The buffers referenced from echo_area_buffer. */
461
462static Lisp_Object echo_buffer[2];
463
464/* A vector saved used in with_area_buffer to reduce consing. */
465
466static Lisp_Object Vwith_echo_area_save_vector;
467
468/* Non-zero means display_echo_area should display the last echo area
469 message again. Set by redisplay_preserve_echo_area. */
470
471static int display_last_displayed_message_p;
472
473/* Nonzero if echo area is being used by print; zero if being used by
474 message. */
475
476int message_buf_print;
477
9142dd5b
GM
478/* Maximum height for resizing mini-windows. Either a float
479 specifying a fraction of the available height, or an integer
480 specifying a number of lines. */
c6e89d6c
GM
481
482static Lisp_Object Vmax_mini_window_height;
483
d6d26ed3
GM
484/* Non-zero means we want a hollow cursor in windows that are not
485 selected. Zero means there's no cursor in such windows. */
486
487int cursor_in_non_selected_windows;
488
5f5c8ee5
GM
489/* A scratch glyph row with contents used for generating truncation
490 glyphs. Also used in direct_output_for_insert. */
12adba34 491
5f5c8ee5
GM
492#define MAX_SCRATCH_GLYPHS 100
493struct glyph_row scratch_glyph_row;
494static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 495
5f5c8ee5
GM
496/* Ascent and height of the last line processed by move_it_to. */
497
498static int last_max_ascent, last_height;
499
500/* The maximum distance to look ahead for text properties. Values
501 that are too small let us call compute_char_face and similar
502 functions too often which is expensive. Values that are too large
503 let us call compute_char_face and alike too often because we
504 might not be interested in text properties that far away. */
505
506#define TEXT_PROP_DISTANCE_LIMIT 100
507
508/* Non-zero means print traces of redisplay if compiled with
509 GLYPH_DEBUG != 0. */
510
511#if GLYPH_DEBUG
512int trace_redisplay_p;
513#endif
514
515/* Value returned from text property handlers (see below). */
516
517enum prop_handled
3c6595e0 518{
5f5c8ee5
GM
519 HANDLED_NORMALLY,
520 HANDLED_RECOMPUTE_PROPS,
521 HANDLED_OVERLAY_STRING_CONSUMED,
522 HANDLED_RETURN
523};
3c6595e0 524
5f5c8ee5
GM
525/* A description of text properties that redisplay is interested
526 in. */
3c6595e0 527
5f5c8ee5
GM
528struct props
529{
530 /* The name of the property. */
531 Lisp_Object *name;
90adcf20 532
5f5c8ee5
GM
533 /* A unique index for the property. */
534 enum prop_idx idx;
535
536 /* A handler function called to set up iterator IT from the property
537 at IT's current position. Value is used to steer handle_stop. */
538 enum prop_handled (*handler) P_ ((struct it *it));
539};
540
541static enum prop_handled handle_face_prop P_ ((struct it *));
542static enum prop_handled handle_invisible_prop P_ ((struct it *));
543static enum prop_handled handle_display_prop P_ ((struct it *));
260a86a0 544static enum prop_handled handle_composition_prop P_ ((struct it *));
5f5c8ee5
GM
545static enum prop_handled handle_overlay_change P_ ((struct it *));
546static enum prop_handled handle_fontified_prop P_ ((struct it *));
547
548/* Properties handled by iterators. */
549
550static struct props it_props[] =
5992c4f7 551{
5f5c8ee5
GM
552 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
553 /* Handle `face' before `display' because some sub-properties of
554 `display' need to know the face. */
555 {&Qface, FACE_PROP_IDX, handle_face_prop},
556 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
557 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
260a86a0 558 {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
5f5c8ee5
GM
559 {NULL, 0, NULL}
560};
5992c4f7 561
5f5c8ee5
GM
562/* Value is the position described by X. If X is a marker, value is
563 the marker_position of X. Otherwise, value is X. */
12adba34 564
5f5c8ee5 565#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 566
5f5c8ee5 567/* Enumeration returned by some move_it_.* functions internally. */
12adba34 568
5f5c8ee5
GM
569enum move_it_result
570{
571 /* Not used. Undefined value. */
572 MOVE_UNDEFINED,
bab29e15 573
5f5c8ee5
GM
574 /* Move ended at the requested buffer position or ZV. */
575 MOVE_POS_MATCH_OR_ZV,
bab29e15 576
5f5c8ee5
GM
577 /* Move ended at the requested X pixel position. */
578 MOVE_X_REACHED,
12adba34 579
5f5c8ee5
GM
580 /* Move within a line ended at the end of a line that must be
581 continued. */
582 MOVE_LINE_CONTINUED,
583
584 /* Move within a line ended at the end of a line that would
585 be displayed truncated. */
586 MOVE_LINE_TRUNCATED,
ff6c30e5 587
5f5c8ee5
GM
588 /* Move within a line ended at a line end. */
589 MOVE_NEWLINE_OR_CR
590};
12adba34 591
ff6c30e5 592
5f5c8ee5
GM
593\f
594/* Function prototypes. */
595
5bcfeb49 596static void ensure_echo_area_buffers P_ ((void));
e037b9ec
GM
597static struct glyph_row *row_containing_pos P_ ((struct window *, int,
598 struct glyph_row *,
599 struct glyph_row *));
c6e89d6c
GM
600static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
601static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
c6e89d6c
GM
602static void clear_garbaged_frames P_ ((void));
603static int current_message_1 P_ ((Lisp_Object *));
604static int truncate_message_1 P_ ((int));
605static int set_message_1 P_ ((char *s, Lisp_Object, int, int));
606static int display_echo_area P_ ((struct window *));
607static int display_echo_area_1 P_ ((struct window *));
28514cd9 608static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
4fdb80f2 609static int string_char_and_length P_ ((unsigned char *, int, int *));
5f5c8ee5
GM
610static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
611 struct text_pos));
612static int compute_window_start_on_continuation_line P_ ((struct window *));
613static Lisp_Object eval_handler P_ ((Lisp_Object));
614static Lisp_Object eval_form P_ ((Lisp_Object));
615static void insert_left_trunc_glyphs P_ ((struct it *));
616static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
617static void extend_face_to_end_of_line P_ ((struct it *));
80c6cb1f 618static int append_space P_ ((struct it *, int));
5f5c8ee5
GM
619static void make_cursor_line_fully_visible P_ ((struct window *));
620static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
621static int trailing_whitespace_p P_ ((int));
622static int message_log_check_duplicate P_ ((int, int, int, int));
623int invisible_p P_ ((Lisp_Object, Lisp_Object));
624int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
625static void push_it P_ ((struct it *));
626static void pop_it P_ ((struct it *));
627static void sync_frame_with_window_matrix_rows P_ ((struct window *));
628static void redisplay_internal P_ ((int));
c6e89d6c 629static int echo_area_display P_ ((int));
5f5c8ee5
GM
630static void redisplay_windows P_ ((Lisp_Object));
631static void redisplay_window P_ ((Lisp_Object, int));
632static void update_menu_bar P_ ((struct frame *, int));
633static int try_window_reusing_current_matrix P_ ((struct window *));
634static int try_window_id P_ ((struct window *));
635static int display_line P_ ((struct it *));
636static void display_mode_lines P_ ((struct window *));
637static void display_mode_line P_ ((struct window *, enum face_id,
638 Lisp_Object));
639static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
68c45bf0 640static char *decode_mode_spec P_ ((struct window *, int, int, int));
5f5c8ee5
GM
641static void display_menu_bar P_ ((struct window *));
642static int display_count_lines P_ ((int, int, int, int, int *));
643static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
644 int, int, struct it *, int, int, int, int));
645static void compute_line_metrics P_ ((struct it *));
646static void run_redisplay_end_trigger_hook P_ ((struct it *));
647static int get_overlay_strings P_ ((struct it *));
648static void next_overlay_string P_ ((struct it *));
649void set_iterator_to_next P_ ((struct it *));
650static void reseat P_ ((struct it *, struct text_pos, int));
651static void reseat_1 P_ ((struct it *, struct text_pos, int));
652static void back_to_previous_visible_line_start P_ ((struct it *));
653static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 654static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
655static int next_element_from_display_vector P_ ((struct it *));
656static int next_element_from_string P_ ((struct it *));
657static int next_element_from_c_string P_ ((struct it *));
658static int next_element_from_buffer P_ ((struct it *));
260a86a0 659static int next_element_from_composition P_ ((struct it *));
5f5c8ee5
GM
660static int next_element_from_image P_ ((struct it *));
661static int next_element_from_stretch P_ ((struct it *));
662static void load_overlay_strings P_ ((struct it *));
663static void init_from_display_pos P_ ((struct it *, struct window *,
664 struct display_pos *));
665static void reseat_to_string P_ ((struct it *, unsigned char *,
666 Lisp_Object, int, int, int, int));
667static int charset_at_position P_ ((struct text_pos));
668static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
669 int, int, int));
670void move_it_vertically_backward P_ ((struct it *, int));
671static void init_to_row_start P_ ((struct it *, struct window *,
672 struct glyph_row *));
673static void init_to_row_end P_ ((struct it *, struct window *,
674 struct glyph_row *));
675static void back_to_previous_line_start P_ ((struct it *));
676static void forward_to_next_line_start P_ ((struct it *));
677static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
678 Lisp_Object, int));
679static struct text_pos string_pos P_ ((int, Lisp_Object));
680static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
681static int number_of_chars P_ ((unsigned char *, int));
682static void compute_stop_pos P_ ((struct it *));
683static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
684 Lisp_Object));
685static int face_before_or_after_it_pos P_ ((struct it *, int));
686static int next_overlay_change P_ ((int));
687static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
688 Lisp_Object, struct text_pos *));
689
690#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
691#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 692
5f5c8ee5 693#ifdef HAVE_WINDOW_SYSTEM
12adba34 694
e037b9ec
GM
695static void update_tool_bar P_ ((struct frame *, int));
696static void build_desired_tool_bar_string P_ ((struct frame *f));
697static int redisplay_tool_bar P_ ((struct frame *));
698static void display_tool_bar_line P_ ((struct it *));
12adba34 699
5f5c8ee5 700#endif /* HAVE_WINDOW_SYSTEM */
12adba34 701
5f5c8ee5
GM
702\f
703/***********************************************************************
704 Window display dimensions
705 ***********************************************************************/
12adba34 706
5f5c8ee5
GM
707/* Return the window-relative maximum y + 1 for glyph rows displaying
708 text in window W. This is the height of W minus the height of a
709 mode line, if any. */
710
711INLINE int
712window_text_bottom_y (w)
713 struct window *w;
714{
715 struct frame *f = XFRAME (w->frame);
716 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
717
718 if (WINDOW_WANTS_MODELINE_P (w))
719 height -= CURRENT_MODE_LINE_HEIGHT (w);
720 return height;
f88eb0b6
KH
721}
722
f82aff7c 723
5f5c8ee5
GM
724/* Return the pixel width of display area AREA of window W. AREA < 0
725 means return the total width of W, not including bitmap areas to
726 the left and right of the window. */
ff6c30e5 727
5f5c8ee5
GM
728INLINE int
729window_box_width (w, area)
730 struct window *w;
731 int area;
732{
733 struct frame *f = XFRAME (w->frame);
734 int width = XFASTINT (w->width);
735
736 if (!w->pseudo_window_p)
ff6c30e5 737 {
050d82d7 738 width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FLAGS_AREA_COLS (f);
5f5c8ee5
GM
739
740 if (area == TEXT_AREA)
741 {
742 if (INTEGERP (w->left_margin_width))
743 width -= XFASTINT (w->left_margin_width);
744 if (INTEGERP (w->right_margin_width))
745 width -= XFASTINT (w->right_margin_width);
746 }
747 else if (area == LEFT_MARGIN_AREA)
748 width = (INTEGERP (w->left_margin_width)
749 ? XFASTINT (w->left_margin_width) : 0);
750 else if (area == RIGHT_MARGIN_AREA)
751 width = (INTEGERP (w->right_margin_width)
752 ? XFASTINT (w->right_margin_width) : 0);
ff6c30e5 753 }
5f5c8ee5
GM
754
755 return width * CANON_X_UNIT (f);
ff6c30e5 756}
1adc55de 757
1adc55de 758
5f5c8ee5
GM
759/* Return the pixel height of the display area of window W, not
760 including mode lines of W, if any.. */
f88eb0b6 761
5f5c8ee5
GM
762INLINE int
763window_box_height (w)
764 struct window *w;
f88eb0b6 765{
5f5c8ee5
GM
766 struct frame *f = XFRAME (w->frame);
767 int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
768
769 if (WINDOW_WANTS_MODELINE_P (w))
770 height -= CURRENT_MODE_LINE_HEIGHT (w);
771
045dee35
GM
772 if (WINDOW_WANTS_HEADER_LINE_P (w))
773 height -= CURRENT_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
774
775 return height;
5992c4f7
KH
776}
777
778
5f5c8ee5
GM
779/* Return the frame-relative coordinate of the left edge of display
780 area AREA of window W. AREA < 0 means return the left edge of the
781 whole window, to the right of any bitmap area at the left side of
782 W. */
5992c4f7 783
5f5c8ee5
GM
784INLINE int
785window_box_left (w, area)
786 struct window *w;
787 int area;
90adcf20 788{
5f5c8ee5
GM
789 struct frame *f = XFRAME (w->frame);
790 int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
a3788d53 791
5f5c8ee5 792 if (!w->pseudo_window_p)
90adcf20 793 {
5f5c8ee5 794 x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
050d82d7 795 + FRAME_LEFT_FLAGS_AREA_WIDTH (f));
5f5c8ee5
GM
796
797 if (area == TEXT_AREA)
798 x += window_box_width (w, LEFT_MARGIN_AREA);
799 else if (area == RIGHT_MARGIN_AREA)
800 x += (window_box_width (w, LEFT_MARGIN_AREA)
801 + window_box_width (w, TEXT_AREA));
90adcf20 802 }
73af359d 803
5f5c8ee5
GM
804 return x;
805}
90adcf20 806
b6436d4e 807
5f5c8ee5
GM
808/* Return the frame-relative coordinate of the right edge of display
809 area AREA of window W. AREA < 0 means return the left edge of the
810 whole window, to the left of any bitmap area at the right side of
811 W. */
ded34426 812
5f5c8ee5
GM
813INLINE int
814window_box_right (w, area)
815 struct window *w;
816 int area;
817{
818 return window_box_left (w, area) + window_box_width (w, area);
819}
820
821
822/* Get the bounding box of the display area AREA of window W, without
823 mode lines, in frame-relative coordinates. AREA < 0 means the
824 whole window, not including bitmap areas to the left and right of
825 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
826 coordinates of the upper-left corner of the box. Return in
827 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
828
829INLINE void
830window_box (w, area, box_x, box_y, box_width, box_height)
831 struct window *w;
832 int area;
833 int *box_x, *box_y, *box_width, *box_height;
834{
835 struct frame *f = XFRAME (w->frame);
836
837 *box_width = window_box_width (w, area);
838 *box_height = window_box_height (w);
839 *box_x = window_box_left (w, area);
840 *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
841 + XFASTINT (w->top) * CANON_Y_UNIT (f));
045dee35
GM
842 if (WINDOW_WANTS_HEADER_LINE_P (w))
843 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
ded34426 844}
1adc55de 845
1adc55de 846
5f5c8ee5
GM
847/* Get the bounding box of the display area AREA of window W, without
848 mode lines. AREA < 0 means the whole window, not including bitmap
849 areas to the left and right of the window. Return in *TOP_LEFT_X
850 and TOP_LEFT_Y the frame-relative pixel coordinates of the
851 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
852 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
853 box. */
ded34426 854
5f5c8ee5
GM
855INLINE void
856window_box_edges (w, area, top_left_x, top_left_y,
857 bottom_right_x, bottom_right_y)
858 struct window *w;
859 int area;
860 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 861{
5f5c8ee5
GM
862 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
863 bottom_right_y);
864 *bottom_right_x += *top_left_x;
865 *bottom_right_y += *top_left_y;
48ae5f0a
KH
866}
867
5f5c8ee5
GM
868
869\f
870/***********************************************************************
871 Utilities
872 ***********************************************************************/
873
4fdb80f2
GM
874/* Return the next character from STR which is MAXLEN bytes long.
875 Return in *LEN the length of the character. This is like
876 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
877 we find one, we return a `?', but with the length of the illegal
878 character. */
879
880static INLINE int
7a5b8a93 881string_char_and_length (str, maxlen, len)
4fdb80f2 882 unsigned char *str;
7a5b8a93 883 int maxlen, *len;
4fdb80f2
GM
884{
885 int c;
886
887 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
888 if (!CHAR_VALID_P (c, 1))
889 /* We may not change the length here because other places in Emacs
890 don't use this function, i.e. they silently accept illegal
891 characters. */
892 c = '?';
893
894 return c;
895}
896
897
898
5f5c8ee5
GM
899/* Given a position POS containing a valid character and byte position
900 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
901
902static struct text_pos
903string_pos_nchars_ahead (pos, string, nchars)
904 struct text_pos pos;
905 Lisp_Object string;
906 int nchars;
0b1005ef 907{
5f5c8ee5
GM
908 xassert (STRINGP (string) && nchars >= 0);
909
910 if (STRING_MULTIBYTE (string))
911 {
912 int rest = STRING_BYTES (XSTRING (string)) - BYTEPOS (pos);
913 unsigned char *p = XSTRING (string)->data + BYTEPOS (pos);
914 int len;
915
916 while (nchars--)
917 {
4fdb80f2 918 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
919 p += len, rest -= len;
920 xassert (rest >= 0);
921 CHARPOS (pos) += 1;
922 BYTEPOS (pos) += len;
923 }
924 }
925 else
926 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
927
928 return pos;
0a9dc68b
RS
929}
930
0a9dc68b 931
5f5c8ee5
GM
932/* Value is the text position, i.e. character and byte position,
933 for character position CHARPOS in STRING. */
934
935static INLINE struct text_pos
936string_pos (charpos, string)
937 int charpos;
0a9dc68b 938 Lisp_Object string;
0a9dc68b 939{
5f5c8ee5
GM
940 struct text_pos pos;
941 xassert (STRINGP (string));
942 xassert (charpos >= 0);
943 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
944 return pos;
945}
946
947
948/* Value is a text position, i.e. character and byte position, for
949 character position CHARPOS in C string S. MULTIBYTE_P non-zero
950 means recognize multibyte characters. */
951
952static struct text_pos
953c_string_pos (charpos, s, multibyte_p)
954 int charpos;
955 unsigned char *s;
956 int multibyte_p;
957{
958 struct text_pos pos;
959
960 xassert (s != NULL);
961 xassert (charpos >= 0);
962
963 if (multibyte_p)
0a9dc68b 964 {
5f5c8ee5
GM
965 int rest = strlen (s), len;
966
967 SET_TEXT_POS (pos, 0, 0);
968 while (charpos--)
0a9dc68b 969 {
4fdb80f2 970 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
971 s += len, rest -= len;
972 xassert (rest >= 0);
973 CHARPOS (pos) += 1;
974 BYTEPOS (pos) += len;
0a9dc68b
RS
975 }
976 }
5f5c8ee5
GM
977 else
978 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 979
5f5c8ee5
GM
980 return pos;
981}
0a9dc68b 982
0a9dc68b 983
5f5c8ee5
GM
984/* Value is the number of characters in C string S. MULTIBYTE_P
985 non-zero means recognize multibyte characters. */
0a9dc68b 986
5f5c8ee5
GM
987static int
988number_of_chars (s, multibyte_p)
989 unsigned char *s;
990 int multibyte_p;
991{
992 int nchars;
993
994 if (multibyte_p)
995 {
996 int rest = strlen (s), len;
997 unsigned char *p = (unsigned char *) s;
0a9dc68b 998
5f5c8ee5
GM
999 for (nchars = 0; rest > 0; ++nchars)
1000 {
4fdb80f2 1001 string_char_and_length (p, rest, &len);
5f5c8ee5 1002 rest -= len, p += len;
0a9dc68b
RS
1003 }
1004 }
5f5c8ee5
GM
1005 else
1006 nchars = strlen (s);
1007
1008 return nchars;
0b1005ef
KH
1009}
1010
5f5c8ee5
GM
1011
1012/* Compute byte position NEWPOS->bytepos corresponding to
1013 NEWPOS->charpos. POS is a known position in string STRING.
1014 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1015
5f5c8ee5
GM
1016static void
1017compute_string_pos (newpos, pos, string)
1018 struct text_pos *newpos, pos;
1019 Lisp_Object string;
76412d64 1020{
5f5c8ee5
GM
1021 xassert (STRINGP (string));
1022 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
1023
1024 if (STRING_MULTIBYTE (string))
1025 *newpos = string_pos_nchars_ahead (pos, CHARPOS (*newpos) - CHARPOS (pos),
1026 string);
1027 else
1028 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1029}
1030
9c74a0dd 1031
5f5c8ee5
GM
1032/* Return the charset of the character at position POS in
1033 current_buffer. */
1adc55de 1034
5f5c8ee5
GM
1035static int
1036charset_at_position (pos)
1037 struct text_pos pos;
a2889657 1038{
5f5c8ee5
GM
1039 int c, multibyte_p;
1040 unsigned char *p = BYTE_POS_ADDR (BYTEPOS (pos));
1041
1042 multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1043 if (multibyte_p)
a2889657 1044 {
5f5c8ee5
GM
1045 int maxlen = ((BYTEPOS (pos) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
1046 - BYTEPOS (pos));
1047 int len;
4fdb80f2 1048 c = string_char_and_length (p, maxlen, &len);
a2889657 1049 }
5f5c8ee5
GM
1050 else
1051 c = *p;
1052
1053 return CHAR_CHARSET (c);
1054}
1055
1056
1057\f
1058/***********************************************************************
1059 Lisp form evaluation
1060 ***********************************************************************/
1061
1062/* Error handler for eval_form. */
1063
1064static Lisp_Object
1065eval_handler (arg)
1066 Lisp_Object arg;
1067{
1068 return Qnil;
1069}
1070
1071
1072/* Evaluate SEXPR and return the result, or nil if something went
1073 wrong. */
1074
1075static Lisp_Object
1076eval_form (sexpr)
1077 Lisp_Object sexpr;
1078{
1079 int count = specpdl_ptr - specpdl;
1080 Lisp_Object val;
1081 specbind (Qinhibit_redisplay, Qt);
1082 val = internal_condition_case_1 (Feval, sexpr, Qerror, eval_handler);
1083 return unbind_to (count, val);
1084}
1085
1086
1087\f
1088/***********************************************************************
1089 Debugging
1090 ***********************************************************************/
1091
1092#if 0
1093
1094/* Define CHECK_IT to perform sanity checks on iterators.
1095 This is for debugging. It is too slow to do unconditionally. */
1096
1097static void
1098check_it (it)
1099 struct it *it;
1100{
1101 if (it->method == next_element_from_string)
a2889657 1102 {
5f5c8ee5
GM
1103 xassert (STRINGP (it->string));
1104 xassert (IT_STRING_CHARPOS (*it) >= 0);
1105 }
1106 else if (it->method == next_element_from_buffer)
1107 {
1108 /* Check that character and byte positions agree. */
1109 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1110 }
73af359d 1111
5f5c8ee5
GM
1112 if (it->dpvec)
1113 xassert (it->current.dpvec_index >= 0);
1114 else
1115 xassert (it->current.dpvec_index < 0);
1116}
1f40cad2 1117
5f5c8ee5
GM
1118#define CHECK_IT(IT) check_it ((IT))
1119
1120#else /* not 0 */
1121
1122#define CHECK_IT(IT) (void) 0
1123
1124#endif /* not 0 */
1125
1126
1127#if GLYPH_DEBUG
1128
1129/* Check that the window end of window W is what we expect it
1130 to be---the last row in the current matrix displaying text. */
1131
1132static void
1133check_window_end (w)
1134 struct window *w;
1135{
1136 if (!MINI_WINDOW_P (w)
1137 && !NILP (w->window_end_valid))
1138 {
1139 struct glyph_row *row;
1140 xassert ((row = MATRIX_ROW (w->current_matrix,
1141 XFASTINT (w->window_end_vpos)),
1142 !row->enabled_p
1143 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1144 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1145 }
1146}
1147
1148#define CHECK_WINDOW_END(W) check_window_end ((W))
1149
1150#else /* not GLYPH_DEBUG */
1151
1152#define CHECK_WINDOW_END(W) (void) 0
1153
1154#endif /* not GLYPH_DEBUG */
1155
1156
1157\f
1158/***********************************************************************
1159 Iterator initialization
1160 ***********************************************************************/
1161
1162/* Initialize IT for displaying current_buffer in window W, starting
1163 at character position CHARPOS. CHARPOS < 0 means that no buffer
1164 position is specified which is useful when the iterator is assigned
1165 a position later. BYTEPOS is the byte position corresponding to
1166 CHARPOS. BYTEPOS <= 0 means compute it from CHARPOS.
1167
1168 If ROW is not null, calls to produce_glyphs with IT as parameter
1169 will produce glyphs in that row.
1170
1171 BASE_FACE_ID is the id of a base face to use. It must be one of
1172 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID or
045dee35 1173 HEADER_LINE_FACE_ID for displaying mode lines, or TOOL_BAR_FACE_ID for
e037b9ec 1174 displaying the tool-bar.
5f5c8ee5
GM
1175
1176 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID or
045dee35 1177 HEADER_LINE_FACE_ID, the iterator will be initialized to use the
5f5c8ee5
GM
1178 corresponding mode line glyph row of the desired matrix of W. */
1179
1180void
1181init_iterator (it, w, charpos, bytepos, row, base_face_id)
1182 struct it *it;
1183 struct window *w;
1184 int charpos, bytepos;
1185 struct glyph_row *row;
1186 enum face_id base_face_id;
1187{
1188 int highlight_region_p;
5f5c8ee5
GM
1189
1190 /* Some precondition checks. */
1191 xassert (w != NULL && it != NULL);
5f5c8ee5
GM
1192 xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
1193
1194 /* If face attributes have been changed since the last redisplay,
1195 free realized faces now because they depend on face definitions
1196 that might have changed. */
1197 if (face_change_count)
1198 {
1199 face_change_count = 0;
1200 free_all_realized_faces (Qnil);
1201 }
1202
1203 /* Use one of the mode line rows of W's desired matrix if
1204 appropriate. */
1205 if (row == NULL)
1206 {
1207 if (base_face_id == MODE_LINE_FACE_ID)
1208 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
1209 else if (base_face_id == HEADER_LINE_FACE_ID)
1210 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5
GM
1211 }
1212
1213 /* Clear IT. */
1214 bzero (it, sizeof *it);
1215 it->current.overlay_string_index = -1;
1216 it->current.dpvec_index = -1;
1217 it->charset = CHARSET_ASCII;
1218 it->base_face_id = base_face_id;
1219
1220 /* The window in which we iterate over current_buffer: */
1221 XSETWINDOW (it->window, w);
1222 it->w = w;
1223 it->f = XFRAME (w->frame);
1224
1225 /* If realized faces have been removed, e.g. because of face
1226 attribute changes of named faces, recompute them. */
1227 if (FRAME_FACE_CACHE (it->f)->used == 0)
1228 recompute_basic_faces (it->f);
1229
5f5c8ee5
GM
1230 /* Current value of the `space-width', and 'height' properties. */
1231 it->space_width = Qnil;
1232 it->font_height = Qnil;
1233
1234 /* Are control characters displayed as `^C'? */
1235 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
1236
1237 /* -1 means everything between a CR and the following line end
1238 is invisible. >0 means lines indented more than this value are
1239 invisible. */
1240 it->selective = (INTEGERP (current_buffer->selective_display)
1241 ? XFASTINT (current_buffer->selective_display)
1242 : (!NILP (current_buffer->selective_display)
1243 ? -1 : 0));
1244 it->selective_display_ellipsis_p
1245 = !NILP (current_buffer->selective_display_ellipses);
1246
1247 /* Display table to use. */
1248 it->dp = window_display_table (w);
1249
1250 /* Are multibyte characters enabled in current_buffer? */
1251 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
1252
1253 /* Non-zero if we should highlight the region. */
1254 highlight_region_p
1255 = (!NILP (Vtransient_mark_mode)
1256 && !NILP (current_buffer->mark_active)
1257 && XMARKER (current_buffer->mark)->buffer != 0);
1258
1259 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
1260 start and end of a visible region in window IT->w. Set both to
1261 -1 to indicate no region. */
1262 if (highlight_region_p
1263 /* Maybe highlight only in selected window. */
1264 && (/* Either show region everywhere. */
1265 highlight_nonselected_windows
1266 /* Or show region in the selected window. */
1267 || w == XWINDOW (selected_window)
1268 /* Or show the region if we are in the mini-buffer and W is
1269 the window the mini-buffer refers to. */
1270 || (MINI_WINDOW_P (XWINDOW (selected_window))
1271 && w == XWINDOW (Vminibuf_scroll_window))))
1272 {
1273 int charpos = marker_position (current_buffer->mark);
1274 it->region_beg_charpos = min (PT, charpos);
1275 it->region_end_charpos = max (PT, charpos);
1276 }
1277 else
1278 it->region_beg_charpos = it->region_end_charpos = -1;
1279
1280 /* Get the position at which the redisplay_end_trigger hook should
1281 be run, if it is to be run at all. */
1282 if (MARKERP (w->redisplay_end_trigger)
1283 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
1284 it->redisplay_end_trigger_charpos
1285 = marker_position (w->redisplay_end_trigger);
1286 else if (INTEGERP (w->redisplay_end_trigger))
1287 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
1288
1289 /* Correct bogus values of tab_width. */
1290 it->tab_width = XINT (current_buffer->tab_width);
1291 if (it->tab_width <= 0 || it->tab_width > 1000)
1292 it->tab_width = 8;
1293
1294 /* Are lines in the display truncated? */
1295 it->truncate_lines_p
1296 = (base_face_id != DEFAULT_FACE_ID
1297 || XINT (it->w->hscroll)
1298 || (truncate_partial_width_windows
1299 && !WINDOW_FULL_WIDTH_P (it->w))
1300 || !NILP (current_buffer->truncate_lines));
1301
1302 /* Get dimensions of truncation and continuation glyphs. These are
1303 displayed as bitmaps under X, so we don't need them for such
1304 frames. */
1305 if (!FRAME_WINDOW_P (it->f))
1306 {
1307 if (it->truncate_lines_p)
1308 {
1309 /* We will need the truncation glyph. */
1310 xassert (it->glyph_row == NULL);
1311 produce_special_glyphs (it, IT_TRUNCATION);
1312 it->truncation_pixel_width = it->pixel_width;
1313 }
1314 else
1315 {
1316 /* We will need the continuation glyph. */
1317 xassert (it->glyph_row == NULL);
1318 produce_special_glyphs (it, IT_CONTINUATION);
1319 it->continuation_pixel_width = it->pixel_width;
1320 }
1321
1322 /* Reset these values to zero becaue the produce_special_glyphs
1323 above has changed them. */
1324 it->pixel_width = it->ascent = it->descent = 0;
312246d1 1325 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
1326 }
1327
1328 /* Set this after getting the dimensions of truncation and
1329 continuation glyphs, so that we don't produce glyphs when calling
1330 produce_special_glyphs, above. */
1331 it->glyph_row = row;
1332 it->area = TEXT_AREA;
1333
1334 /* Get the dimensions of the display area. The display area
1335 consists of the visible window area plus a horizontally scrolled
1336 part to the left of the window. All x-values are relative to the
1337 start of this total display area. */
1338 if (base_face_id != DEFAULT_FACE_ID)
1339 {
1340 /* Mode lines, menu bar in terminal frames. */
1341 it->first_visible_x = 0;
1342 it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
1343 }
1344 else
1345 {
1346 it->first_visible_x
1347 = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
1348 it->last_visible_x = (it->first_visible_x
1349 + window_box_width (w, TEXT_AREA));
1350
1351 /* If we truncate lines, leave room for the truncator glyph(s) at
1352 the right margin. Otherwise, leave room for the continuation
1353 glyph(s). Truncation and continuation glyphs are not inserted
1354 for window-based redisplay. */
1355 if (!FRAME_WINDOW_P (it->f))
1356 {
1357 if (it->truncate_lines_p)
1358 it->last_visible_x -= it->truncation_pixel_width;
1359 else
1360 it->last_visible_x -= it->continuation_pixel_width;
1361 }
1362
045dee35
GM
1363 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
1364 it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
1365 }
1366
1367 /* Leave room for a border glyph. */
1368 if (!FRAME_WINDOW_P (it->f)
1369 && !WINDOW_RIGHTMOST_P (it->w))
1370 it->last_visible_x -= 1;
1371
1372 it->last_visible_y = window_text_bottom_y (w);
1373
1374 /* For mode lines and alike, arrange for the first glyph having a
1375 left box line if the face specifies a box. */
1376 if (base_face_id != DEFAULT_FACE_ID)
1377 {
1378 struct face *face;
1379
1380 it->face_id = base_face_id;
1381
1382 /* If we have a boxed mode line, make the first character appear
1383 with a left box line. */
1384 face = FACE_FROM_ID (it->f, base_face_id);
1385 if (face->box != FACE_NO_BOX)
1386 it->start_of_box_run_p = 1;
1387 }
1388
1389 /* If a buffer position was specified, set the iterator there,
1390 getting overlays and face properties from that position. */
1391 if (charpos > 0)
1392 {
1393 it->end_charpos = ZV;
1394 it->face_id = -1;
1395 IT_CHARPOS (*it) = charpos;
1396
1397 /* Compute byte position if not specified. */
1398 if (bytepos <= 0)
1399 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
1400 else
1401 IT_BYTEPOS (*it) = bytepos;
1402
1403 /* Compute faces etc. */
1404 reseat (it, it->current.pos, 1);
1405 }
1406
1407 CHECK_IT (it);
1408}
1409
1410
1411/* Initialize IT for the display of window W with window start POS. */
1412
1413void
1414start_display (it, w, pos)
1415 struct it *it;
1416 struct window *w;
1417 struct text_pos pos;
1418{
1419 int start_at_line_beg_p;
1420 struct glyph_row *row;
045dee35 1421 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
1422 int first_y;
1423
1424 row = w->desired_matrix->rows + first_vpos;
1425 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
1426 first_y = it->current_y;
1427
1428 /* If window start is not at a line start, move back to the line
1429 start. This makes sure that we take continuation lines into
1430 account. */
1431 start_at_line_beg_p = (CHARPOS (pos) == BEGV
1432 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
1433 if (!start_at_line_beg_p)
1434 reseat_at_previous_visible_line_start (it);
1435
5f5c8ee5
GM
1436 /* If window start is not at a line start, skip forward to POS to
1437 get the correct continuation_lines_width and current_x. */
1438 if (!start_at_line_beg_p)
1439 {
1440 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
1441
1442 /* If lines are continued, this line may end in the middle of a
1443 multi-glyph character (e.g. a control character displayed as
1444 \003, or in the middle of an overlay string). In this case
1445 move_it_to above will not have taken us to the start of
1446 the continuation line but to the end of the continued line. */
1447 if (!it->truncate_lines_p && it->current_x > 0)
1448 {
1449 if (it->current.dpvec_index >= 0
1450 || it->current.overlay_string_index >= 0)
1451 {
1452 set_iterator_to_next (it);
1453 move_it_in_display_line_to (it, -1, -1, 0);
1454 }
1455 it->continuation_lines_width += it->current_x;
1456 }
1457
1458 it->current_y = first_y;
1459 it->vpos = 0;
1460 it->current_x = it->hpos = 0;
1461 }
1462
1463#if 0 /* Don't assert the following because start_display is sometimes
1464 called intentionally with a window start that is not at a
1465 line start. Please leave this code in as a comment. */
1466
1467 /* Window start should be on a line start, now. */
1468 xassert (it->continuation_lines_width
1469 || IT_CHARPOS (it) == BEGV
1470 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
1471#endif /* 0 */
1472}
1473
1474
1475/* Initialize IT for stepping through current_buffer in window W,
1476 starting at position POS that includes overlay string and display
1477 vector/ control character translation position information. */
1478
1479static void
1480init_from_display_pos (it, w, pos)
1481 struct it *it;
1482 struct window *w;
1483 struct display_pos *pos;
1484{
1485 /* Keep in mind: the call to reseat in init_iterator skips invisible
1486 text, so we might end up at a position different from POS. This
1487 is only a problem when POS is a row start after a newline and an
1488 overlay starts there with an after-string, and the overlay has an
1489 invisible property. Since we don't skip invisible text in
1490 display_line and elsewhere immediately after consuming the
1491 newline before the row start, such a POS will not be in a string,
1492 but the call to init_iterator below will move us to the
1493 after-string. */
1494 init_iterator (it, w, CHARPOS (pos->pos), BYTEPOS (pos->pos),
1495 NULL, DEFAULT_FACE_ID);
1496
1497 /* If position is within an overlay string, set up IT to
1498 the right overlay string. */
1499 if (pos->overlay_string_index >= 0)
1500 {
1501 int relative_index;
1502
1503 /* We already have the first chunk of overlay strings in
1504 IT->overlay_strings. Load more until the one for
1505 pos->overlay_string_index is in IT->overlay_strings. */
1506 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
1507 {
1508 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
1509 it->current.overlay_string_index = 0;
1510 while (n--)
1511 {
1512 load_overlay_strings (it);
1513 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
1514 }
1515 }
1516
1517 it->current.overlay_string_index = pos->overlay_string_index;
1518 relative_index = (it->current.overlay_string_index
1519 % OVERLAY_STRING_CHUNK_SIZE);
1520 it->string = it->overlay_strings[relative_index];
1521 it->current.string_pos = pos->string_pos;
1522 it->method = next_element_from_string;
1523 }
1524 else if (CHARPOS (pos->string_pos) >= 0)
1525 {
1526 /* Recorded position is not in an overlay string, but in another
1527 string. This can only be a string from a `display' property.
1528 IT should already be filled with that string. */
1529 it->current.string_pos = pos->string_pos;
1530 xassert (STRINGP (it->string));
1531 }
1532
1533 /* Restore position in display vector translations or control
1534 character translations. */
1535 if (pos->dpvec_index >= 0)
1536 {
1537 /* This fills IT->dpvec. */
1538 get_next_display_element (it);
1539 xassert (it->dpvec && it->current.dpvec_index == 0);
1540 it->current.dpvec_index = pos->dpvec_index;
1541 }
1542
1543 CHECK_IT (it);
1544}
1545
1546
1547/* Initialize IT for stepping through current_buffer in window W
1548 starting at ROW->start. */
1549
1550static void
1551init_to_row_start (it, w, row)
1552 struct it *it;
1553 struct window *w;
1554 struct glyph_row *row;
1555{
1556 init_from_display_pos (it, w, &row->start);
1557 it->continuation_lines_width = row->continuation_lines_width;
1558 CHECK_IT (it);
1559}
1560
1561
1562/* Initialize IT for stepping through current_buffer in window W
1563 starting in the line following ROW, i.e. starting at ROW->end. */
1564
1565static void
1566init_to_row_end (it, w, row)
1567 struct it *it;
1568 struct window *w;
1569 struct glyph_row *row;
1570{
1571 init_from_display_pos (it, w, &row->end);
1572
1573 if (row->continued_p)
1574 it->continuation_lines_width = (row->continuation_lines_width
1575 + row->pixel_width);
1576 CHECK_IT (it);
1577}
1578
1579
1580
1581\f
1582/***********************************************************************
1583 Text properties
1584 ***********************************************************************/
1585
1586/* Called when IT reaches IT->stop_charpos. Handle text property and
1587 overlay changes. Set IT->stop_charpos to the next position where
1588 to stop. */
1589
1590static void
1591handle_stop (it)
1592 struct it *it;
1593{
1594 enum prop_handled handled;
1595 int handle_overlay_change_p = 1;
1596 struct props *p;
1597
1598 it->dpvec = NULL;
1599 it->current.dpvec_index = -1;
1600
1601 do
1602 {
1603 handled = HANDLED_NORMALLY;
1604
1605 /* Call text property handlers. */
1606 for (p = it_props; p->handler; ++p)
1607 {
1608 handled = p->handler (it);
1609
1610 if (handled == HANDLED_RECOMPUTE_PROPS)
1611 break;
1612 else if (handled == HANDLED_RETURN)
1613 return;
1614 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
1615 handle_overlay_change_p = 0;
1616 }
1617
1618 if (handled != HANDLED_RECOMPUTE_PROPS)
1619 {
1620 /* Don't check for overlay strings below when set to deliver
1621 characters from a display vector. */
1622 if (it->method == next_element_from_display_vector)
1623 handle_overlay_change_p = 0;
1624
1625 /* Handle overlay changes. */
1626 if (handle_overlay_change_p)
1627 handled = handle_overlay_change (it);
1628
1629 /* Determine where to stop next. */
1630 if (handled == HANDLED_NORMALLY)
1631 compute_stop_pos (it);
1632 }
1633 }
1634 while (handled == HANDLED_RECOMPUTE_PROPS);
1635}
1636
1637
1638/* Compute IT->stop_charpos from text property and overlay change
1639 information for IT's current position. */
1640
1641static void
1642compute_stop_pos (it)
1643 struct it *it;
1644{
1645 register INTERVAL iv, next_iv;
1646 Lisp_Object object, limit, position;
1647
1648 /* If nowhere else, stop at the end. */
1649 it->stop_charpos = it->end_charpos;
1650
1651 if (STRINGP (it->string))
1652 {
1653 /* Strings are usually short, so don't limit the search for
1654 properties. */
1655 object = it->string;
1656 limit = Qnil;
1657 XSETFASTINT (position, IT_STRING_CHARPOS (*it));
1658 }
1659 else
1660 {
1661 int charpos;
1662
1663 /* If next overlay change is in front of the current stop pos
1664 (which is IT->end_charpos), stop there. Note: value of
1665 next_overlay_change is point-max if no overlay change
1666 follows. */
1667 charpos = next_overlay_change (IT_CHARPOS (*it));
1668 if (charpos < it->stop_charpos)
1669 it->stop_charpos = charpos;
1670
1671 /* If showing the region, we have to stop at the region
1672 start or end because the face might change there. */
1673 if (it->region_beg_charpos > 0)
1674 {
1675 if (IT_CHARPOS (*it) < it->region_beg_charpos)
1676 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
1677 else if (IT_CHARPOS (*it) < it->region_end_charpos)
1678 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
1679 }
1680
1681 /* Set up variables for computing the stop position from text
1682 property changes. */
1683 XSETBUFFER (object, current_buffer);
1684 XSETFASTINT (limit, IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
1685 XSETFASTINT (position, IT_CHARPOS (*it));
1686
1687 }
1688
1689 /* Get the interval containing IT's position. Value is a null
1690 interval if there isn't such an interval. */
1691 iv = validate_interval_range (object, &position, &position, 0);
1692 if (!NULL_INTERVAL_P (iv))
1693 {
1694 Lisp_Object values_here[LAST_PROP_IDX];
1695 struct props *p;
1696
1697 /* Get properties here. */
1698 for (p = it_props; p->handler; ++p)
1699 values_here[p->idx] = textget (iv->plist, *p->name);
1700
1701 /* Look for an interval following iv that has different
1702 properties. */
1703 for (next_iv = next_interval (iv);
1704 (!NULL_INTERVAL_P (next_iv)
1705 && (NILP (limit)
1706 || XFASTINT (limit) > next_iv->position));
1707 next_iv = next_interval (next_iv))
1708 {
1709 for (p = it_props; p->handler; ++p)
1710 {
1711 Lisp_Object new_value;
1712
1713 new_value = textget (next_iv->plist, *p->name);
1714 if (!EQ (values_here[p->idx], new_value))
1715 break;
1716 }
1717
1718 if (p->handler)
1719 break;
1720 }
1721
1722 if (!NULL_INTERVAL_P (next_iv))
1723 {
1724 if (INTEGERP (limit)
1725 && next_iv->position >= XFASTINT (limit))
1726 /* No text property change up to limit. */
1727 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
1728 else
1729 /* Text properties change in next_iv. */
1730 it->stop_charpos = min (it->stop_charpos, next_iv->position);
1731 }
1732 }
1733
1734 xassert (STRINGP (it->string)
1735 || (it->stop_charpos >= BEGV
1736 && it->stop_charpos >= IT_CHARPOS (*it)));
1737}
1738
1739
1740/* Return the position of the next overlay change after POS in
1741 current_buffer. Value is point-max if no overlay change
1742 follows. This is like `next-overlay-change' but doesn't use
1743 xmalloc. */
1744
1745static int
1746next_overlay_change (pos)
1747 int pos;
1748{
1749 int noverlays;
1750 int endpos;
1751 Lisp_Object *overlays;
1752 int len;
1753 int i;
1754
1755 /* Get all overlays at the given position. */
1756 len = 10;
1757 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
1758 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
1759 if (noverlays > len)
1760 {
1761 len = noverlays;
1762 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
1763 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL);
1764 }
1765
1766 /* If any of these overlays ends before endpos,
1767 use its ending point instead. */
1768 for (i = 0; i < noverlays; ++i)
1769 {
1770 Lisp_Object oend;
1771 int oendpos;
1772
1773 oend = OVERLAY_END (overlays[i]);
1774 oendpos = OVERLAY_POSITION (oend);
1775 endpos = min (endpos, oendpos);
1776 }
1777
1778 return endpos;
1779}
1780
1781
1782\f
1783/***********************************************************************
1784 Fontification
1785 ***********************************************************************/
1786
1787/* Handle changes in the `fontified' property of the current buffer by
1788 calling hook functions from Qfontification_functions to fontify
1789 regions of text. */
1790
1791static enum prop_handled
1792handle_fontified_prop (it)
1793 struct it *it;
1794{
1795 Lisp_Object prop, pos;
1796 enum prop_handled handled = HANDLED_NORMALLY;
2bf6fa4b 1797 struct gcpro gcpro1;
5f5c8ee5
GM
1798
1799 /* Get the value of the `fontified' property at IT's current buffer
1800 position. (The `fontified' property doesn't have a special
1801 meaning in strings.) If the value is nil, call functions from
1802 Qfontification_functions. */
1803 if (!STRINGP (it->string)
1804 && it->s == NULL
1805 && !NILP (Vfontification_functions)
1806 && (pos = make_number (IT_CHARPOS (*it)),
1807 prop = Fget_char_property (pos, Qfontified, Qnil),
1808 NILP (prop)))
1809 {
1810 Lisp_Object args[2];
1811
2bf6fa4b 1812 GCPRO1 (pos);
5f5c8ee5
GM
1813 /* Run the hook functions. */
1814 args[0] = Qfontification_functions;
1815 args[1] = pos;
1816 Frun_hook_with_args (make_number (2), args);
1817
1818 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
1819 something. This avoids an endless loop if they failed to
1820 fontify the text for which reason ever. */
1821 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
1822 handled = HANDLED_RECOMPUTE_PROPS;
2bf6fa4b 1823 UNGCPRO;
5f5c8ee5
GM
1824 }
1825
1826 return handled;
1827}
1828
1829
1830\f
1831/***********************************************************************
1832 Faces
1833 ***********************************************************************/
1834
1835/* Set up iterator IT from face properties at its current position.
1836 Called from handle_stop. */
1837
1838static enum prop_handled
1839handle_face_prop (it)
1840 struct it *it;
1841{
1842 int new_face_id, next_stop;
1843
1844 if (!STRINGP (it->string))
1845 {
1846 new_face_id
1847 = face_at_buffer_position (it->w,
1848 IT_CHARPOS (*it),
1849 it->region_beg_charpos,
1850 it->region_end_charpos,
1851 &next_stop,
1852 (IT_CHARPOS (*it)
1853 + TEXT_PROP_DISTANCE_LIMIT),
1854 0);
1855
1856 /* Is this a start of a run of characters with box face?
1857 Caveat: this can be called for a freshly initialized
1858 iterator; face_id is -1 is this case. We know that the new
1859 face will not change until limit, i.e. if the new face has a
1860 box, all characters up to limit will have one. But, as
1861 usual, we don't know whether limit is really the end. */
1862 if (new_face_id != it->face_id)
1863 {
1864 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1865
1866 /* If new face has a box but old face has not, this is
1867 the start of a run of characters with box, i.e. it has
1868 a shadow on the left side. The value of face_id of the
1869 iterator will be -1 if this is the initial call that gets
1870 the face. In this case, we have to look in front of IT's
1871 position and see whether there is a face != new_face_id. */
1872 it->start_of_box_run_p
1873 = (new_face->box != FACE_NO_BOX
1874 && (it->face_id >= 0
1875 || IT_CHARPOS (*it) == BEG
1876 || new_face_id != face_before_it_pos (it)));
1877 it->face_box_p = new_face->box != FACE_NO_BOX;
1878 }
1879 }
1880 else
1881 {
1882 new_face_id
1883 = face_at_string_position (it->w,
1884 it->string,
1885 IT_STRING_CHARPOS (*it),
1886 (it->current.overlay_string_index >= 0
1887 ? IT_CHARPOS (*it)
1888 : 0),
1889 it->region_beg_charpos,
1890 it->region_end_charpos,
1891 &next_stop,
1892 it->base_face_id);
1893
1894#if 0 /* This shouldn't be neccessary. Let's check it. */
1895 /* If IT is used to display a mode line we would really like to
1896 use the mode line face instead of the frame's default face. */
1897 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
1898 && new_face_id == DEFAULT_FACE_ID)
1899 new_face_id = MODE_LINE_FACE_ID;
1900#endif
1901
1902 /* Is this a start of a run of characters with box? Caveat:
1903 this can be called for a freshly allocated iterator; face_id
1904 is -1 is this case. We know that the new face will not
1905 change until the next check pos, i.e. if the new face has a
1906 box, all characters up to that position will have a
1907 box. But, as usual, we don't know whether that position
1908 is really the end. */
1909 if (new_face_id != it->face_id)
1910 {
1911 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
1912 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
1913
1914 /* If new face has a box but old face hasn't, this is the
1915 start of a run of characters with box, i.e. it has a
1916 shadow on the left side. */
1917 it->start_of_box_run_p
1918 = new_face->box && (old_face == NULL || !old_face->box);
1919 it->face_box_p = new_face->box != FACE_NO_BOX;
1920 }
1921 }
1922
1923 it->face_id = new_face_id;
1924 it->charset = CHARSET_ASCII;
1925 return HANDLED_NORMALLY;
1926}
1927
1928
1929/* Compute the face one character before or after the current position
1930 of IT. BEFORE_P non-zero means get the face in front of IT's
1931 position. Value is the id of the face. */
1932
1933static int
1934face_before_or_after_it_pos (it, before_p)
1935 struct it *it;
1936 int before_p;
1937{
1938 int face_id, limit;
1939 int next_check_charpos;
1940 struct text_pos pos;
1941
1942 xassert (it->s == NULL);
1943
1944 if (STRINGP (it->string))
1945 {
1946 /* No face change past the end of the string (for the case
1947 we are padding with spaces). No face change before the
1948 string start. */
1949 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size
1950 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
1951 return it->face_id;
1952
1953 /* Set pos to the position before or after IT's current position. */
1954 if (before_p)
1955 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
1956 else
260a86a0
KH
1957 /* For composition, we must check the character after the
1958 composition. */
1959 pos = (it->what == IT_COMPOSITION
1960 ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
1961 : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
5f5c8ee5
GM
1962
1963 /* Get the face for ASCII, or unibyte. */
1964 face_id
1965 = face_at_string_position (it->w,
1966 it->string,
1967 CHARPOS (pos),
1968 (it->current.overlay_string_index >= 0
1969 ? IT_CHARPOS (*it)
1970 : 0),
1971 it->region_beg_charpos,
1972 it->region_end_charpos,
1973 &next_check_charpos,
1974 it->base_face_id);
1975
1976 /* Correct the face for charsets different from ASCII. Do it
1977 for the multibyte case only. The face returned above is
1978 suitable for unibyte text if IT->string is unibyte. */
1979 if (STRING_MULTIBYTE (it->string))
1980 {
1981 unsigned char *p = XSTRING (it->string)->data + BYTEPOS (pos);
1982 int rest = STRING_BYTES (XSTRING (it->string)) - BYTEPOS (pos);
1983 int c, len, charset;
1984
4fdb80f2 1985 c = string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1986 charset = CHAR_CHARSET (c);
1987 if (charset != CHARSET_ASCII)
1988 face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
1989 }
1990 }
1991 else
1992 {
70851746
GM
1993 if ((IT_CHARPOS (*it) >= ZV && !before_p)
1994 || (IT_CHARPOS (*it) <= BEGV && before_p))
1995 return it->face_id;
1996
5f5c8ee5
GM
1997 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
1998 pos = it->current.pos;
1999
2000 if (before_p)
2001 DEC_TEXT_POS (pos);
2002 else
260a86a0
KH
2003 {
2004 if (it->what == IT_COMPOSITION)
2005 /* For composition, we must check the position after the
2006 composition. */
2007 pos.charpos += it->cmp_len, pos.bytepos += it->len;
2008 else
2009 INC_TEXT_POS (pos);
2010 }
5f5c8ee5
GM
2011 /* Determine face for CHARSET_ASCII, or unibyte. */
2012 face_id = face_at_buffer_position (it->w,
2013 CHARPOS (pos),
2014 it->region_beg_charpos,
2015 it->region_end_charpos,
2016 &next_check_charpos,
2017 limit, 0);
2018
2019 /* Correct the face for charsets different from ASCII. Do it
2020 for the multibyte case only. The face returned above is
2021 suitable for unibyte text if current_buffer is unibyte. */
2022 if (it->multibyte_p)
2023 {
2024 int charset = charset_at_position (pos);
2025 if (charset != CHARSET_ASCII)
2026 face_id = FACE_FOR_CHARSET (it->f, face_id, charset);
2027 }
2028 }
2029
2030 return face_id;
2031}
2032
2033
2034\f
2035/***********************************************************************
2036 Invisible text
2037 ***********************************************************************/
2038
2039/* Set up iterator IT from invisible properties at its current
2040 position. Called from handle_stop. */
2041
2042static enum prop_handled
2043handle_invisible_prop (it)
2044 struct it *it;
2045{
2046 enum prop_handled handled = HANDLED_NORMALLY;
2047
2048 if (STRINGP (it->string))
2049 {
2050 extern Lisp_Object Qinvisible;
2051 Lisp_Object prop, end_charpos, limit, charpos;
2052
2053 /* Get the value of the invisible text property at the
2054 current position. Value will be nil if there is no such
2055 property. */
2056 XSETFASTINT (charpos, IT_STRING_CHARPOS (*it));
2057 prop = Fget_text_property (charpos, Qinvisible, it->string);
2058
2059 if (!NILP (prop))
2060 {
2061 handled = HANDLED_RECOMPUTE_PROPS;
2062
2063 /* Get the position at which the next change of the
2064 invisible text property can be found in IT->string.
2065 Value will be nil if the property value is the same for
2066 all the rest of IT->string. */
2067 XSETINT (limit, XSTRING (it->string)->size);
2068 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2069 it->string, limit);
2070
2071 /* Text at current position is invisible. The next
2072 change in the property is at position end_charpos.
2073 Move IT's current position to that position. */
2074 if (INTEGERP (end_charpos)
2075 && XFASTINT (end_charpos) < XFASTINT (limit))
2076 {
2077 struct text_pos old;
2078 old = it->current.string_pos;
2079 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
2080 compute_string_pos (&it->current.string_pos, old, it->string);
2081 }
2082 else
2083 {
2084 /* The rest of the string is invisible. If this is an
2085 overlay string, proceed with the next overlay string
2086 or whatever comes and return a character from there. */
2087 if (it->current.overlay_string_index >= 0)
2088 {
2089 next_overlay_string (it);
2090 /* Don't check for overlay strings when we just
2091 finished processing them. */
2092 handled = HANDLED_OVERLAY_STRING_CONSUMED;
2093 }
2094 else
2095 {
2096 struct Lisp_String *s = XSTRING (it->string);
2097 IT_STRING_CHARPOS (*it) = s->size;
2098 IT_STRING_BYTEPOS (*it) = STRING_BYTES (s);
2099 }
2100 }
2101 }
2102 }
2103 else
2104 {
2105 int visible_p, newpos, next_stop;
2106 Lisp_Object pos, prop;
2107
2108 /* First of all, is there invisible text at this position? */
2109 XSETFASTINT (pos, IT_CHARPOS (*it));
2110 prop = Fget_char_property (pos, Qinvisible, it->window);
2111
2112 /* If we are on invisible text, skip over it. */
2113 if (TEXT_PROP_MEANS_INVISIBLE (prop))
2114 {
2115 /* Record whether we have to display an ellipsis for the
2116 invisible text. */
2117 int display_ellipsis_p
2118 = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
2119
2120 handled = HANDLED_RECOMPUTE_PROPS;
2121
2122 /* Loop skipping over invisible text. The loop is left at
2123 ZV or with IT on the first char being visible again. */
2124 do
2125 {
2126 /* Try to skip some invisible text. Return value is the
2127 position reached which can be equal to IT's position
2128 if there is nothing invisible here. This skips both
2129 over invisible text properties and overlays with
2130 invisible property. */
2131 newpos = skip_invisible (IT_CHARPOS (*it),
2132 &next_stop, ZV, it->window);
2133
2134 /* If we skipped nothing at all we weren't at invisible
2135 text in the first place. If everything to the end of
2136 the buffer was skipped, end the loop. */
2137 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
2138 visible_p = 1;
2139 else
2140 {
2141 /* We skipped some characters but not necessarily
2142 all there are. Check if we ended up on visible
2143 text. Fget_char_property returns the property of
2144 the char before the given position, i.e. if we
2145 get visible_p = 1, this means that the char at
2146 newpos is visible. */
2147 XSETFASTINT (pos, newpos);
2148 prop = Fget_char_property (pos, Qinvisible, it->window);
2149 visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
2150 }
2151
2152 /* If we ended up on invisible text, proceed to
2153 skip starting with next_stop. */
2154 if (!visible_p)
2155 IT_CHARPOS (*it) = next_stop;
2156 }
2157 while (!visible_p);
2158
2159 /* The position newpos is now either ZV or on visible text. */
2160 IT_CHARPOS (*it) = newpos;
2161 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2162
2163 /* Maybe return `...' next for the end of the invisible text. */
2164 if (display_ellipsis_p)
2165 {
2166 if (it->dp
2167 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
2168 {
2169 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
2170 it->dpvec = v->contents;
2171 it->dpend = v->contents + v->size;
2172 }
2173 else
2174 {
2175 /* Default `...'. */
2176 it->dpvec = default_invis_vector;
2177 it->dpend = default_invis_vector + 3;
2178 }
2179
2180 /* The ellipsis display does not replace the display of
2181 the character at the new position. Indicate this by
2182 setting IT->dpvec_char_len to zero. */
2183 it->dpvec_char_len = 0;
2184
2185 it->current.dpvec_index = 0;
2186 it->method = next_element_from_display_vector;
2187 }
2188 }
2189 }
2190
2191 return handled;
2192}
2193
2194
2195\f
2196/***********************************************************************
2197 'display' property
2198 ***********************************************************************/
2199
2200/* Set up iterator IT from `display' property at its current position.
2201 Called from handle_stop. */
2202
2203static enum prop_handled
2204handle_display_prop (it)
2205 struct it *it;
2206{
2207 Lisp_Object prop, object;
2208 struct text_pos *position;
2209 int space_or_image_found_p;
2210
2211 if (STRINGP (it->string))
2212 {
2213 object = it->string;
2214 position = &it->current.string_pos;
2215 }
2216 else
2217 {
2218 object = Qnil;
2219 position = &it->current.pos;
2220 }
2221
2222 /* Reset those iterator values set from display property values. */
2223 it->font_height = Qnil;
2224 it->space_width = Qnil;
2225 it->voffset = 0;
2226
2227 /* We don't support recursive `display' properties, i.e. string
2228 values that have a string `display' property, that have a string
2229 `display' property etc. */
2230 if (!it->string_from_display_prop_p)
2231 it->area = TEXT_AREA;
2232
2233 prop = Fget_char_property (make_number (position->charpos),
2234 Qdisplay, object);
2235 if (NILP (prop))
2236 return HANDLED_NORMALLY;
2237
2238 space_or_image_found_p = 0;
f3751a65
GM
2239 if (CONSP (prop)
2240 && CONSP (XCAR (prop))
2241 && !EQ (Qmargin, XCAR (XCAR (prop))))
5f5c8ee5 2242 {
f3751a65 2243 /* A list of sub-properties. */
5f5c8ee5
GM
2244 while (CONSP (prop))
2245 {
2246 if (handle_single_display_prop (it, XCAR (prop), object, position))
2247 space_or_image_found_p = 1;
2248 prop = XCDR (prop);
2249 }
2250 }
2251 else if (VECTORP (prop))
2252 {
2253 int i;
2254 for (i = 0; i < XVECTOR (prop)->size; ++i)
2255 if (handle_single_display_prop (it, XVECTOR (prop)->contents[i],
2256 object, position))
2257 space_or_image_found_p = 1;
2258 }
2259 else
2260 {
2261 if (handle_single_display_prop (it, prop, object, position))
2262 space_or_image_found_p = 1;
2263 }
2264
2265 return space_or_image_found_p ? HANDLED_RETURN : HANDLED_NORMALLY;
2266}
2267
2268
6c577098 2269/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
2270 at START_POS in OBJECT. */
2271
2272static struct text_pos
2273display_prop_end (it, object, start_pos)
2274 struct it *it;
2275 Lisp_Object object;
2276 struct text_pos start_pos;
2277{
2278 Lisp_Object end;
2279 struct text_pos end_pos;
5f5c8ee5 2280
6c577098
GM
2281 end = next_single_char_property_change (make_number (CHARPOS (start_pos)),
2282 Qdisplay, object, Qnil);
2283 CHARPOS (end_pos) = XFASTINT (end);
2284 if (STRINGP (object))
5f5c8ee5
GM
2285 compute_string_pos (&end_pos, start_pos, it->string);
2286 else
6c577098 2287 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
2288
2289 return end_pos;
2290}
2291
2292
2293/* Set up IT from a single `display' sub-property value PROP. OBJECT
2294 is the object in which the `display' property was found. *POSITION
2295 is the position at which it was found.
2296
2297 If PROP is a `space' or `image' sub-property, set *POSITION to the
2298 end position of the `display' property.
2299
2300 Value is non-zero if a `space' or `image' property value was found. */
2301
2302static int
2303handle_single_display_prop (it, prop, object, position)
2304 struct it *it;
2305 Lisp_Object prop;
2306 Lisp_Object object;
2307 struct text_pos *position;
2308{
2309 Lisp_Object value;
2310 int space_or_image_found_p = 0;
2311
2312 Lisp_Object form;
2313
d3acf96b 2314 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
5a4c88c4 2315 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 2316 form = Qt;
d3acf96b 2317 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
2318 {
2319 prop = XCDR (prop);
2320 if (!CONSP (prop))
2321 return 0;
2322 form = XCAR (prop);
2323 prop = XCDR (prop);
5f5c8ee5
GM
2324 }
2325
2326 if (!NILP (form) && !EQ (form, Qt))
2327 {
2328 struct gcpro gcpro1;
2329 struct text_pos end_pos, pt;
2330
2331 end_pos = display_prop_end (it, object, *position);
2332 GCPRO1 (form);
2333
2334 /* Temporarily set point to the end position, and then evaluate
2335 the form. This makes `(eolp)' work as FORM. */
2336 CHARPOS (pt) = PT;
2337 BYTEPOS (pt) = PT_BYTE;
2338 TEMP_SET_PT_BOTH (CHARPOS (end_pos), BYTEPOS (end_pos));
2339 form = eval_form (form);
2340 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
2341 UNGCPRO;
2342 }
2343
2344 if (NILP (form))
2345 return 0;
2346
2347 if (CONSP (prop)
2348 && EQ (XCAR (prop), Qheight)
2349 && CONSP (XCDR (prop)))
2350 {
2351 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2352 return 0;
2353
2354 /* `(height HEIGHT)'. */
2355 it->font_height = XCAR (XCDR (prop));
2356 if (!NILP (it->font_height))
2357 {
2358 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2359 int new_height = -1;
2360
2361 if (CONSP (it->font_height)
2362 && (EQ (XCAR (it->font_height), Qplus)
2363 || EQ (XCAR (it->font_height), Qminus))
2364 && CONSP (XCDR (it->font_height))
2365 && INTEGERP (XCAR (XCDR (it->font_height))))
2366 {
2367 /* `(+ N)' or `(- N)' where N is an integer. */
2368 int steps = XINT (XCAR (XCDR (it->font_height)));
2369 if (EQ (XCAR (it->font_height), Qplus))
2370 steps = - steps;
2371 it->face_id = smaller_face (it->f, it->face_id, steps);
2372 }
2373 else if (SYMBOLP (it->font_height))
2374 {
2375 /* Call function with current height as argument.
2376 Value is the new height. */
2377 Lisp_Object form, height;
2378 struct gcpro gcpro1;
2379
2380 height = face->lface[LFACE_HEIGHT_INDEX];
2381 form = Fcons (it->font_height, Fcons (height, Qnil));
2382 GCPRO1 (form);
2383 height = eval_form (form);
2384 if (NUMBERP (height))
2385 new_height = XFLOATINT (height);
2386 UNGCPRO;
2387 }
2388 else if (NUMBERP (it->font_height))
2389 {
2390 /* Value is a multiple of the canonical char height. */
2391 struct face *face;
2392
2393 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
2394 new_height = (XFLOATINT (it->font_height)
2395 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
2396 }
2397 else
2398 {
2399 /* Evaluate IT->font_height with `height' bound to the
2400 current specified height to get the new height. */
2401 Lisp_Object value;
2402 int count = specpdl_ptr - specpdl;
2403
2404 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
2405 value = eval_form (it->font_height);
2406 unbind_to (count, Qnil);
2407
2408 if (NUMBERP (value))
2409 new_height = XFLOATINT (value);
2410 }
2411
2412 if (new_height > 0)
2413 it->face_id = face_with_height (it->f, it->face_id, new_height);
2414 }
2415 }
2416 else if (CONSP (prop)
2417 && EQ (XCAR (prop), Qspace_width)
2418 && CONSP (XCDR (prop)))
2419 {
2420 /* `(space_width WIDTH)'. */
2421 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2422 return 0;
2423
2424 value = XCAR (XCDR (prop));
2425 if (NUMBERP (value) && XFLOATINT (value) > 0)
2426 it->space_width = value;
2427 }
2428 else if (CONSP (prop)
2429 && EQ (XCAR (prop), Qraise)
2430 && CONSP (XCDR (prop)))
2431 {
5f5c8ee5
GM
2432 /* `(raise FACTOR)'. */
2433 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
2434 return 0;
2435
fb3842a8 2436#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
2437 value = XCAR (XCDR (prop));
2438 if (NUMBERP (value))
2439 {
2440 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2441 it->voffset = - (XFLOATINT (value)
1ab3e082 2442 * (FONT_HEIGHT (face->font)));
5f5c8ee5
GM
2443 }
2444#endif /* HAVE_WINDOW_SYSTEM */
2445 }
2446 else if (!it->string_from_display_prop_p)
2447 {
f3751a65
GM
2448 /* `((margin left-margin) VALUE)' or `((margin right-margin)
2449 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
2450 Lisp_Object location, value;
2451 struct text_pos start_pos;
2452 int valid_p;
2453
2454 /* Characters having this form of property are not displayed, so
2455 we have to find the end of the property. */
2456 space_or_image_found_p = 1;
2457 start_pos = *position;
2458 *position = display_prop_end (it, object, start_pos);
2459
2460 /* Let's stop at the new position and assume that all
2461 text properties change there. */
2462 it->stop_charpos = position->charpos;
2463
f3751a65
GM
2464 location = Qunbound;
2465 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 2466 {
f3751a65
GM
2467 Lisp_Object tem;
2468
5f5c8ee5 2469 value = XCDR (prop);
f3751a65
GM
2470 if (CONSP (value))
2471 value = XCAR (value);
2472
2473 tem = XCAR (prop);
2474 if (EQ (XCAR (tem), Qmargin)
2475 && (tem = XCDR (tem),
2476 tem = CONSP (tem) ? XCAR (tem) : Qnil,
2477 (NILP (tem)
2478 || EQ (tem, Qleft_margin)
2479 || EQ (tem, Qright_margin))))
2480 location = tem;
5f5c8ee5 2481 }
f3751a65
GM
2482
2483 if (EQ (location, Qunbound))
5f5c8ee5
GM
2484 {
2485 location = Qnil;
2486 value = prop;
2487 }
2488
2489#ifdef HAVE_WINDOW_SYSTEM
fb3842a8 2490 if (FRAME_TERMCAP_P (it->f))
5f5c8ee5
GM
2491 valid_p = STRINGP (value);
2492 else
2493 valid_p = (STRINGP (value)
2494 || (CONSP (value) && EQ (XCAR (value), Qspace))
2495 || valid_image_p (value));
2496#else /* not HAVE_WINDOW_SYSTEM */
2497 valid_p = STRINGP (value);
2498#endif /* not HAVE_WINDOW_SYSTEM */
2499
2500 if ((EQ (location, Qleft_margin)
2501 || EQ (location, Qright_margin)
2502 || NILP (location))
2503 && valid_p)
2504 {
2505 /* Save current settings of IT so that we can restore them
2506 when we are finished with the glyph property value. */
2507 push_it (it);
2508
2509 if (NILP (location))
2510 it->area = TEXT_AREA;
2511 else if (EQ (location, Qleft_margin))
2512 it->area = LEFT_MARGIN_AREA;
2513 else
2514 it->area = RIGHT_MARGIN_AREA;
2515
2516 if (STRINGP (value))
2517 {
2518 it->string = value;
2519 it->multibyte_p = STRING_MULTIBYTE (it->string);
2520 it->current.overlay_string_index = -1;
2521 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2522 it->end_charpos = it->string_nchars
2523 = XSTRING (it->string)->size;
2524 it->method = next_element_from_string;
2525 it->stop_charpos = 0;
2526 it->string_from_display_prop_p = 1;
2527 }
2528 else if (CONSP (value) && EQ (XCAR (value), Qspace))
2529 {
2530 it->method = next_element_from_stretch;
2531 it->object = value;
2532 it->current.pos = it->position = start_pos;
2533 }
2534#ifdef HAVE_WINDOW_SYSTEM
2535 else
2536 {
2537 it->what = IT_IMAGE;
2538 it->image_id = lookup_image (it->f, value);
2539 it->position = start_pos;
2540 it->object = NILP (object) ? it->w->buffer : object;
2541 it->method = next_element_from_image;
2542
2543 /* Say that we don't have consumed the characters with
2544 `display' property yet. The call to pop_it in
2545 set_iterator_to_next will clean this up. */
2546 *position = start_pos;
2547 }
2548#endif /* HAVE_WINDOW_SYSTEM */
2549 }
2550 }
2551
2552 return space_or_image_found_p;
2553}
2554
2555
2556\f
260a86a0
KH
2557/***********************************************************************
2558 `composition' property
2559 ***********************************************************************/
2560
2561/* Set up iterator IT from `composition' property at its current
2562 position. Called from handle_stop. */
2563
2564static enum prop_handled
2565handle_composition_prop (it)
2566 struct it *it;
2567{
2568 Lisp_Object prop, string;
2569 int pos, pos_byte, end;
2570 enum prop_handled handled = HANDLED_NORMALLY;
2571
2572 if (STRINGP (it->string))
2573 {
2574 pos = IT_STRING_CHARPOS (*it);
2575 pos_byte = IT_STRING_BYTEPOS (*it);
2576 string = it->string;
2577 }
2578 else
2579 {
2580 pos = IT_CHARPOS (*it);
2581 pos_byte = IT_BYTEPOS (*it);
2582 string = Qnil;
2583 }
2584
2585 /* If there's a valid composition and point is not inside of the
2586 composition (in the case that the composition is from the current
2587 buffer), draw a glyph composed from the composition components. */
2588 if (find_composition (pos, -1, &pos, &end, &prop, string)
2589 && COMPOSITION_VALID_P (pos, end, prop)
2590 && (STRINGP (it->string) || (PT <= pos || PT >= end)))
2591 {
2592 int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
2593
2594 if (id >= 0)
2595 {
2596 it->method = next_element_from_composition;
2597 it->cmp_id = id;
2598 it->cmp_len = COMPOSITION_LENGTH (prop);
2599 /* For a terminal, draw only the first character of the
2600 components. */
2601 it->c = COMPOSITION_GLYPH (composition_table[id], 0);
2602 it->len = (STRINGP (it->string)
2603 ? string_char_to_byte (it->string, end)
2604 : CHAR_TO_BYTE (end)) - pos_byte;
2605 it->stop_charpos = end;
2606 handled = HANDLED_RETURN;
2607 }
2608 }
2609
2610 return handled;
2611}
2612
2613
2614\f
5f5c8ee5
GM
2615/***********************************************************************
2616 Overlay strings
2617 ***********************************************************************/
2618
2619/* The following structure is used to record overlay strings for
2620 later sorting in load_overlay_strings. */
2621
2622struct overlay_entry
2623{
2624 Lisp_Object string;
2625 int priority;
2626 int after_string_p;
2627};
2628
2629
2630/* Set up iterator IT from overlay strings at its current position.
2631 Called from handle_stop. */
2632
2633static enum prop_handled
2634handle_overlay_change (it)
2635 struct it *it;
2636{
2637 /* Overlays are handled in current_buffer only. */
2638 if (STRINGP (it->string))
2639 return HANDLED_NORMALLY;
2640 else
2641 return (get_overlay_strings (it)
2642 ? HANDLED_RECOMPUTE_PROPS
2643 : HANDLED_NORMALLY);
2644}
2645
2646
2647/* Set up the next overlay string for delivery by IT, if there is an
2648 overlay string to deliver. Called by set_iterator_to_next when the
2649 end of the current overlay string is reached. If there are more
2650 overlay strings to display, IT->string and
2651 IT->current.overlay_string_index are set appropriately here.
2652 Otherwise IT->string is set to nil. */
2653
2654static void
2655next_overlay_string (it)
2656 struct it *it;
2657{
2658 ++it->current.overlay_string_index;
2659 if (it->current.overlay_string_index == it->n_overlay_strings)
2660 {
2661 /* No more overlay strings. Restore IT's settings to what
2662 they were before overlay strings were processed, and
2663 continue to deliver from current_buffer. */
2664 pop_it (it);
2665 xassert (it->stop_charpos >= BEGV
2666 && it->stop_charpos <= it->end_charpos);
2667 it->string = Qnil;
2668 it->current.overlay_string_index = -1;
2669 SET_TEXT_POS (it->current.string_pos, -1, -1);
2670 it->n_overlay_strings = 0;
2671 it->method = next_element_from_buffer;
2672 }
2673 else
2674 {
2675 /* There are more overlay strings to process. If
2676 IT->current.overlay_string_index has advanced to a position
2677 where we must load IT->overlay_strings with more strings, do
2678 it. */
2679 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2680
2681 if (it->current.overlay_string_index && i == 0)
2682 load_overlay_strings (it);
2683
2684 /* Initialize IT to deliver display elements from the overlay
2685 string. */
2686 it->string = it->overlay_strings[i];
2687 it->multibyte_p = STRING_MULTIBYTE (it->string);
2688 SET_TEXT_POS (it->current.string_pos, 0, 0);
2689 it->method = next_element_from_string;
2690 it->stop_charpos = 0;
2691 }
2692
2693 CHECK_IT (it);
2694}
2695
2696
2697/* Compare two overlay_entry structures E1 and E2. Used as a
2698 comparison function for qsort in load_overlay_strings. Overlay
2699 strings for the same position are sorted so that
2700
2701 1. All after-strings come in front of before-strings.
2702
2703 2. Within after-strings, strings are sorted so that overlay strings
2704 from overlays with higher priorities come first.
2705
2706 2. Within before-strings, strings are sorted so that overlay
2707 strings from overlays with higher priorities come last.
2708
2709 Value is analogous to strcmp. */
2710
2711
2712static int
2713compare_overlay_entries (e1, e2)
2714 void *e1, *e2;
2715{
2716 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
2717 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
2718 int result;
2719
2720 if (entry1->after_string_p != entry2->after_string_p)
2721 /* Let after-strings appear in front of before-strings. */
2722 result = entry1->after_string_p ? -1 : 1;
2723 else if (entry1->after_string_p)
2724 /* After-strings sorted in order of decreasing priority. */
2725 result = entry2->priority - entry1->priority;
2726 else
2727 /* Before-strings sorted in order of increasing priority. */
2728 result = entry1->priority - entry2->priority;
2729
2730 return result;
2731}
2732
2733
2734/* Load the vector IT->overlay_strings with overlay strings from IT's
2735 current buffer position. Set IT->n_overlays to the total number of
2736 overlay strings found.
2737
2738 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
2739 a time. On entry into load_overlay_strings,
2740 IT->current.overlay_string_index gives the number of overlay
2741 strings that have already been loaded by previous calls to this
2742 function.
2743
2744 Overlay strings are sorted so that after-string strings come in
2745 front of before-string strings. Within before and after-strings,
2746 strings are sorted by overlay priority. See also function
2747 compare_overlay_entries. */
2748
2749static void
2750load_overlay_strings (it)
2751 struct it *it;
2752{
2753 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
2754 Lisp_Object ov, overlay, window, str;
2755 int start, end;
2756 int size = 20;
2757 int n = 0, i, j;
2758 struct overlay_entry *entries
2759 = (struct overlay_entry *) alloca (size * sizeof *entries);
2760
2761 /* Append the overlay string STRING of overlay OVERLAY to vector
2762 `entries' which has size `size' and currently contains `n'
2763 elements. AFTER_P non-zero means STRING is an after-string of
2764 OVERLAY. */
2765#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
2766 do \
2767 { \
2768 Lisp_Object priority; \
2769 \
2770 if (n == size) \
2771 { \
2772 int new_size = 2 * size; \
2773 struct overlay_entry *old = entries; \
2774 entries = \
2775 (struct overlay_entry *) alloca (new_size \
2776 * sizeof *entries); \
2777 bcopy (old, entries, size * sizeof *entries); \
2778 size = new_size; \
2779 } \
2780 \
2781 entries[n].string = (STRING); \
2782 priority = Foverlay_get ((OVERLAY), Qpriority); \
2783 entries[n].priority \
2784 = INTEGERP (priority) ? XFASTINT (priority) : 0; \
2785 entries[n].after_string_p = (AFTER_P); \
2786 ++n; \
2787 } \
2788 while (0)
2789
2790 /* Process overlay before the overlay center. */
2791 for (ov = current_buffer->overlays_before;
2792 CONSP (ov);
9472f927 2793 ov = XCDR (ov))
5f5c8ee5 2794 {
9472f927 2795 overlay = XCAR (ov);
5f5c8ee5
GM
2796 xassert (OVERLAYP (overlay));
2797 start = OVERLAY_POSITION (OVERLAY_START (overlay));
2798 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2799
2800 if (end < IT_CHARPOS (*it))
2801 break;
2802
2803 /* Skip this overlay if it doesn't start or end at IT's current
2804 position. */
2805 if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
2806 continue;
2807
2808 /* Skip this overlay if it doesn't apply to IT->w. */
2809 window = Foverlay_get (overlay, Qwindow);
2810 if (WINDOWP (window) && XWINDOW (window) != it->w)
2811 continue;
2812
2813 /* If overlay has a non-empty before-string, record it. */
2814 if (start == IT_CHARPOS (*it)
2815 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2816 && XSTRING (str)->size)
2817 RECORD_OVERLAY_STRING (overlay, str, 0);
2818
2819 /* If overlay has a non-empty after-string, record it. */
2820 if (end == IT_CHARPOS (*it)
2821 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2822 && XSTRING (str)->size)
2823 RECORD_OVERLAY_STRING (overlay, str, 1);
2824 }
2825
2826 /* Process overlays after the overlay center. */
2827 for (ov = current_buffer->overlays_after;
2828 CONSP (ov);
9472f927 2829 ov = XCDR (ov))
5f5c8ee5 2830 {
9472f927 2831 overlay = XCAR (ov);
5f5c8ee5
GM
2832 xassert (OVERLAYP (overlay));
2833 start = OVERLAY_POSITION (OVERLAY_START (overlay));
2834 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2835
2836 if (start > IT_CHARPOS (*it))
2837 break;
2838
2839 /* Skip this overlay if it doesn't start or end at IT's current
2840 position. */
2841 if (end != IT_CHARPOS (*it) && start != IT_CHARPOS (*it))
2842 continue;
2843
2844 /* Skip this overlay if it doesn't apply to IT->w. */
2845 window = Foverlay_get (overlay, Qwindow);
2846 if (WINDOWP (window) && XWINDOW (window) != it->w)
2847 continue;
2848
2849 /* If overlay has a non-empty before-string, record it. */
2850 if (start == IT_CHARPOS (*it)
2851 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2852 && XSTRING (str)->size)
2853 RECORD_OVERLAY_STRING (overlay, str, 0);
2854
2855 /* If overlay has a non-empty after-string, record it. */
2856 if (end == IT_CHARPOS (*it)
2857 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2858 && XSTRING (str)->size)
2859 RECORD_OVERLAY_STRING (overlay, str, 1);
2860 }
2861
2862#undef RECORD_OVERLAY_STRING
2863
2864 /* Sort entries. */
2865 qsort (entries, n, sizeof *entries, compare_overlay_entries);
2866
2867 /* Record the total number of strings to process. */
2868 it->n_overlay_strings = n;
2869
2870 /* IT->current.overlay_string_index is the number of overlay strings
2871 that have already been consumed by IT. Copy some of the
2872 remaining overlay strings to IT->overlay_strings. */
2873 i = 0;
2874 j = it->current.overlay_string_index;
2875 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
2876 it->overlay_strings[i++] = entries[j++].string;
2877
2878 CHECK_IT (it);
2879}
2880
2881
2882/* Get the first chunk of overlay strings at IT's current buffer
2883 position. Value is non-zero if at least one overlay string was
2884 found. */
2885
2886static int
2887get_overlay_strings (it)
2888 struct it *it;
2889{
2890 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
2891 process. This fills IT->overlay_strings with strings, and sets
2892 IT->n_overlay_strings to the total number of strings to process.
2893 IT->pos.overlay_string_index has to be set temporarily to zero
2894 because load_overlay_strings needs this; it must be set to -1
2895 when no overlay strings are found because a zero value would
2896 indicate a position in the first overlay string. */
2897 it->current.overlay_string_index = 0;
2898 load_overlay_strings (it);
2899
2900 /* If we found overlay strings, set up IT to deliver display
2901 elements from the first one. Otherwise set up IT to deliver
2902 from current_buffer. */
2903 if (it->n_overlay_strings)
2904 {
2905 /* Make sure we know settings in current_buffer, so that we can
2906 restore meaningful values when we're done with the overlay
2907 strings. */
2908 compute_stop_pos (it);
2909 xassert (it->face_id >= 0);
2910
2911 /* Save IT's settings. They are restored after all overlay
2912 strings have been processed. */
2913 xassert (it->sp == 0);
2914 push_it (it);
2915
2916 /* Set up IT to deliver display elements from the first overlay
2917 string. */
2918 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2919 it->stop_charpos = 0;
2920 it->string = it->overlay_strings[0];
2921 it->multibyte_p = STRING_MULTIBYTE (it->string);
2922 xassert (STRINGP (it->string));
2923 it->method = next_element_from_string;
2924 }
2925 else
2926 {
2927 it->string = Qnil;
2928 it->current.overlay_string_index = -1;
2929 it->method = next_element_from_buffer;
2930 }
2931
2932 CHECK_IT (it);
2933
2934 /* Value is non-zero if we found at least one overlay string. */
2935 return STRINGP (it->string);
2936}
2937
2938
2939\f
2940/***********************************************************************
2941 Saving and restoring state
2942 ***********************************************************************/
2943
2944/* Save current settings of IT on IT->stack. Called, for example,
2945 before setting up IT for an overlay string, to be able to restore
2946 IT's settings to what they were after the overlay string has been
2947 processed. */
2948
2949static void
2950push_it (it)
2951 struct it *it;
2952{
2953 struct iterator_stack_entry *p;
2954
2955 xassert (it->sp < 2);
2956 p = it->stack + it->sp;
2957
2958 p->stop_charpos = it->stop_charpos;
2959 xassert (it->face_id >= 0);
2960 p->face_id = it->face_id;
2961 p->string = it->string;
2962 p->pos = it->current;
2963 p->end_charpos = it->end_charpos;
2964 p->string_nchars = it->string_nchars;
2965 p->area = it->area;
2966 p->multibyte_p = it->multibyte_p;
2967 p->space_width = it->space_width;
2968 p->font_height = it->font_height;
2969 p->voffset = it->voffset;
2970 p->string_from_display_prop_p = it->string_from_display_prop_p;
2971 ++it->sp;
2972}
2973
2974
2975/* Restore IT's settings from IT->stack. Called, for example, when no
2976 more overlay strings must be processed, and we return to delivering
2977 display elements from a buffer, or when the end of a string from a
2978 `display' property is reached and we return to delivering display
2979 elements from an overlay string, or from a buffer. */
2980
2981static void
2982pop_it (it)
2983 struct it *it;
2984{
2985 struct iterator_stack_entry *p;
2986
2987 xassert (it->sp > 0);
2988 --it->sp;
2989 p = it->stack + it->sp;
2990 it->stop_charpos = p->stop_charpos;
2991 it->face_id = p->face_id;
2992 it->string = p->string;
2993 it->current = p->pos;
2994 it->end_charpos = p->end_charpos;
2995 it->string_nchars = p->string_nchars;
2996 it->area = p->area;
2997 it->multibyte_p = p->multibyte_p;
2998 it->space_width = p->space_width;
2999 it->font_height = p->font_height;
3000 it->voffset = p->voffset;
3001 it->string_from_display_prop_p = p->string_from_display_prop_p;
3002}
3003
3004
3005\f
3006/***********************************************************************
3007 Moving over lines
3008 ***********************************************************************/
3009
3010/* Set IT's current position to the previous line start. */
3011
3012static void
3013back_to_previous_line_start (it)
3014 struct it *it;
3015{
3016 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
3017 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3018}
3019
3020
3021/* Set IT's current position to the next line start. */
3022
3023static void
3024forward_to_next_line_start (it)
3025 struct it *it;
3026{
3027 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it), 1);
3028 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3029}
3030
3031
3032/* Set IT's current position to the previous visible line start. Skip
3033 invisible text that is so either due to text properties or due to
3034 selective display. Caution: this does not change IT->current_x and
3035 IT->hpos. */
3036
3037static void
3038back_to_previous_visible_line_start (it)
3039 struct it *it;
3040{
3041 int visible_p = 0;
3042
3043 /* Go back one newline if not on BEGV already. */
3044 if (IT_CHARPOS (*it) > BEGV)
3045 back_to_previous_line_start (it);
3046
3047 /* Move over lines that are invisible because of selective display
3048 or text properties. */
3049 while (IT_CHARPOS (*it) > BEGV
3050 && !visible_p)
3051 {
3052 visible_p = 1;
3053
3054 /* If selective > 0, then lines indented more than that values
3055 are invisible. */
3056 if (it->selective > 0
3057 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3058 it->selective))
3059 visible_p = 0;
5f5c8ee5
GM
3060 else
3061 {
3062 Lisp_Object prop;
3063
3064 prop = Fget_char_property (IT_CHARPOS (*it), Qinvisible, it->window);
3065 if (TEXT_PROP_MEANS_INVISIBLE (prop))
3066 visible_p = 0;
3067 }
5f5c8ee5
GM
3068
3069 /* Back one more newline if the current one is invisible. */
3070 if (!visible_p)
3071 back_to_previous_line_start (it);
3072 }
3073
3074 xassert (IT_CHARPOS (*it) >= BEGV);
3075 xassert (IT_CHARPOS (*it) == BEGV
3076 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3077 CHECK_IT (it);
3078}
3079
3080
3081/* Reseat iterator IT at the previous visible line start. Skip
3082 invisible text that is so either due to text properties or due to
3083 selective display. At the end, update IT's overlay information,
3084 face information etc. */
3085
3086static void
3087reseat_at_previous_visible_line_start (it)
3088 struct it *it;
3089{
3090 back_to_previous_visible_line_start (it);
3091 reseat (it, it->current.pos, 1);
3092 CHECK_IT (it);
3093}
3094
3095
3096/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
3097 buffer. ON_NEWLINE_P non-zero means position IT on the newline
3098 preceding the line start. Skip over invisible text that is so
3099 because of selective display. Compute faces, overlays etc at the
3100 new position. Note that this function does not skip over text that
3101 is invisible because of text properties. */
5f5c8ee5
GM
3102
3103static void
312246d1 3104reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 3105 struct it *it;
312246d1 3106 int on_newline_p;
5f5c8ee5
GM
3107{
3108 /* Restore the buffer position when currently not delivering display
3109 elements from the current buffer. This is the case, for example,
3110 when called at the end of a truncated overlay string. */
3111 while (it->sp)
3112 pop_it (it);
3113 it->method = next_element_from_buffer;
3114
3115 /* Otherwise, scan_buffer would not work. */
3116 if (IT_CHARPOS (*it) < ZV)
3117 {
3118 /* If on a newline, advance past it. Otherwise, find the next
3119 newline which automatically gives us the position following
3120 the newline. */
3121 if (FETCH_BYTE (IT_BYTEPOS (*it)) == '\n')
3122 {
3123 ++IT_CHARPOS (*it);
3124 ++IT_BYTEPOS (*it);
3125 }
3126 else
3127 forward_to_next_line_start (it);
3128
3129 /* We must either have reached the end of the buffer or end up
3130 after a newline. */
3131 xassert (IT_CHARPOS (*it) == ZV
3132 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
3133
3134 /* Skip over lines that are invisible because they are indented
3135 more than the value of IT->selective. */
3136 if (it->selective > 0)
3137 while (IT_CHARPOS (*it) < ZV
3138 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
3139 it->selective))
3140 forward_to_next_line_start (it);
312246d1
GM
3141
3142 /* Position on the newline if we should. */
13f19968
GM
3143 if (on_newline_p
3144 && IT_CHARPOS (*it) > BEGV
3145 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n')
312246d1
GM
3146 {
3147 --IT_CHARPOS (*it);
3148 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
3149 }
5f5c8ee5
GM
3150
3151 /* Set the iterator there. The 0 as the last parameter of
3152 reseat means don't force a text property lookup. The lookup
3153 is then only done if we've skipped past the iterator's
3154 check_charpos'es. This optimization is important because
3155 text property lookups tend to be expensive. */
3156 reseat (it, it->current.pos, 0);
3157 }
3158
3159 CHECK_IT (it);
3160}
3161
3162
3163\f
3164/***********************************************************************
3165 Changing an iterator's position
3166***********************************************************************/
3167
3168/* Change IT's current position to POS in current_buffer. If FORCE_P
3169 is non-zero, always check for text properties at the new position.
3170 Otherwise, text properties are only looked up if POS >=
3171 IT->check_charpos of a property. */
3172
3173static void
3174reseat (it, pos, force_p)
3175 struct it *it;
3176 struct text_pos pos;
3177 int force_p;
3178{
3179 int original_pos = IT_CHARPOS (*it);
3180
3181 reseat_1 (it, pos, 0);
3182
3183 /* Determine where to check text properties. Avoid doing it
3184 where possible because text property lookup is very expensive. */
3185 if (force_p
3186 || CHARPOS (pos) > it->stop_charpos
3187 || CHARPOS (pos) < original_pos)
3188 handle_stop (it);
3189
3190 CHECK_IT (it);
3191}
3192
3193
3194/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
3195 IT->stop_pos to POS, also. */
3196
3197static void
3198reseat_1 (it, pos, set_stop_p)
3199 struct it *it;
3200 struct text_pos pos;
3201 int set_stop_p;
3202{
3203 /* Don't call this function when scanning a C string. */
3204 xassert (it->s == NULL);
3205
3206 /* POS must be a reasonable value. */
3207 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
3208
3209 it->current.pos = it->position = pos;
3210 XSETBUFFER (it->object, current_buffer);
3211 it->dpvec = NULL;
3212 it->current.dpvec_index = -1;
3213 it->current.overlay_string_index = -1;
3214 IT_STRING_CHARPOS (*it) = -1;
3215 IT_STRING_BYTEPOS (*it) = -1;
3216 it->string = Qnil;
3217 it->method = next_element_from_buffer;
3218 it->sp = 0;
3219
3220 if (set_stop_p)
3221 it->stop_charpos = CHARPOS (pos);
3222}
3223
3224
3225/* Set up IT for displaying a string, starting at CHARPOS in window W.
3226 If S is non-null, it is a C string to iterate over. Otherwise,
3227 STRING gives a Lisp string to iterate over.
3228
3229 If PRECISION > 0, don't return more then PRECISION number of
3230 characters from the string.
3231
3232 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
3233 characters have been returned. FIELD_WIDTH < 0 means an infinite
3234 field width.
3235
3236 MULTIBYTE = 0 means disable processing of multibyte characters,
3237 MULTIBYTE > 0 means enable it,
3238 MULTIBYTE < 0 means use IT->multibyte_p.
3239
3240 IT must be initialized via a prior call to init_iterator before
3241 calling this function. */
3242
3243static void
3244reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
3245 struct it *it;
3246 unsigned char *s;
3247 Lisp_Object string;
3248 int charpos;
3249 int precision, field_width, multibyte;
3250{
3251 /* No region in strings. */
3252 it->region_beg_charpos = it->region_end_charpos = -1;
3253
3254 /* No text property checks performed by default, but see below. */
3255 it->stop_charpos = -1;
3256
3257 /* Set iterator position and end position. */
3258 bzero (&it->current, sizeof it->current);
3259 it->current.overlay_string_index = -1;
3260 it->current.dpvec_index = -1;
3261 it->charset = CHARSET_ASCII;
3262 xassert (charpos >= 0);
3263
3264 /* Use the setting of MULTIBYTE if specified. */
3265 if (multibyte >= 0)
3266 it->multibyte_p = multibyte > 0;
3267
3268 if (s == NULL)
3269 {
3270 xassert (STRINGP (string));
3271 it->string = string;
3272 it->s = NULL;
3273 it->end_charpos = it->string_nchars = XSTRING (string)->size;
3274 it->method = next_element_from_string;
3275 it->current.string_pos = string_pos (charpos, string);
3276 }
3277 else
3278 {
3279 it->s = s;
3280 it->string = Qnil;
3281
3282 /* Note that we use IT->current.pos, not it->current.string_pos,
3283 for displaying C strings. */
3284 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3285 if (it->multibyte_p)
3286 {
3287 it->current.pos = c_string_pos (charpos, s, 1);
3288 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
3289 }
3290 else
3291 {
3292 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
3293 it->end_charpos = it->string_nchars = strlen (s);
3294 }
3295
3296 it->method = next_element_from_c_string;
3297 }
3298
3299 /* PRECISION > 0 means don't return more than PRECISION characters
3300 from the string. */
3301 if (precision > 0 && it->end_charpos - charpos > precision)
3302 it->end_charpos = it->string_nchars = charpos + precision;
3303
3304 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
3305 characters have been returned. FIELD_WIDTH == 0 means don't pad,
3306 FIELD_WIDTH < 0 means infinite field width. This is useful for
3307 padding with `-' at the end of a mode line. */
3308 if (field_width < 0)
3309 field_width = INFINITY;
3310 if (field_width > it->end_charpos - charpos)
3311 it->end_charpos = charpos + field_width;
3312
3313 /* Use the standard display table for displaying strings. */
3314 if (DISP_TABLE_P (Vstandard_display_table))
3315 it->dp = XCHAR_TABLE (Vstandard_display_table);
3316
3317 it->stop_charpos = charpos;
3318 CHECK_IT (it);
3319}
3320
3321
3322\f
3323/***********************************************************************
3324 Iteration
3325 ***********************************************************************/
3326
3327/* Load IT's display element fields with information about the next
3328 display element from the current position of IT. Value is zero if
3329 end of buffer (or C string) is reached. */
3330
3331int
3332get_next_display_element (it)
3333 struct it *it;
3334{
3335 /* Non-zero means that we found an display element. Zero means that
3336 we hit the end of what we iterate over. Performance note: the
3337 function pointer `method' used here turns out to be faster than
3338 using a sequence of if-statements. */
3339 int success_p = (*it->method) (it);
3340 int charset;
3341
3342 if (it->what == IT_CHARACTER)
3343 {
3344 /* Map via display table or translate control characters.
3345 IT->c, IT->len etc. have been set to the next character by
3346 the function call above. If we have a display table, and it
3347 contains an entry for IT->c, translate it. Don't do this if
3348 IT->c itself comes from a display table, otherwise we could
3349 end up in an infinite recursion. (An alternative could be to
3350 count the recursion depth of this function and signal an
3351 error when a certain maximum depth is reached.) Is it worth
3352 it? */
3353 if (success_p && it->dpvec == NULL)
3354 {
3355 Lisp_Object dv;
3356
3357 if (it->dp
3358 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
3359 VECTORP (dv)))
3360 {
3361 struct Lisp_Vector *v = XVECTOR (dv);
3362
3363 /* Return the first character from the display table
3364 entry, if not empty. If empty, don't display the
3365 current character. */
3366 if (v->size)
3367 {
3368 it->dpvec_char_len = it->len;
3369 it->dpvec = v->contents;
3370 it->dpend = v->contents + v->size;
3371 it->current.dpvec_index = 0;
3372 it->method = next_element_from_display_vector;
3373 }
3374
3375 success_p = get_next_display_element (it);
3376 }
3377
3378 /* Translate control characters into `\003' or `^C' form.
3379 Control characters coming from a display table entry are
3380 currently not translated because we use IT->dpvec to hold
3381 the translation. This could easily be changed but I
197516c2
KH
3382 don't believe that it is worth doing.
3383
3384 Non-printable multibyte characters are also translated
3385 octal form. */
5f5c8ee5
GM
3386 else if ((it->c < ' '
3387 && (it->area != TEXT_AREA
c6e89d6c 3388 || (it->c != '\n' && it->c != '\t')))
54c85a23 3389 || (it->c >= 127
197516c2
KH
3390 && it->len == 1)
3391 || !CHAR_PRINTABLE_P (it->c))
5f5c8ee5
GM
3392 {
3393 /* IT->c is a control character which must be displayed
3394 either as '\003' or as `^C' where the '\\' and '^'
3395 can be defined in the display table. Fill
3396 IT->ctl_chars with glyphs for what we have to
3397 display. Then, set IT->dpvec to these glyphs. */
3398 GLYPH g;
3399
54c85a23 3400 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
3401 {
3402 /* Set IT->ctl_chars[0] to the glyph for `^'. */
3403 if (it->dp
3404 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
3405 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
3406 g = XINT (DISP_CTRL_GLYPH (it->dp));
3407 else
3408 g = FAST_MAKE_GLYPH ('^', 0);
3409 XSETINT (it->ctl_chars[0], g);
3410
3411 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
3412 XSETINT (it->ctl_chars[1], g);
3413
3414 /* Set up IT->dpvec and return first character from it. */
3415 it->dpvec_char_len = it->len;
3416 it->dpvec = it->ctl_chars;
3417 it->dpend = it->dpvec + 2;
3418 it->current.dpvec_index = 0;
3419 it->method = next_element_from_display_vector;
3420 get_next_display_element (it);
3421 }
3422 else
3423 {
260a86a0
KH
3424 unsigned char str[MAX_MULTIBYTE_LENGTH];
3425 int len = CHAR_STRING (it->c, str);
197516c2
KH
3426 int i;
3427 GLYPH escape_glyph;
3428
5f5c8ee5
GM
3429 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
3430 if (it->dp
3431 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
3432 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 3433 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 3434 else
197516c2
KH
3435 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
3436
3437 for (i = 0; i < len; i++)
3438 {
3439 XSETINT (it->ctl_chars[i * 4], escape_glyph);
3440 /* Insert three more glyphs into IT->ctl_chars for
3441 the octal display of the character. */
3442 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
3443 XSETINT (it->ctl_chars[i * 4 + 1], g);
3444 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
3445 XSETINT (it->ctl_chars[i * 4 + 2], g);
3446 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
3447 XSETINT (it->ctl_chars[i * 4 + 3], g);
3448 }
5f5c8ee5
GM
3449
3450 /* Set up IT->dpvec and return the first character
3451 from it. */
3452 it->dpvec_char_len = it->len;
3453 it->dpvec = it->ctl_chars;
197516c2 3454 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
3455 it->current.dpvec_index = 0;
3456 it->method = next_element_from_display_vector;
3457 get_next_display_element (it);
3458 }
3459 }
3460 }
3461
3462 /* Adjust face id if charset changes. There are no charset
3463 changes in unibyte text because Emacs' charsets are not
3464 applicable there. */
3465 if (it->multibyte_p
3466 && success_p
3467 && (charset = CHAR_CHARSET (it->c),
3468 charset != it->charset))
3469 {
3470 it->charset = charset;
3471 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, charset);
3472 }
3473 }
3474
3475 /* Is this character the last one of a run of characters with
3476 box? If yes, set IT->end_of_box_run_p to 1. */
3477 if (it->face_box_p
3478 && it->s == NULL)
3479 {
3480 int face_id;
3481 struct face *face;
3482
3483 it->end_of_box_run_p
3484 = ((face_id = face_after_it_pos (it),
3485 face_id != it->face_id)
3486 && (face = FACE_FROM_ID (it->f, face_id),
3487 face->box == FACE_NO_BOX));
3488 }
3489
3490 /* Value is 0 if end of buffer or string reached. */
3491 return success_p;
3492}
3493
3494
3495/* Move IT to the next display element.
3496
3497 Functions get_next_display_element and set_iterator_to_next are
3498 separate because I find this arrangement easier to handle than a
3499 get_next_display_element function that also increments IT's
3500 position. The way it is we can first look at an iterator's current
3501 display element, decide whether it fits on a line, and if it does,
3502 increment the iterator position. The other way around we probably
3503 would either need a flag indicating whether the iterator has to be
3504 incremented the next time, or we would have to implement a
3505 decrement position function which would not be easy to write. */
3506
3507void
3508set_iterator_to_next (it)
3509 struct it *it;
3510{
3511 if (it->method == next_element_from_buffer)
3512 {
3513 /* The current display element of IT is a character from
3514 current_buffer. Advance in the buffer, and maybe skip over
3515 invisible lines that are so because of selective display. */
3516 if (ITERATOR_AT_END_OF_LINE_P (it))
312246d1 3517 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
3518 else
3519 {
3520 xassert (it->len != 0);
3521 IT_BYTEPOS (*it) += it->len;
3522 IT_CHARPOS (*it) += 1;
3523 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
3524 }
3525 }
260a86a0
KH
3526 else if (it->method == next_element_from_composition)
3527 {
3528 xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
3529 if (STRINGP (it->string))
3530 {
3531 IT_STRING_BYTEPOS (*it) += it->len;
3532 IT_STRING_CHARPOS (*it) += it->cmp_len;
3533 it->method = next_element_from_string;
3534 goto consider_string_end;
3535 }
3536 else
3537 {
3538 IT_BYTEPOS (*it) += it->len;
3539 IT_CHARPOS (*it) += it->cmp_len;
3540 it->method = next_element_from_buffer;
3541 }
3542 }
5f5c8ee5
GM
3543 else if (it->method == next_element_from_c_string)
3544 {
3545 /* Current display element of IT is from a C string. */
3546 IT_BYTEPOS (*it) += it->len;
3547 IT_CHARPOS (*it) += 1;
3548 }
3549 else if (it->method == next_element_from_display_vector)
3550 {
3551 /* Current display element of IT is from a display table entry.
3552 Advance in the display table definition. Reset it to null if
3553 end reached, and continue with characters from buffers/
3554 strings. */
3555 ++it->current.dpvec_index;
286bcbc9
GM
3556
3557 /* Restore face and charset of the iterator to what they were
3558 before the display vector entry (these entries may contain
3559 faces, and of course characters of different charsets). */
5f5c8ee5 3560 it->face_id = it->saved_face_id;
286bcbc9
GM
3561 it->charset = FACE_FROM_ID (it->f, it->face_id)->charset;
3562
5f5c8ee5
GM
3563 if (it->dpvec + it->current.dpvec_index == it->dpend)
3564 {
3565 if (it->s)
3566 it->method = next_element_from_c_string;
3567 else if (STRINGP (it->string))
3568 it->method = next_element_from_string;
3569 else
3570 it->method = next_element_from_buffer;
3571
3572 it->dpvec = NULL;
3573 it->current.dpvec_index = -1;
3574
312246d1
GM
3575 /* Skip over characters which were displayed via IT->dpvec. */
3576 if (it->dpvec_char_len < 0)
3577 reseat_at_next_visible_line_start (it, 1);
3578 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
3579 {
3580 it->len = it->dpvec_char_len;
3581 set_iterator_to_next (it);
3582 }
3583 }
3584 }
3585 else if (it->method == next_element_from_string)
3586 {
3587 /* Current display element is a character from a Lisp string. */
3588 xassert (it->s == NULL && STRINGP (it->string));
3589 IT_STRING_BYTEPOS (*it) += it->len;
3590 IT_STRING_CHARPOS (*it) += 1;
3591
3592 consider_string_end:
3593
3594 if (it->current.overlay_string_index >= 0)
3595 {
3596 /* IT->string is an overlay string. Advance to the
3597 next, if there is one. */
3598 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3599 next_overlay_string (it);
3600 }
3601 else
3602 {
3603 /* IT->string is not an overlay string. If we reached
3604 its end, and there is something on IT->stack, proceed
3605 with what is on the stack. This can be either another
3606 string, this time an overlay string, or a buffer. */
3607 if (IT_STRING_CHARPOS (*it) == XSTRING (it->string)->size
3608 && it->sp > 0)
3609 {
3610 pop_it (it);
3611 if (!STRINGP (it->string))
3612 it->method = next_element_from_buffer;
3613 }
3614 }
3615 }
3616 else if (it->method == next_element_from_image
3617 || it->method == next_element_from_stretch)
3618 {
3619 /* The position etc with which we have to proceed are on
3620 the stack. The position may be at the end of a string,
3621 if the `display' property takes up the whole string. */
3622 pop_it (it);
3623 it->image_id = 0;
3624 if (STRINGP (it->string))
3625 {
3626 it->method = next_element_from_string;
3627 goto consider_string_end;
3628 }
3629 else
3630 it->method = next_element_from_buffer;
3631 }
3632 else
3633 /* There are no other methods defined, so this should be a bug. */
3634 abort ();
3635
3636 /* Reset flags indicating start and end of a sequence of
3637 characters with box. */
3638 it->start_of_box_run_p = it->end_of_box_run_p = 0;
3639
3640 xassert (it->method != next_element_from_string
3641 || (STRINGP (it->string)
3642 && IT_STRING_CHARPOS (*it) >= 0));
3643}
3644
3645
3646/* Load IT's display element fields with information about the next
3647 display element which comes from a display table entry or from the
3648 result of translating a control character to one of the forms `^C'
3649 or `\003'. IT->dpvec holds the glyphs to return as characters. */
3650
3651static int
3652next_element_from_display_vector (it)
3653 struct it *it;
3654{
3655 /* Precondition. */
3656 xassert (it->dpvec && it->current.dpvec_index >= 0);
3657
3658 /* Remember the current face id in case glyphs specify faces.
3659 IT's face is restored in set_iterator_to_next. */
3660 it->saved_face_id = it->face_id;
3661
3662 if (INTEGERP (*it->dpvec)
3663 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
3664 {
3665 int lface_id;
3666 GLYPH g;
3667
3668 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
3669 it->c = FAST_GLYPH_CHAR (g);
3670 it->len = CHAR_LEN (it->c);
3671
3672 /* The entry may contain a face id to use. Such a face id is
3673 the id of a Lisp face, not a realized face. A face id of
3674 zero means no face. */
3675 lface_id = FAST_GLYPH_FACE (g);
3676 if (lface_id)
3677 {
3678 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
3679 if (face_id >= 0)
3680 {
3681 it->face_id = face_id;
3682 it->charset = CHARSET_ASCII;
3683 }
3684 }
3685 }
3686 else
3687 /* Display table entry is invalid. Return a space. */
3688 it->c = ' ', it->len = 1;
3689
3690 /* Don't change position and object of the iterator here. They are
3691 still the values of the character that had this display table
3692 entry or was translated, and that's what we want. */
3693 it->what = IT_CHARACTER;
3694 return 1;
3695}
3696
3697
3698/* Load IT with the next display element from Lisp string IT->string.
3699 IT->current.string_pos is the current position within the string.
3700 If IT->current.overlay_string_index >= 0, the Lisp string is an
3701 overlay string. */
3702
3703static int
3704next_element_from_string (it)
3705 struct it *it;
3706{
3707 struct text_pos position;
3708
3709 xassert (STRINGP (it->string));
3710 xassert (IT_STRING_CHARPOS (*it) >= 0);
3711 position = it->current.string_pos;
3712
3713 /* Time to check for invisible text? */
3714 if (IT_STRING_CHARPOS (*it) < it->end_charpos
3715 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
3716 {
3717 handle_stop (it);
3718
3719 /* Since a handler may have changed IT->method, we must
3720 recurse here. */
3721 return get_next_display_element (it);
3722 }
3723
3724 if (it->current.overlay_string_index >= 0)
3725 {
3726 /* Get the next character from an overlay string. In overlay
3727 strings, There is no field width or padding with spaces to
3728 do. */
3729 if (IT_STRING_CHARPOS (*it) >= XSTRING (it->string)->size)
3730 {
3731 it->what = IT_EOB;
3732 return 0;
3733 }
3734 else if (STRING_MULTIBYTE (it->string))
3735 {
3736 int remaining = (STRING_BYTES (XSTRING (it->string))
3737 - IT_STRING_BYTEPOS (*it));
3738 unsigned char *s = (XSTRING (it->string)->data
3739 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3740 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
3741 }
3742 else
3743 {
3744 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3745 it->len = 1;
3746 }
3747 }
3748 else
3749 {
3750 /* Get the next character from a Lisp string that is not an
3751 overlay string. Such strings come from the mode line, for
3752 example. We may have to pad with spaces, or truncate the
3753 string. See also next_element_from_c_string. */
3754 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
3755 {
3756 it->what = IT_EOB;
3757 return 0;
3758 }
3759 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
3760 {
3761 /* Pad with spaces. */
3762 it->c = ' ', it->len = 1;
3763 CHARPOS (position) = BYTEPOS (position) = -1;
3764 }
3765 else if (STRING_MULTIBYTE (it->string))
3766 {
3767 int maxlen = (STRING_BYTES (XSTRING (it->string))
3768 - IT_STRING_BYTEPOS (*it));
3769 unsigned char *s = (XSTRING (it->string)->data
3770 + IT_STRING_BYTEPOS (*it));
4fdb80f2 3771 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
3772 }
3773 else
3774 {
3775 it->c = XSTRING (it->string)->data[IT_STRING_BYTEPOS (*it)];
3776 it->len = 1;
3777 }
3778 }
3779
3780 /* Record what we have and where it came from. Note that we store a
3781 buffer position in IT->position although it could arguably be a
3782 string position. */
3783 it->what = IT_CHARACTER;
3784 it->object = it->string;
3785 it->position = position;
3786 return 1;
3787}
3788
3789
3790/* Load IT with next display element from C string IT->s.
3791 IT->string_nchars is the maximum number of characters to return
3792 from the string. IT->end_charpos may be greater than
3793 IT->string_nchars when this function is called, in which case we
3794 may have to return padding spaces. Value is zero if end of string
3795 reached, including padding spaces. */
3796
3797static int
3798next_element_from_c_string (it)
3799 struct it *it;
3800{
3801 int success_p = 1;
3802
3803 xassert (it->s);
3804 it->what = IT_CHARACTER;
3805 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
3806 it->object = Qnil;
3807
3808 /* IT's position can be greater IT->string_nchars in case a field
3809 width or precision has been specified when the iterator was
3810 initialized. */
3811 if (IT_CHARPOS (*it) >= it->end_charpos)
3812 {
3813 /* End of the game. */
3814 it->what = IT_EOB;
3815 success_p = 0;
3816 }
3817 else if (IT_CHARPOS (*it) >= it->string_nchars)
3818 {
3819 /* Pad with spaces. */
3820 it->c = ' ', it->len = 1;
3821 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
3822 }
3823 else if (it->multibyte_p)
3824 {
3825 /* Implementation note: The calls to strlen apparently aren't a
3826 performance problem because there is no noticeable performance
3827 difference between Emacs running in unibyte or multibyte mode. */
3828 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
3829 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
3830 maxlen, &it->len);
5f5c8ee5
GM
3831 }
3832 else
3833 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
3834
3835 return success_p;
3836}
3837
3838
3839/* Set up IT to return characters from an ellipsis, if appropriate.
3840 The definition of the ellipsis glyphs may come from a display table
3841 entry. This function Fills IT with the first glyph from the
3842 ellipsis if an ellipsis is to be displayed. */
3843
13f19968 3844static int
5f5c8ee5
GM
3845next_element_from_ellipsis (it)
3846 struct it *it;
3847{
13f19968 3848 if (it->selective_display_ellipsis_p)
5f5c8ee5 3849 {
13f19968
GM
3850 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
3851 {
3852 /* Use the display table definition for `...'. Invalid glyphs
3853 will be handled by the method returning elements from dpvec. */
3854 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
3855 it->dpvec_char_len = it->len;
3856 it->dpvec = v->contents;
3857 it->dpend = v->contents + v->size;
3858 it->current.dpvec_index = 0;
3859 it->method = next_element_from_display_vector;
3860 }
3861 else
3862 {
3863 /* Use default `...' which is stored in default_invis_vector. */
3864 it->dpvec_char_len = it->len;
3865 it->dpvec = default_invis_vector;
3866 it->dpend = default_invis_vector + 3;
3867 it->current.dpvec_index = 0;
3868 it->method = next_element_from_display_vector;
3869 }
5f5c8ee5 3870 }
13f19968
GM
3871 else
3872 reseat_at_next_visible_line_start (it, 1);
3873
3874 return get_next_display_element (it);
5f5c8ee5
GM
3875}
3876
3877
3878/* Deliver an image display element. The iterator IT is already
3879 filled with image information (done in handle_display_prop). Value
3880 is always 1. */
3881
3882
3883static int
3884next_element_from_image (it)
3885 struct it *it;
3886{
3887 it->what = IT_IMAGE;
3888 return 1;
3889}
3890
3891
3892/* Fill iterator IT with next display element from a stretch glyph
3893 property. IT->object is the value of the text property. Value is
3894 always 1. */
3895
3896static int
3897next_element_from_stretch (it)
3898 struct it *it;
3899{
3900 it->what = IT_STRETCH;
3901 return 1;
3902}
3903
3904
3905/* Load IT with the next display element from current_buffer. Value
3906 is zero if end of buffer reached. IT->stop_charpos is the next
3907 position at which to stop and check for text properties or buffer
3908 end. */
3909
3910static int
3911next_element_from_buffer (it)
3912 struct it *it;
3913{
3914 int success_p = 1;
3915
3916 /* Check this assumption, otherwise, we would never enter the
3917 if-statement, below. */
3918 xassert (IT_CHARPOS (*it) >= BEGV
3919 && IT_CHARPOS (*it) <= it->stop_charpos);
3920
3921 if (IT_CHARPOS (*it) >= it->stop_charpos)
3922 {
3923 if (IT_CHARPOS (*it) >= it->end_charpos)
3924 {
3925 int overlay_strings_follow_p;
3926
3927 /* End of the game, except when overlay strings follow that
3928 haven't been returned yet. */
3929 if (it->overlay_strings_at_end_processed_p)
3930 overlay_strings_follow_p = 0;
3931 else
3932 {
3933 it->overlay_strings_at_end_processed_p = 1;
c880678e 3934 overlay_strings_follow_p = get_overlay_strings (it);
5f5c8ee5
GM
3935 }
3936
3937 if (overlay_strings_follow_p)
3938 success_p = get_next_display_element (it);
3939 else
3940 {
3941 it->what = IT_EOB;
3942 it->position = it->current.pos;
3943 success_p = 0;
3944 }
3945 }
3946 else
3947 {
3948 handle_stop (it);
3949 return get_next_display_element (it);
3950 }
3951 }
3952 else
3953 {
3954 /* No face changes, overlays etc. in sight, so just return a
3955 character from current_buffer. */
3956 unsigned char *p;
3957
3958 /* Maybe run the redisplay end trigger hook. Performance note:
3959 This doesn't seem to cost measurable time. */
3960 if (it->redisplay_end_trigger_charpos
3961 && it->glyph_row
3962 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
3963 run_redisplay_end_trigger_hook (it);
3964
3965 /* Get the next character, maybe multibyte. */
3966 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
260a86a0 3967 if (it->multibyte_p && !ASCII_BYTE_P (*p))
5f5c8ee5
GM
3968 {
3969 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
3970 - IT_BYTEPOS (*it));
4fdb80f2 3971 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
3972 }
3973 else
3974 it->c = *p, it->len = 1;
3975
3976 /* Record what we have and where it came from. */
3977 it->what = IT_CHARACTER;;
3978 it->object = it->w->buffer;
3979 it->position = it->current.pos;
3980
3981 /* Normally we return the character found above, except when we
3982 really want to return an ellipsis for selective display. */
3983 if (it->selective)
3984 {
3985 if (it->c == '\n')
3986 {
3987 /* A value of selective > 0 means hide lines indented more
3988 than that number of columns. */
3989 if (it->selective > 0
3990 && IT_CHARPOS (*it) + 1 < ZV
3991 && indented_beyond_p (IT_CHARPOS (*it) + 1,
3992 IT_BYTEPOS (*it) + 1,
3993 it->selective))
312246d1 3994 {
13f19968 3995 success_p = next_element_from_ellipsis (it);
312246d1
GM
3996 it->dpvec_char_len = -1;
3997 }
5f5c8ee5
GM
3998 }
3999 else if (it->c == '\r' && it->selective == -1)
4000 {
4001 /* A value of selective == -1 means that everything from the
4002 CR to the end of the line is invisible, with maybe an
4003 ellipsis displayed for it. */
13f19968 4004 success_p = next_element_from_ellipsis (it);
312246d1 4005 it->dpvec_char_len = -1;
5f5c8ee5
GM
4006 }
4007 }
4008 }
4009
4010 /* Value is zero if end of buffer reached. */
c880678e 4011 xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
5f5c8ee5
GM
4012 return success_p;
4013}
4014
4015
4016/* Run the redisplay end trigger hook for IT. */
4017
4018static void
4019run_redisplay_end_trigger_hook (it)
4020 struct it *it;
4021{
4022 Lisp_Object args[3];
4023
4024 /* IT->glyph_row should be non-null, i.e. we should be actually
4025 displaying something, or otherwise we should not run the hook. */
4026 xassert (it->glyph_row);
4027
4028 /* Set up hook arguments. */
4029 args[0] = Qredisplay_end_trigger_functions;
4030 args[1] = it->window;
4031 XSETINT (args[2], it->redisplay_end_trigger_charpos);
4032 it->redisplay_end_trigger_charpos = 0;
4033
4034 /* Since we are *trying* to run these functions, don't try to run
4035 them again, even if they get an error. */
4036 it->w->redisplay_end_trigger = Qnil;
4037 Frun_hook_with_args (3, args);
4038
4039 /* Notice if it changed the face of the character we are on. */
4040 handle_face_prop (it);
4041}
4042
4043
260a86a0
KH
4044/* Deliver a composition display element. The iterator IT is already
4045 filled with composition information (done in
4046 handle_composition_prop). Value is always 1. */
4047
4048static int
4049next_element_from_composition (it)
4050 struct it *it;
4051{
4052 it->what = IT_COMPOSITION;
4053 it->position = (STRINGP (it->string)
4054 ? it->current.string_pos
4055 : it->current.pos);
4056 return 1;
4057}
4058
4059
5f5c8ee5
GM
4060\f
4061/***********************************************************************
4062 Moving an iterator without producing glyphs
4063 ***********************************************************************/
4064
4065/* Move iterator IT to a specified buffer or X position within one
4066 line on the display without producing glyphs.
4067
4068 Begin to skip at IT's current position. Skip to TO_CHARPOS or TO_X
4069 whichever is reached first.
4070
4071 TO_CHARPOS <= 0 means no TO_CHARPOS is specified.
4072
4073 TO_X < 0 means that no TO_X is specified. TO_X is normally a value
4074 0 <= TO_X <= IT->last_visible_x. This means in particular, that
4075 TO_X includes the amount by which a window is horizontally
4076 scrolled.
4077
4078 Value is
4079
4080 MOVE_POS_MATCH_OR_ZV
4081 - when TO_POS or ZV was reached.
4082
4083 MOVE_X_REACHED
4084 -when TO_X was reached before TO_POS or ZV were reached.
4085
4086 MOVE_LINE_CONTINUED
4087 - when we reached the end of the display area and the line must
4088 be continued.
4089
4090 MOVE_LINE_TRUNCATED
4091 - when we reached the end of the display area and the line is
4092 truncated.
4093
4094 MOVE_NEWLINE_OR_CR
4095 - when we stopped at a line end, i.e. a newline or a CR and selective
4096 display is on. */
4097
701552dd 4098static enum move_it_result
5f5c8ee5
GM
4099move_it_in_display_line_to (it, to_charpos, to_x, op)
4100 struct it *it;
4101 int to_charpos, to_x, op;
4102{
4103 enum move_it_result result = MOVE_UNDEFINED;
4104 struct glyph_row *saved_glyph_row;
4105
4106 /* Don't produce glyphs in produce_glyphs. */
4107 saved_glyph_row = it->glyph_row;
4108 it->glyph_row = NULL;
4109
5f5c8ee5
GM
4110 while (1)
4111 {
4112 int x, i;
4113
4114 /* Stop when ZV or TO_CHARPOS reached. */
4115 if (!get_next_display_element (it)
4116 || ((op & MOVE_TO_POS) != 0
4117 && BUFFERP (it->object)
4118 && IT_CHARPOS (*it) >= to_charpos))
4119 {
4120 result = MOVE_POS_MATCH_OR_ZV;
4121 break;
4122 }
4123
4124 /* The call to produce_glyphs will get the metrics of the
4125 display element IT is loaded with. We record in x the
4126 x-position before this display element in case it does not
4127 fit on the line. */
4128 x = it->current_x;
4129 PRODUCE_GLYPHS (it);
4130
4131 if (it->area != TEXT_AREA)
4132 {
4133 set_iterator_to_next (it);
4134 continue;
4135 }
4136
4137 /* The number of glyphs we get back in IT->nglyphs will normally
4138 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
4139 character on a terminal frame, or (iii) a line end. For the
4140 second case, IT->nglyphs - 1 padding glyphs will be present
4141 (on X frames, there is only one glyph produced for a
4142 composite character.
4143
4144 The behavior implemented below means, for continuation lines,
4145 that as many spaces of a TAB as fit on the current line are
4146 displayed there. For terminal frames, as many glyphs of a
4147 multi-glyph character are displayed in the current line, too.
4148 This is what the old redisplay code did, and we keep it that
4149 way. Under X, the whole shape of a complex character must
4150 fit on the line or it will be completely displayed in the
4151 next line.
4152
4153 Note that both for tabs and padding glyphs, all glyphs have
4154 the same width. */
4155 if (it->nglyphs)
4156 {
4157 /* More than one glyph or glyph doesn't fit on line. All
4158 glyphs have the same width. */
4159 int single_glyph_width = it->pixel_width / it->nglyphs;
4160 int new_x;
4161
4162 for (i = 0; i < it->nglyphs; ++i, x = new_x)
4163 {
4164 new_x = x + single_glyph_width;
4165
4166 /* We want to leave anything reaching TO_X to the caller. */
4167 if ((op & MOVE_TO_X) && new_x > to_x)
4168 {
4169 it->current_x = x;
4170 result = MOVE_X_REACHED;
4171 break;
4172 }
4173 else if (/* Lines are continued. */
4174 !it->truncate_lines_p
4175 && (/* And glyph doesn't fit on the line. */
4176 new_x > it->last_visible_x
4177 /* Or it fits exactly and we're on a window
4178 system frame. */
4179 || (new_x == it->last_visible_x
4180 && FRAME_WINDOW_P (it->f))))
4181 {
4182 if (/* IT->hpos == 0 means the very first glyph
4183 doesn't fit on the line, e.g. a wide image. */
4184 it->hpos == 0
4185 || (new_x == it->last_visible_x
4186 && FRAME_WINDOW_P (it->f)))
4187 {
4188 ++it->hpos;
4189 it->current_x = new_x;
4190 if (i == it->nglyphs - 1)
4191 set_iterator_to_next (it);
4192 }
4193 else
4194 it->current_x = x;
4195
4196 result = MOVE_LINE_CONTINUED;
4197 break;
4198 }
4199 else if (new_x > it->first_visible_x)
4200 {
4201 /* Glyph is visible. Increment number of glyphs that
4202 would be displayed. */
4203 ++it->hpos;
4204 }
4205 else
4206 {
4207 /* Glyph is completely off the left margin of the display
4208 area. Nothing to do. */
4209 }
4210 }
4211
4212 if (result != MOVE_UNDEFINED)
4213 break;
4214 }
4215 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
4216 {
4217 /* Stop when TO_X specified and reached. This check is
4218 necessary here because of lines consisting of a line end,
4219 only. The line end will not produce any glyphs and we
4220 would never get MOVE_X_REACHED. */
4221 xassert (it->nglyphs == 0);
4222 result = MOVE_X_REACHED;
4223 break;
4224 }
4225
4226 /* Is this a line end? If yes, we're done. */
4227 if (ITERATOR_AT_END_OF_LINE_P (it))
4228 {
4229 result = MOVE_NEWLINE_OR_CR;
4230 break;
4231 }
4232
4233 /* The current display element has been consumed. Advance
4234 to the next. */
4235 set_iterator_to_next (it);
4236
4237 /* Stop if lines are truncated and IT's current x-position is
4238 past the right edge of the window now. */
4239 if (it->truncate_lines_p
4240 && it->current_x >= it->last_visible_x)
4241 {
4242 result = MOVE_LINE_TRUNCATED;
4243 break;
4244 }
4245 }
4246
4247 /* Restore the iterator settings altered at the beginning of this
4248 function. */
4249 it->glyph_row = saved_glyph_row;
4250 return result;
4251}
4252
4253
4254/* Move IT forward to a specified buffer position TO_CHARPOS, TO_X,
4255 TO_Y, TO_VPOS. OP is a bit-mask that specifies where to stop. See
4256 the description of enum move_operation_enum.
4257
4258 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
4259 screen line, this function will set IT to the next position >
4260 TO_CHARPOS. */
4261
4262void
4263move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
4264 struct it *it;
4265 int to_charpos, to_x, to_y, to_vpos;
4266 int op;
4267{
4268 enum move_it_result skip, skip2 = MOVE_X_REACHED;
4269 int line_height;
4270
5f5c8ee5
GM
4271 while (1)
4272 {
4273 if (op & MOVE_TO_VPOS)
4274 {
4275 /* If no TO_CHARPOS and no TO_X specified, stop at the
4276 start of the line TO_VPOS. */
4277 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
4278 {
4279 if (it->vpos == to_vpos)
4280 break;
4281 skip = move_it_in_display_line_to (it, -1, -1, 0);
4282 }
4283 else
4284 {
4285 /* TO_VPOS >= 0 means stop at TO_X in the line at
4286 TO_VPOS, or at TO_POS, whichever comes first. */
4287 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
4288
4289 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
4290 break;
4291 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
4292 {
4293 /* We have reached TO_X but not in the line we want. */
4294 skip = move_it_in_display_line_to (it, to_charpos,
4295 -1, MOVE_TO_POS);
4296 if (skip == MOVE_POS_MATCH_OR_ZV)
4297 break;
4298 }
4299 }
4300 }
4301 else if (op & MOVE_TO_Y)
4302 {
4303 struct it it_backup;
4304 int done_p;
4305
4306 /* TO_Y specified means stop at TO_X in the line containing
4307 TO_Y---or at TO_CHARPOS if this is reached first. The
4308 problem is that we can't really tell whether the line
4309 contains TO_Y before we have completely scanned it, and
4310 this may skip past TO_X. What we do is to first scan to
4311 TO_X.
4312
4313 If TO_X is not specified, use a TO_X of zero. The reason
4314 is to make the outcome of this function more predictable.
4315 If we didn't use TO_X == 0, we would stop at the end of
4316 the line which is probably not what a caller would expect
4317 to happen. */
4318 skip = move_it_in_display_line_to (it, to_charpos,
4319 ((op & MOVE_TO_X)
4320 ? to_x : 0),
4321 (MOVE_TO_X
4322 | (op & MOVE_TO_POS)));
4323
4324 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
4325 if (skip == MOVE_POS_MATCH_OR_ZV)
4326 break;
4327
4328 /* If TO_X was reached, we would like to know whether TO_Y
4329 is in the line. This can only be said if we know the
4330 total line height which requires us to scan the rest of
4331 the line. */
4332 done_p = 0;
4333 if (skip == MOVE_X_REACHED)
4334 {
4335 it_backup = *it;
4336 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
4337 op & MOVE_TO_POS);
4338 }
4339
4340 /* Now, decide whether TO_Y is in this line. */
4341 line_height = it->max_ascent + it->max_descent;
4342
4343 if (to_y >= it->current_y
4344 && to_y < it->current_y + line_height)
4345 {
4346 if (skip == MOVE_X_REACHED)
4347 /* If TO_Y is in this line and TO_X was reached above,
4348 we scanned too far. We have to restore IT's settings
4349 to the ones before skipping. */
4350 *it = it_backup;
4351 done_p = 1;
4352 }
4353 else if (skip == MOVE_X_REACHED)
4354 {
4355 skip = skip2;
4356 if (skip == MOVE_POS_MATCH_OR_ZV)
4357 done_p = 1;
4358 }
4359
4360 if (done_p)
4361 break;
4362 }
4363 else
4364 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
4365
4366 switch (skip)
4367 {
4368 case MOVE_POS_MATCH_OR_ZV:
4369 return;
4370
4371 case MOVE_NEWLINE_OR_CR:
4372 set_iterator_to_next (it);
4373 it->continuation_lines_width = 0;
4374 break;
4375
4376 case MOVE_LINE_TRUNCATED:
4377 it->continuation_lines_width = 0;
312246d1 4378 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4379 if ((op & MOVE_TO_POS) != 0
4380 && IT_CHARPOS (*it) > to_charpos)
4381 goto out;
4382 break;
4383
4384 case MOVE_LINE_CONTINUED:
4385 it->continuation_lines_width += it->current_x;
4386 break;
4387
4388 default:
4389 abort ();
4390 }
4391
4392 /* Reset/increment for the next run. */
4393 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
4394 it->current_x = it->hpos = 0;
4395 it->current_y += it->max_ascent + it->max_descent;
4396 ++it->vpos;
4397 last_height = it->max_ascent + it->max_descent;
4398 last_max_ascent = it->max_ascent;
4399 it->max_ascent = it->max_descent = 0;
4400 }
4401 out:;
4402}
4403
4404
4405/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
4406
4407 If DY > 0, move IT backward at least that many pixels. DY = 0
4408 means move IT backward to the preceding line start or BEGV. This
4409 function may move over more than DY pixels if IT->current_y - DY
4410 ends up in the middle of a line; in this case IT->current_y will be
4411 set to the top of the line moved to. */
4412
4413void
4414move_it_vertically_backward (it, dy)
4415 struct it *it;
4416 int dy;
4417{
4418 int nlines, h, line_height;
4419 struct it it2;
4420 int start_pos = IT_CHARPOS (*it);
4421
4422 xassert (dy >= 0);
4423
4424 /* Estimate how many newlines we must move back. */
4425 nlines = max (1, dy / CANON_Y_UNIT (it->f));
4426
4427 /* Set the iterator's position that many lines back. */
4428 while (nlines-- && IT_CHARPOS (*it) > BEGV)
4429 back_to_previous_visible_line_start (it);
4430
4431 /* Reseat the iterator here. When moving backward, we don't want
4432 reseat to skip forward over invisible text, set up the iterator
4433 to deliver from overlay strings at the new position etc. So,
4434 use reseat_1 here. */
4435 reseat_1 (it, it->current.pos, 1);
4436
4437 /* We are now surely at a line start. */
4438 it->current_x = it->hpos = 0;
4439
4440 /* Move forward and see what y-distance we moved. First move to the
4441 start of the next line so that we get its height. We need this
4442 height to be able to tell whether we reached the specified
4443 y-distance. */
4444 it2 = *it;
4445 it2.max_ascent = it2.max_descent = 0;
4446 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
4447 MOVE_TO_POS | MOVE_TO_VPOS);
4448 xassert (IT_CHARPOS (*it) >= BEGV);
4449 line_height = it2.max_ascent + it2.max_descent;
4450 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
4451 xassert (IT_CHARPOS (*it) >= BEGV);
4452 h = it2.current_y - it->current_y;
4453 nlines = it2.vpos - it->vpos;
4454
4455 /* Correct IT's y and vpos position. */
4456 it->vpos -= nlines;
4457 it->current_y -= h;
4458
4459 if (dy == 0)
4460 {
4461 /* DY == 0 means move to the start of the screen line. The
4462 value of nlines is > 0 if continuation lines were involved. */
4463 if (nlines > 0)
4464 move_it_by_lines (it, nlines, 1);
4465 xassert (IT_CHARPOS (*it) <= start_pos);
4466 }
4467 else if (nlines)
4468 {
4469 /* The y-position we try to reach. Note that h has been
4470 subtracted in front of the if-statement. */
4471 int target_y = it->current_y + h - dy;
4472
4473 /* If we did not reach target_y, try to move further backward if
4474 we can. If we moved too far backward, try to move forward. */
4475 if (target_y < it->current_y
4476 && IT_CHARPOS (*it) > BEGV)
4477 {
4478 move_it_vertically (it, target_y - it->current_y);
4479 xassert (IT_CHARPOS (*it) >= BEGV);
4480 }
4481 else if (target_y >= it->current_y + line_height
4482 && IT_CHARPOS (*it) < ZV)
4483 {
4484 move_it_vertically (it, target_y - (it->current_y + line_height));
4485 xassert (IT_CHARPOS (*it) >= BEGV);
4486 }
4487 }
4488}
4489
4490
4491/* Move IT by a specified amount of pixel lines DY. DY negative means
4492 move backwards. DY = 0 means move to start of screen line. At the
4493 end, IT will be on the start of a screen line. */
4494
4495void
4496move_it_vertically (it, dy)
4497 struct it *it;
4498 int dy;
4499{
4500 if (dy <= 0)
4501 move_it_vertically_backward (it, -dy);
4502 else if (dy > 0)
4503 {
4504 move_it_to (it, ZV, -1, it->current_y + dy, -1,
4505 MOVE_TO_POS | MOVE_TO_Y);
4506
4507 /* If buffer ends in ZV without a newline, move to the start of
4508 the line to satisfy the post-condition. */
4509 if (IT_CHARPOS (*it) == ZV
4510 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
4511 move_it_by_lines (it, 0, 0);
4512 }
4513}
4514
4515
4516/* Return non-zero if some text between buffer positions START_CHARPOS
4517 and END_CHARPOS is invisible. IT->window is the window for text
4518 property lookup. */
4519
4520static int
4521invisible_text_between_p (it, start_charpos, end_charpos)
4522 struct it *it;
4523 int start_charpos, end_charpos;
4524{
5f5c8ee5
GM
4525 Lisp_Object prop, limit;
4526 int invisible_found_p;
4527
4528 xassert (it != NULL && start_charpos <= end_charpos);
4529
4530 /* Is text at START invisible? */
4531 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
4532 it->window);
4533 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4534 invisible_found_p = 1;
4535 else
4536 {
6c577098
GM
4537 limit = next_single_char_property_change (make_number (start_charpos),
4538 Qinvisible, Qnil,
4539 make_number (end_charpos));
5f5c8ee5
GM
4540 invisible_found_p = XFASTINT (limit) < end_charpos;
4541 }
4542
4543 return invisible_found_p;
5f5c8ee5
GM
4544}
4545
4546
4547/* Move IT by a specified number DVPOS of screen lines down. DVPOS
4548 negative means move up. DVPOS == 0 means move to the start of the
4549 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
4550 NEED_Y_P is zero, IT->current_y will be left unchanged.
4551
4552 Further optimization ideas: If we would know that IT->f doesn't use
4553 a face with proportional font, we could be faster for
4554 truncate-lines nil. */
4555
4556void
4557move_it_by_lines (it, dvpos, need_y_p)
4558 struct it *it;
4559 int dvpos, need_y_p;
4560{
4561 struct position pos;
4562
4563 if (!FRAME_WINDOW_P (it->f))
4564 {
4565 struct text_pos textpos;
4566
4567 /* We can use vmotion on frames without proportional fonts. */
4568 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
4569 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
4570 reseat (it, textpos, 1);
4571 it->vpos += pos.vpos;
4572 it->current_y += pos.vpos;
4573 }
4574 else if (dvpos == 0)
4575 {
4576 /* DVPOS == 0 means move to the start of the screen line. */
4577 move_it_vertically_backward (it, 0);
4578 xassert (it->current_x == 0 && it->hpos == 0);
4579 }
4580 else if (dvpos > 0)
4581 {
4582 /* If there are no continuation lines, and if there is no
4583 selective display, try the simple method of moving forward
4584 DVPOS newlines, then see where we are. */
4585 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4586 {
4587 int shortage = 0, charpos;
4588
4589 if (FETCH_BYTE (IT_BYTEPOS (*it) == '\n'))
4590 charpos = IT_CHARPOS (*it) + 1;
4591 else
4592 charpos = scan_buffer ('\n', IT_CHARPOS (*it), 0, dvpos,
4593 &shortage, 0);
4594
4595 if (!invisible_text_between_p (it, IT_CHARPOS (*it), charpos))
4596 {
4597 struct text_pos pos;
4598 CHARPOS (pos) = charpos;
4599 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4600 reseat (it, pos, 1);
4601 it->vpos += dvpos - shortage;
4602 it->hpos = it->current_x = 0;
4603 return;
4604 }
4605 }
4606
4607 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
4608 }
4609 else
4610 {
4611 struct it it2;
4612 int start_charpos, i;
4613
4614 /* If there are no continuation lines, and if there is no
4615 selective display, try the simple method of moving backward
4616 -DVPOS newlines. */
4617 if (!need_y_p && it->truncate_lines_p && it->selective == 0)
4618 {
4619 int shortage;
4620 int charpos = IT_CHARPOS (*it);
4621 int bytepos = IT_BYTEPOS (*it);
4622
4623 /* If in the middle of a line, go to its start. */
4624 if (charpos > BEGV && FETCH_BYTE (bytepos - 1) != '\n')
4625 {
4626 charpos = find_next_newline_no_quit (charpos, -1);
4627 bytepos = CHAR_TO_BYTE (charpos);
4628 }
4629
4630 if (charpos == BEGV)
4631 {
4632 struct text_pos pos;
4633 CHARPOS (pos) = charpos;
4634 BYTEPOS (pos) = bytepos;
4635 reseat (it, pos, 1);
4636 it->hpos = it->current_x = 0;
4637 return;
4638 }
4639 else
4640 {
4641 charpos = scan_buffer ('\n', charpos - 1, 0, dvpos, &shortage, 0);
4642 if (!invisible_text_between_p (it, charpos, IT_CHARPOS (*it)))
4643 {
4644 struct text_pos pos;
4645 CHARPOS (pos) = charpos;
4646 BYTEPOS (pos) = CHAR_TO_BYTE (charpos);
4647 reseat (it, pos, 1);
4648 it->vpos += dvpos + (shortage ? shortage - 1 : 0);
4649 it->hpos = it->current_x = 0;
4650 return;
4651 }
4652 }
4653 }
4654
4655 /* Go back -DVPOS visible lines and reseat the iterator there. */
4656 start_charpos = IT_CHARPOS (*it);
4657 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
4658 back_to_previous_visible_line_start (it);
4659 reseat (it, it->current.pos, 1);
4660 it->current_x = it->hpos = 0;
4661
4662 /* Above call may have moved too far if continuation lines
4663 are involved. Scan forward and see if it did. */
4664 it2 = *it;
4665 it2.vpos = it2.current_y = 0;
4666 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
4667 it->vpos -= it2.vpos;
4668 it->current_y -= it2.current_y;
4669 it->current_x = it->hpos = 0;
4670
4671 /* If we moved too far, move IT some lines forward. */
4672 if (it2.vpos > -dvpos)
4673 {
4674 int delta = it2.vpos + dvpos;
4675 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
4676 }
4677 }
4678}
4679
4680
4681\f
4682/***********************************************************************
4683 Messages
4684 ***********************************************************************/
4685
4686
937248bc
GM
4687/* Add a message with format string FORMAT and arguments ARG1 and ARG2
4688 to *Messages*. */
4689
4690void
4691add_to_log (format, arg1, arg2)
4692 char *format;
4693 Lisp_Object arg1, arg2;
4694{
4695 Lisp_Object args[3];
4696 Lisp_Object msg, fmt;
4697 char *buffer;
4698 int len;
4699 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4700
4701 fmt = msg = Qnil;
4702 GCPRO4 (fmt, msg, arg1, arg2);
4703
4704 args[0] = fmt = build_string (format);
4705 args[1] = arg1;
4706 args[2] = arg2;
4707 msg = Fformat (make_number (3), args);
4708
4709 len = STRING_BYTES (XSTRING (msg)) + 1;
4710 buffer = (char *) alloca (len);
4711 strcpy (buffer, XSTRING (msg)->data);
4712
4713 message_dolog (buffer, len, 1, 0);
4714 UNGCPRO;
4715}
4716
4717
5f5c8ee5
GM
4718/* Output a newline in the *Messages* buffer if "needs" one. */
4719
4720void
4721message_log_maybe_newline ()
4722{
4723 if (message_log_need_newline)
4724 message_dolog ("", 0, 1, 0);
4725}
4726
4727
4728/* Add a string M of length LEN to the message log, optionally
4729 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
4730 nonzero, means interpret the contents of M as multibyte. This
4731 function calls low-level routines in order to bypass text property
4732 hooks, etc. which might not be safe to run. */
4733
4734void
4735message_dolog (m, len, nlflag, multibyte)
4736 char *m;
4737 int len, nlflag, multibyte;
4738{
4739 if (!NILP (Vmessage_log_max))
4740 {
4741 struct buffer *oldbuf;
4742 Lisp_Object oldpoint, oldbegv, oldzv;
4743 int old_windows_or_buffers_changed = windows_or_buffers_changed;
4744 int point_at_end = 0;
4745 int zv_at_end = 0;
4746 Lisp_Object old_deactivate_mark, tem;
4747 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4748
4749 old_deactivate_mark = Vdeactivate_mark;
4750 oldbuf = current_buffer;
4751 Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
4752 current_buffer->undo_list = Qt;
4753
4754 oldpoint = Fpoint_marker ();
4755 oldbegv = Fpoint_min_marker ();
4756 oldzv = Fpoint_max_marker ();
4757 GCPRO4 (oldpoint, oldbegv, oldzv, old_deactivate_mark);
4758
4759 if (PT == Z)
4760 point_at_end = 1;
4761 if (ZV == Z)
4762 zv_at_end = 1;
4763
4764 BEGV = BEG;
4765 BEGV_BYTE = BEG_BYTE;
4766 ZV = Z;
4767 ZV_BYTE = Z_BYTE;
4768 TEMP_SET_PT_BOTH (Z, Z_BYTE);
4769
4770 /* Insert the string--maybe converting multibyte to single byte
4771 or vice versa, so that all the text fits the buffer. */
4772 if (multibyte
4773 && NILP (current_buffer->enable_multibyte_characters))
4774 {
4775 int i, c, nbytes;
4776 unsigned char work[1];
4777
4778 /* Convert a multibyte string to single-byte
4779 for the *Message* buffer. */
4780 for (i = 0; i < len; i += nbytes)
4781 {
4fdb80f2 4782 c = string_char_and_length (m + i, len - i, &nbytes);
5f5c8ee5
GM
4783 work[0] = (SINGLE_BYTE_CHAR_P (c)
4784 ? c
4785 : multibyte_char_to_unibyte (c, Qnil));
4786 insert_1_both (work, 1, 1, 1, 0, 0);
4787 }
4788 }
4789 else if (! multibyte
4790 && ! NILP (current_buffer->enable_multibyte_characters))
4791 {
4792 int i, c, nbytes;
4793 unsigned char *msg = (unsigned char *) m;
260a86a0 4794 unsigned char str[MAX_MULTIBYTE_LENGTH];
5f5c8ee5
GM
4795 /* Convert a single-byte string to multibyte
4796 for the *Message* buffer. */
4797 for (i = 0; i < len; i++)
4798 {
4799 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
4800 nbytes = CHAR_STRING (c, str);
4801 insert_1_both (str, 1, nbytes, 1, 0, 0);
5f5c8ee5
GM
4802 }
4803 }
4804 else if (len)
4805 insert_1 (m, len, 1, 0, 0);
4806
4807 if (nlflag)
4808 {
4809 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
4810 insert_1 ("\n", 1, 1, 0, 0);
4811
4812 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
4813 this_bol = PT;
4814 this_bol_byte = PT_BYTE;
4815
4816 if (this_bol > BEG)
4817 {
4818 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
4819 prev_bol = PT;
4820 prev_bol_byte = PT_BYTE;
4821
4822 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
4823 this_bol, this_bol_byte);
4824 if (dup)
4825 {
4826 del_range_both (prev_bol, prev_bol_byte,
4827 this_bol, this_bol_byte, 0);
4828 if (dup > 1)
4829 {
4830 char dupstr[40];
4831 int duplen;
4832
4833 /* If you change this format, don't forget to also
4834 change message_log_check_duplicate. */
4835 sprintf (dupstr, " [%d times]", dup);
4836 duplen = strlen (dupstr);
4837 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
4838 insert_1 (dupstr, duplen, 1, 0, 1);
4839 }
4840 }
4841 }
4842
4843 if (NATNUMP (Vmessage_log_max))
4844 {
4845 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
4846 -XFASTINT (Vmessage_log_max) - 1, 0);
4847 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
4848 }
4849 }
4850 BEGV = XMARKER (oldbegv)->charpos;
4851 BEGV_BYTE = marker_byte_position (oldbegv);
4852
4853 if (zv_at_end)
4854 {
4855 ZV = Z;
4856 ZV_BYTE = Z_BYTE;
4857 }
4858 else
4859 {
4860 ZV = XMARKER (oldzv)->charpos;
4861 ZV_BYTE = marker_byte_position (oldzv);
4862 }
4863
4864 if (point_at_end)
4865 TEMP_SET_PT_BOTH (Z, Z_BYTE);
4866 else
4867 /* We can't do Fgoto_char (oldpoint) because it will run some
4868 Lisp code. */
4869 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
4870 XMARKER (oldpoint)->bytepos);
4871
4872 UNGCPRO;
4873 free_marker (oldpoint);
4874 free_marker (oldbegv);
4875 free_marker (oldzv);
4876
4877 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
4878 set_buffer_internal (oldbuf);
4879 if (NILP (tem))
4880 windows_or_buffers_changed = old_windows_or_buffers_changed;
4881 message_log_need_newline = !nlflag;
4882 Vdeactivate_mark = old_deactivate_mark;
4883 }
4884}
4885
4886
4887/* We are at the end of the buffer after just having inserted a newline.
4888 (Note: We depend on the fact we won't be crossing the gap.)
4889 Check to see if the most recent message looks a lot like the previous one.
4890 Return 0 if different, 1 if the new one should just replace it, or a
4891 value N > 1 if we should also append " [N times]". */
4892
4893static int
4894message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
4895 int prev_bol, this_bol;
4896 int prev_bol_byte, this_bol_byte;
4897{
4898 int i;
4899 int len = Z_BYTE - 1 - this_bol_byte;
4900 int seen_dots = 0;
4901 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
4902 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
4903
4904 for (i = 0; i < len; i++)
4905 {
4906 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
4907 && p1[i] != '\n')
4908 seen_dots = 1;
4909 if (p1[i] != p2[i])
4910 return seen_dots;
4911 }
4912 p1 += len;
4913 if (*p1 == '\n')
4914 return 2;
4915 if (*p1++ == ' ' && *p1++ == '[')
4916 {
4917 int n = 0;
4918 while (*p1 >= '0' && *p1 <= '9')
4919 n = n * 10 + *p1++ - '0';
4920 if (strncmp (p1, " times]\n", 8) == 0)
4921 return n+1;
4922 }
4923 return 0;
4924}
4925
4926
4927/* Display an echo area message M with a specified length of LEN
4928 chars. The string may include null characters. If M is 0, clear
4929 out any existing message, and let the mini-buffer text show through.
4930
4931 The buffer M must continue to exist until after the echo area gets
4932 cleared or some other message gets displayed there. This means do
4933 not pass text that is stored in a Lisp string; do not pass text in
4934 a buffer that was alloca'd. */
4935
4936void
4937message2 (m, len, multibyte)
4938 char *m;
4939 int len;
4940 int multibyte;
4941{
4942 /* First flush out any partial line written with print. */
4943 message_log_maybe_newline ();
4944 if (m)
4945 message_dolog (m, len, 1, multibyte);
4946 message2_nolog (m, len, multibyte);
4947}
4948
4949
4950/* The non-logging counterpart of message2. */
4951
4952void
4953message2_nolog (m, len, multibyte)
4954 char *m;
4955 int len;
4956{
886bd6f2 4957 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
4958 message_enable_multibyte = multibyte;
4959
4960 if (noninteractive)
4961 {
4962 if (noninteractive_need_newline)
4963 putc ('\n', stderr);
4964 noninteractive_need_newline = 0;
4965 if (m)
4966 fwrite (m, len, 1, stderr);
4967 if (cursor_in_echo_area == 0)
4968 fprintf (stderr, "\n");
4969 fflush (stderr);
4970 }
4971 /* A null message buffer means that the frame hasn't really been
4972 initialized yet. Error messages get reported properly by
4973 cmd_error, so this must be just an informative message; toss it. */
4974 else if (INTERACTIVE
886bd6f2
GM
4975 && sf->glyphs_initialized_p
4976 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
4977 {
4978 Lisp_Object mini_window;
4979 struct frame *f;
4980
4981 /* Get the frame containing the mini-buffer
4982 that the selected frame is using. */
886bd6f2 4983 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
4984 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
4985
4986 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 4987 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
4988 && ! FRAME_VISIBLE_P (f))
4989 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
4990
4991 if (m)
4992 {
c6e89d6c 4993 set_message (m, Qnil, len, multibyte);
5f5c8ee5
GM
4994 if (minibuffer_auto_raise)
4995 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
4996 }
4997 else
c6e89d6c 4998 clear_message (1, 1);
5f5c8ee5 4999
c6e89d6c 5000 do_pending_window_change (0);
5f5c8ee5 5001 echo_area_display (1);
c6e89d6c 5002 do_pending_window_change (0);
5f5c8ee5
GM
5003 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
5004 (*frame_up_to_date_hook) (f);
5005 }
5006}
5007
5008
c6e89d6c
GM
5009/* Display an echo area message M with a specified length of NBYTES
5010 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
5011 string, clear out any existing message, and let the mini-buffer
5012 text show through. */
5013
5014void
c6e89d6c 5015message3 (m, nbytes, multibyte)
5f5c8ee5 5016 Lisp_Object m;
c6e89d6c 5017 int nbytes;
5f5c8ee5
GM
5018 int multibyte;
5019{
5020 struct gcpro gcpro1;
5021
5022 GCPRO1 (m);
5023
5024 /* First flush out any partial line written with print. */
5025 message_log_maybe_newline ();
5026 if (STRINGP (m))
c6e89d6c
GM
5027 message_dolog (XSTRING (m)->data, nbytes, 1, multibyte);
5028 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
5029
5030 UNGCPRO;
5031}
5032
5033
5034/* The non-logging version of message3. */
5035
5036void
c6e89d6c 5037message3_nolog (m, nbytes, multibyte)
5f5c8ee5 5038 Lisp_Object m;
c6e89d6c 5039 int nbytes, multibyte;
5f5c8ee5 5040{
886bd6f2 5041 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5042 message_enable_multibyte = multibyte;
5043
5044 if (noninteractive)
5045 {
5046 if (noninteractive_need_newline)
5047 putc ('\n', stderr);
5048 noninteractive_need_newline = 0;
5049 if (STRINGP (m))
c6e89d6c 5050 fwrite (XSTRING (m)->data, nbytes, 1, stderr);
5f5c8ee5
GM
5051 if (cursor_in_echo_area == 0)
5052 fprintf (stderr, "\n");
5053 fflush (stderr);
5054 }
5055 /* A null message buffer means that the frame hasn't really been
5056 initialized yet. Error messages get reported properly by
5057 cmd_error, so this must be just an informative message; toss it. */
5058 else if (INTERACTIVE
886bd6f2
GM
5059 && sf->glyphs_initialized_p
5060 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
5061 {
5062 Lisp_Object mini_window;
c6e89d6c 5063 Lisp_Object frame;
5f5c8ee5
GM
5064 struct frame *f;
5065
5066 /* Get the frame containing the mini-buffer
5067 that the selected frame is using. */
886bd6f2 5068 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5069 frame = XWINDOW (mini_window)->frame;
5070 f = XFRAME (frame);
5f5c8ee5
GM
5071
5072 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 5073 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
5074 && !FRAME_VISIBLE_P (f))
5075 Fmake_frame_visible (frame);
5f5c8ee5 5076
c6e89d6c 5077 if (STRINGP (m) && XSTRING (m)->size)
5f5c8ee5 5078 {
c6e89d6c 5079 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
5080 if (minibuffer_auto_raise)
5081 Fraise_frame (frame);
5f5c8ee5
GM
5082 }
5083 else
c6e89d6c 5084 clear_message (1, 1);
5f5c8ee5 5085
c6e89d6c 5086 do_pending_window_change (0);
5f5c8ee5 5087 echo_area_display (1);
c6e89d6c 5088 do_pending_window_change (0);
5f5c8ee5
GM
5089 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
5090 (*frame_up_to_date_hook) (f);
5091 }
5092}
5093
5094
5095/* Display a null-terminated echo area message M. If M is 0, clear
5096 out any existing message, and let the mini-buffer text show through.
5097
5098 The buffer M must continue to exist until after the echo area gets
5099 cleared or some other message gets displayed there. Do not pass
5100 text that is stored in a Lisp string. Do not pass text in a buffer
5101 that was alloca'd. */
5102
5103void
5104message1 (m)
5105 char *m;
5106{
5107 message2 (m, (m ? strlen (m) : 0), 0);
5108}
5109
5110
5111/* The non-logging counterpart of message1. */
5112
5113void
5114message1_nolog (m)
5115 char *m;
5116{
5117 message2_nolog (m, (m ? strlen (m) : 0), 0);
5118}
5119
5120/* Display a message M which contains a single %s
5121 which gets replaced with STRING. */
5122
5123void
5124message_with_string (m, string, log)
5125 char *m;
5126 Lisp_Object string;
5127 int log;
5128{
5129 if (noninteractive)
5130 {
5131 if (m)
5132 {
5133 if (noninteractive_need_newline)
5134 putc ('\n', stderr);
5135 noninteractive_need_newline = 0;
5136 fprintf (stderr, m, XSTRING (string)->data);
5137 if (cursor_in_echo_area == 0)
5138 fprintf (stderr, "\n");
5139 fflush (stderr);
5140 }
5141 }
5142 else if (INTERACTIVE)
5143 {
5144 /* The frame whose minibuffer we're going to display the message on.
5145 It may be larger than the selected frame, so we need
5146 to use its buffer, not the selected frame's buffer. */
5147 Lisp_Object mini_window;
886bd6f2 5148 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5149
5150 /* Get the frame containing the minibuffer
5151 that the selected frame is using. */
886bd6f2 5152 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5153 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5154
5155 /* A null message buffer means that the frame hasn't really been
5156 initialized yet. Error messages get reported properly by
5157 cmd_error, so this must be just an informative message; toss it. */
5158 if (FRAME_MESSAGE_BUF (f))
5159 {
5160 int len;
5161 char *a[1];
5162 a[0] = (char *) XSTRING (string)->data;
5163
5164 len = doprnt (FRAME_MESSAGE_BUF (f),
5165 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5166
5167 if (log)
5168 message2 (FRAME_MESSAGE_BUF (f), len,
5169 STRING_MULTIBYTE (string));
5170 else
5171 message2_nolog (FRAME_MESSAGE_BUF (f), len,
5172 STRING_MULTIBYTE (string));
5173
5174 /* Print should start at the beginning of the message
5175 buffer next time. */
5176 message_buf_print = 0;
5177 }
5178 }
5179}
5180
5181
5f5c8ee5
GM
5182/* Dump an informative message to the minibuf. If M is 0, clear out
5183 any existing message, and let the mini-buffer text show through. */
5184
5185/* VARARGS 1 */
5186void
5187message (m, a1, a2, a3)
5188 char *m;
5189 EMACS_INT a1, a2, a3;
5190{
5191 if (noninteractive)
5192 {
5193 if (m)
5194 {
5195 if (noninteractive_need_newline)
5196 putc ('\n', stderr);
5197 noninteractive_need_newline = 0;
5198 fprintf (stderr, m, a1, a2, a3);
5199 if (cursor_in_echo_area == 0)
5200 fprintf (stderr, "\n");
5201 fflush (stderr);
5202 }
5203 }
5204 else if (INTERACTIVE)
5205 {
5206 /* The frame whose mini-buffer we're going to display the message
5207 on. It may be larger than the selected frame, so we need to
5208 use its buffer, not the selected frame's buffer. */
5209 Lisp_Object mini_window;
886bd6f2 5210 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
5211
5212 /* Get the frame containing the mini-buffer
5213 that the selected frame is using. */
886bd6f2 5214 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
5215 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
5216
5217 /* A null message buffer means that the frame hasn't really been
5218 initialized yet. Error messages get reported properly by
5219 cmd_error, so this must be just an informative message; toss
5220 it. */
5221 if (FRAME_MESSAGE_BUF (f))
5222 {
5223 if (m)
5224 {
5225 int len;
5226#ifdef NO_ARG_ARRAY
5227 char *a[3];
5228 a[0] = (char *) a1;
5229 a[1] = (char *) a2;
5230 a[2] = (char *) a3;
5231
5232 len = doprnt (FRAME_MESSAGE_BUF (f),
5233 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
5234#else
5235 len = doprnt (FRAME_MESSAGE_BUF (f),
5236 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
5237 (char **) &a1);
5238#endif /* NO_ARG_ARRAY */
5239
5240 message2 (FRAME_MESSAGE_BUF (f), len, 0);
5241 }
5242 else
5243 message1 (0);
5244
5245 /* Print should start at the beginning of the message
5246 buffer next time. */
5247 message_buf_print = 0;
5248 }
5249 }
5250}
5251
5252
5253/* The non-logging version of message. */
5254
5255void
5256message_nolog (m, a1, a2, a3)
5257 char *m;
5258 EMACS_INT a1, a2, a3;
5259{
5260 Lisp_Object old_log_max;
5261 old_log_max = Vmessage_log_max;
5262 Vmessage_log_max = Qnil;
5263 message (m, a1, a2, a3);
5264 Vmessage_log_max = old_log_max;
5265}
5266
5267
c6e89d6c
GM
5268/* Display the current message in the current mini-buffer. This is
5269 only called from error handlers in process.c, and is not time
5270 critical. */
5f5c8ee5
GM
5271
5272void
5273update_echo_area ()
5274{
c6e89d6c
GM
5275 if (!NILP (echo_area_buffer[0]))
5276 {
5277 Lisp_Object string;
5278 string = Fcurrent_message ();
5279 message3 (string, XSTRING (string)->size,
5280 !NILP (current_buffer->enable_multibyte_characters));
5281 }
5282}
5283
5284
5bcfeb49
GM
5285/* Make sure echo area buffers in echo_buffers[] are life. If they
5286 aren't, make new ones. */
5287
5288static void
5289ensure_echo_area_buffers ()
5290{
5291 int i;
5292
5293 for (i = 0; i < 2; ++i)
5294 if (!BUFFERP (echo_buffer[i])
5295 || NILP (XBUFFER (echo_buffer[i])->name))
5296 {
5297 char name[30];
5298 sprintf (name, " *Echo Area %d*", i);
5299 echo_buffer[i] = Fget_buffer_create (build_string (name));
5300 }
5301}
5302
5303
c6e89d6c
GM
5304/* Call FN with args A1..A5 with either the current or last displayed
5305 echo_area_buffer as current buffer.
5306
5307 WHICH zero means use the current message buffer
5308 echo_area_buffer[0]. If that is nil, choose a suitable buffer
5309 from echo_buffer[] and clear it.
5310
5311 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
5312 suitable buffer from echo_buffer[] and clear it.
5313
5314 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
5315 that the current message becomes the last displayed one, make
5316 choose a suitable buffer for echo_area_buffer[0], and clear it.
5317
5318 Value is what FN returns. */
5319
5320static int
5321with_echo_area_buffer (w, which, fn, a1, a2, a3, a4, a5)
5322 struct window *w;
5323 int which;
5324 int (*fn) ();
5325 int a1, a2, a3, a4, a5;
5326{
5327 Lisp_Object buffer;
5328 int i, this_one, the_other, clear_buffer_p, rc;
5329 int count = specpdl_ptr - specpdl;
5330
5331 /* If buffers aren't life, make new ones. */
5bcfeb49 5332 ensure_echo_area_buffers ();
c6e89d6c
GM
5333
5334 clear_buffer_p = 0;
5335
5336 if (which == 0)
5337 this_one = 0, the_other = 1;
5338 else if (which > 0)
5339 this_one = 1, the_other = 0;
5f5c8ee5 5340 else
c6e89d6c
GM
5341 {
5342 this_one = 0, the_other = 1;
5343 clear_buffer_p = 1;
5344
5345 /* We need a fresh one in case the current echo buffer equals
5346 the one containing the last displayed echo area message. */
5347 if (!NILP (echo_area_buffer[this_one])
5348 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
5349 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
5350 }
5351
5352 /* Choose a suitable buffer from echo_buffer[] is we don't
5353 have one. */
5354 if (NILP (echo_area_buffer[this_one]))
5355 {
5356 echo_area_buffer[this_one]
5357 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
5358 ? echo_buffer[the_other]
5359 : echo_buffer[this_one]);
5360 clear_buffer_p = 1;
5361 }
5362
5363 buffer = echo_area_buffer[this_one];
5364
5365 record_unwind_protect (unwind_with_echo_area_buffer,
5366 with_echo_area_buffer_unwind_data (w));
5367
5368 /* Make the echo area buffer current. Note that for display
5369 purposes, it is not necessary that the displayed window's buffer
5370 == current_buffer, except for text property lookup. So, let's
5371 only set that buffer temporarily here without doing a full
5372 Fset_window_buffer. We must also change w->pointm, though,
5373 because otherwise an assertions in unshow_buffer fails, and Emacs
5374 aborts. */
9142dd5b 5375 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
5376 if (w)
5377 {
5378 w->buffer = buffer;
5379 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
5380 }
5381 current_buffer->truncate_lines = Qnil;
5382 current_buffer->undo_list = Qt;
5383 current_buffer->read_only = Qnil;
5384
5385 if (clear_buffer_p && Z > BEG)
5386 del_range (BEG, Z);
5387
5388 xassert (BEGV >= BEG);
5389 xassert (ZV <= Z && ZV >= BEGV);
5390
5391 rc = fn (a1, a2, a3, a4, a5);
5392
5393 xassert (BEGV >= BEG);
5394 xassert (ZV <= Z && ZV >= BEGV);
5395
5396 unbind_to (count, Qnil);
5397 return rc;
5f5c8ee5
GM
5398}
5399
5400
c6e89d6c
GM
5401/* Save state that should be preserved around the call to the function
5402 FN called in with_echo_area_buffer. */
5f5c8ee5 5403
c6e89d6c
GM
5404static Lisp_Object
5405with_echo_area_buffer_unwind_data (w)
5406 struct window *w;
5f5c8ee5 5407{
c6e89d6c
GM
5408 int i = 0;
5409 Lisp_Object vector;
5f5c8ee5 5410
c6e89d6c
GM
5411 /* Reduce consing by keeping one vector in
5412 Vwith_echo_area_save_vector. */
5413 vector = Vwith_echo_area_save_vector;
5414 Vwith_echo_area_save_vector = Qnil;
5415
5416 if (NILP (vector))
9142dd5b 5417 vector = Fmake_vector (make_number (7), Qnil);
c6e89d6c
GM
5418
5419 XSETBUFFER (XVECTOR (vector)->contents[i], current_buffer); ++i;
5420 XVECTOR (vector)->contents[i++] = Vdeactivate_mark;
5421 XVECTOR (vector)->contents[i++] = make_number (windows_or_buffers_changed);
c6e89d6c
GM
5422
5423 if (w)
5424 {
5425 XSETWINDOW (XVECTOR (vector)->contents[i], w); ++i;
5426 XVECTOR (vector)->contents[i++] = w->buffer;
5427 XVECTOR (vector)->contents[i++]
5428 = make_number (XMARKER (w->pointm)->charpos);
5429 XVECTOR (vector)->contents[i++]
5430 = make_number (XMARKER (w->pointm)->bytepos);
5431 }
5432 else
5433 {
5434 int end = i + 4;
5435 while (i < end)
5436 XVECTOR (vector)->contents[i++] = Qnil;
5437 }
5f5c8ee5 5438
c6e89d6c
GM
5439 xassert (i == XVECTOR (vector)->size);
5440 return vector;
5441}
5f5c8ee5 5442
5f5c8ee5 5443
c6e89d6c
GM
5444/* Restore global state from VECTOR which was created by
5445 with_echo_area_buffer_unwind_data. */
5446
5447static Lisp_Object
5448unwind_with_echo_area_buffer (vector)
5449 Lisp_Object vector;
5450{
5451 int i = 0;
5452
9142dd5b 5453 set_buffer_internal_1 (XBUFFER (XVECTOR (vector)->contents[i])); ++i;
c6e89d6c
GM
5454 Vdeactivate_mark = XVECTOR (vector)->contents[i]; ++i;
5455 windows_or_buffers_changed = XFASTINT (XVECTOR (vector)->contents[i]); ++i;
c6e89d6c
GM
5456
5457 if (WINDOWP (XVECTOR (vector)->contents[i]))
5458 {
5459 struct window *w;
5460 Lisp_Object buffer, charpos, bytepos;
5461
5462 w = XWINDOW (XVECTOR (vector)->contents[i]); ++i;
5463 buffer = XVECTOR (vector)->contents[i]; ++i;
5464 charpos = XVECTOR (vector)->contents[i]; ++i;
5465 bytepos = XVECTOR (vector)->contents[i]; ++i;
5466
5467 w->buffer = buffer;
5468 set_marker_both (w->pointm, buffer,
5469 XFASTINT (charpos), XFASTINT (bytepos));
5470 }
5471
5472 Vwith_echo_area_save_vector = vector;
5473 return Qnil;
5474}
5475
5476
5477/* Set up the echo area for use by print functions. MULTIBYTE_P
5478 non-zero means we will print multibyte. */
5479
5480void
5481setup_echo_area_for_printing (multibyte_p)
5482 int multibyte_p;
5483{
5bcfeb49
GM
5484 ensure_echo_area_buffers ();
5485
c6e89d6c
GM
5486 if (!message_buf_print)
5487 {
5488 /* A message has been output since the last time we printed.
5489 Choose a fresh echo area buffer. */
5490 if (EQ (echo_area_buffer[1], echo_buffer[0]))
5491 echo_area_buffer[0] = echo_buffer[1];
5492 else
5493 echo_area_buffer[0] = echo_buffer[0];
5494
5495 /* Switch to that buffer and clear it. */
5496 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5497 if (Z > BEG)
5498 del_range (BEG, Z);
5499 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5500
5501 /* Set up the buffer for the multibyteness we need. */
5502 if (multibyte_p
5503 != !NILP (current_buffer->enable_multibyte_characters))
5504 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
5505
5506 /* Raise the frame containing the echo area. */
5507 if (minibuffer_auto_raise)
5508 {
886bd6f2 5509 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5510 Lisp_Object mini_window;
886bd6f2 5511 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5512 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
5513 }
5514
5515 message_buf_print = 1;
5516 }
5517 else if (current_buffer != XBUFFER (echo_area_buffer[0]))
5518 /* Someone switched buffers between print requests. */
5519 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
5520}
5521
5522
dd2eb166
GM
5523/* Display an echo area message in window W. Value is non-zero if W's
5524 height is changed. If display_last_displayed_message_p is
5525 non-zero, display the message that was last displayed, otherwise
5526 display the current message. */
c6e89d6c
GM
5527
5528static int
5529display_echo_area (w)
5530 struct window *w;
5531{
dd2eb166
GM
5532 int i, no_message_p, window_height_changed_p;
5533
5534 /* If there is no message, we must call display_echo_area_1
5535 nevertheless because it resizes the window. But we will have to
5536 reset the echo_area_buffer in question to nil at the end because
5537 with_echo_area_buffer will sets it to an empty buffer. */
5538 i = display_last_displayed_message_p ? 1 : 0;
5539 no_message_p = NILP (echo_area_buffer[i]);
5540
5541 window_height_changed_p
5542 = with_echo_area_buffer (w, display_last_displayed_message_p,
5543 (int (*) ()) display_echo_area_1, w);
5544
5545 if (no_message_p)
5546 echo_area_buffer[i] = Qnil;
5547
5548 return window_height_changed_p;
c6e89d6c
GM
5549}
5550
5551
5552/* Helper for display_echo_area. Display the current buffer which
5553 contains the current echo area message in window W, a mini-window.
5554 Change the height of W so that all of the message is displayed.
5555 Value is non-zero if height of W was changed. */
5556
5557static int
5558display_echo_area_1 (w)
5559 struct window *w;
5560{
5561 Lisp_Object window;
c6e89d6c
GM
5562 struct text_pos start;
5563 int window_height_changed_p = 0;
5564
5565 /* Do this before displaying, so that we have a large enough glyph
5566 matrix for the display. */
92a90e89 5567 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
5568
5569 /* Display. */
5570 clear_glyph_matrix (w->desired_matrix);
5571 XSETWINDOW (window, w);
5572 SET_TEXT_POS (start, BEG, BEG_BYTE);
5573 try_window (window, start);
5574
c6e89d6c
GM
5575 return window_height_changed_p;
5576}
5577
5578
92a90e89
GM
5579/* Resize the echo area window to exactly the size needed for the
5580 currently displayed message, if there is one. */
5581
5582void
5583resize_echo_area_axactly ()
5584{
5585 if (BUFFERP (echo_area_buffer[0])
5586 && WINDOWP (echo_area_window))
5587 {
5588 struct window *w = XWINDOW (echo_area_window);
5589 int resized_p;
5590
5591 resized_p = with_echo_area_buffer (w, 0,
5592 (int (*) ()) resize_mini_window,
5593 w, 1);
5594 if (resized_p)
5595 {
5596 ++windows_or_buffers_changed;
5597 ++update_mode_lines;
5598 redisplay_internal (0);
5599 }
5600 }
5601}
5602
5603
5604/* Resize mini-window W to fit the size of its contents. EXACT:P
5605 means size the window exactly to the size needed. Otherwise, it's
5606 only enlarged until W's buffer is empty. Value is non-zero if
5607 the window height has been changed. */
c6e89d6c 5608
9472f927 5609int
92a90e89 5610resize_mini_window (w, exact_p)
c6e89d6c 5611 struct window *w;
92a90e89 5612 int exact_p;
c6e89d6c
GM
5613{
5614 struct frame *f = XFRAME (w->frame);
5615 int window_height_changed_p = 0;
5616
5617 xassert (MINI_WINDOW_P (w));
97cafc0f
GM
5618
5619 /* Nil means don't try to resize. */
00f6d59e
GM
5620 if (NILP (Vmax_mini_window_height)
5621 || (FRAME_X_P (f) && f->output_data.x == NULL))
97cafc0f 5622 return 0;
c6e89d6c
GM
5623
5624 if (!FRAME_MINIBUF_ONLY_P (f))
5625 {
5626 struct it it;
dd2eb166
GM
5627 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
5628 int total_height = XFASTINT (root->height) + XFASTINT (w->height);
5629 int height, max_height;
5630 int unit = CANON_Y_UNIT (f);
5631 struct text_pos start;
9142dd5b 5632
c6e89d6c 5633 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 5634
dd2eb166
GM
5635 /* Compute the max. number of lines specified by the user. */
5636 if (FLOATP (Vmax_mini_window_height))
5637 max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
5638 else if (INTEGERP (Vmax_mini_window_height))
5639 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
5640 else
5641 max_height = total_height / 4;
dd2eb166
GM
5642
5643 /* Correct that max. height if it's bogus. */
5644 max_height = max (1, max_height);
5645 max_height = min (total_height, max_height);
5646
5647 /* Find out the height of the text in the window. */
55b064bd 5648 last_height = 0;
dd2eb166 5649 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
55b064bd
GM
5650 if (it.max_ascent == 0 && it.max_descent == 0)
5651 height = it.current_y + last_height;
5652 else
5653 height = it.current_y + it.max_ascent + it.max_descent;
5654 height = (height + unit - 1) / unit;
dd2eb166
GM
5655
5656 /* Compute a suitable window start. */
5657 if (height > max_height)
5658 {
5659 height = max_height;
5660 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5661 move_it_vertically_backward (&it, (height - 1) * unit);
5662 start = it.current.pos;
5663 }
5664 else
5665 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5666 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 5667
9472f927
GM
5668 /* Let it grow only, until we display an empty message, in which
5669 case the window shrinks again. */
da448723 5670 if (height > XFASTINT (w->height))
dd2eb166 5671 {
d2c48e86 5672 int old_height = XFASTINT (w->height);
da448723
GM
5673 freeze_window_starts (f, 1);
5674 grow_mini_window (w, height - XFASTINT (w->height));
5675 window_height_changed_p = XFASTINT (w->height) != old_height;
5676 }
5677 else if (height < XFASTINT (w->height)
5678 && (exact_p || BEGV == ZV))
5679 {
5680 int old_height = XFASTINT (w->height);
5681 freeze_window_starts (f, 0);
5682 shrink_mini_window (w);
d2c48e86 5683 window_height_changed_p = XFASTINT (w->height) != old_height;
9142dd5b 5684 }
c6e89d6c
GM
5685 }
5686
5687 return window_height_changed_p;
5688}
5689
5690
5691/* Value is the current message, a string, or nil if there is no
5692 current message. */
5693
5694Lisp_Object
5695current_message ()
5696{
5697 Lisp_Object msg;
5698
5699 if (NILP (echo_area_buffer[0]))
5700 msg = Qnil;
5701 else
5702 {
5703 with_echo_area_buffer (0, 0, (int (*) ()) current_message_1, &msg);
5704 if (NILP (msg))
5705 echo_area_buffer[0] = Qnil;
5706 }
5707
5708 return msg;
5709}
5710
5711
5712static int
5713current_message_1 (msg)
5714 Lisp_Object *msg;
5715{
5716 if (Z > BEG)
5717 *msg = make_buffer_string (BEG, Z, 1);
5718 else
5719 *msg = Qnil;
5720 return 0;
5721}
5722
5723
5724/* Push the current message on Vmessage_stack for later restauration
5725 by restore_message. Value is non-zero if the current message isn't
5726 empty. This is a relatively infrequent operation, so it's not
5727 worth optimizing. */
5728
5729int
5730push_message ()
5731{
5732 Lisp_Object msg;
5733 msg = current_message ();
5734 Vmessage_stack = Fcons (msg, Vmessage_stack);
5735 return STRINGP (msg);
5736}
5737
5738
5739/* Restore message display from the top of Vmessage_stack. */
5740
5741void
5742restore_message ()
5743{
5744 Lisp_Object msg;
5745
5746 xassert (CONSP (Vmessage_stack));
5747 msg = XCAR (Vmessage_stack);
5748 if (STRINGP (msg))
5749 message3_nolog (msg, STRING_BYTES (XSTRING (msg)), STRING_MULTIBYTE (msg));
5750 else
5751 message3_nolog (msg, 0, 0);
5752}
5753
5754
5755/* Pop the top-most entry off Vmessage_stack. */
5756
5757void
5758pop_message ()
5759{
5760 xassert (CONSP (Vmessage_stack));
5761 Vmessage_stack = XCDR (Vmessage_stack);
5762}
5763
5764
5765/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
5766 exits. If the stack is not empty, we have a missing pop_message
5767 somewhere. */
5768
5769void
5770check_message_stack ()
5771{
5772 if (!NILP (Vmessage_stack))
5773 abort ();
5774}
5775
5776
5777/* Truncate to NCHARS what will be displayed in the echo area the next
5778 time we display it---but don't redisplay it now. */
5779
5780void
5781truncate_echo_area (nchars)
5782 int nchars;
5783{
5784 if (nchars == 0)
5785 echo_area_buffer[0] = Qnil;
5786 /* A null message buffer means that the frame hasn't really been
5787 initialized yet. Error messages get reported properly by
5788 cmd_error, so this must be just an informative message; toss it. */
5789 else if (!noninteractive
5790 && INTERACTIVE
c6e89d6c 5791 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
5792 {
5793 struct frame *sf = SELECTED_FRAME ();
5794 if (FRAME_MESSAGE_BUF (sf))
5795 with_echo_area_buffer (0, 0, (int (*) ()) truncate_message_1, nchars);
5796 }
c6e89d6c
GM
5797}
5798
5799
5800/* Helper function for truncate_echo_area. Truncate the current
5801 message to at most NCHARS characters. */
5802
5803static int
5804truncate_message_1 (nchars)
5805 int nchars;
5806{
5807 if (BEG + nchars < Z)
5808 del_range (BEG + nchars, Z);
5809 if (Z == BEG)
5810 echo_area_buffer[0] = Qnil;
5811 return 0;
5812}
5813
5814
5815/* Set the current message to a substring of S or STRING.
5816
5817 If STRING is a Lisp string, set the message to the first NBYTES
5818 bytes from STRING. NBYTES zero means use the whole string. If
5819 STRING is multibyte, the message will be displayed multibyte.
5820
5821 If S is not null, set the message to the first LEN bytes of S. LEN
5822 zero means use the whole string. MULTIBYTE_P non-zero means S is
5823 multibyte. Display the message multibyte in that case. */
5824
5825void
5826set_message (s, string, nbytes, multibyte_p)
5827 char *s;
5828 Lisp_Object string;
5829 int nbytes;
5830{
5831 message_enable_multibyte
5832 = ((s && multibyte_p)
5833 || (STRINGP (string) && STRING_MULTIBYTE (string)));
5834
5835 with_echo_area_buffer (0, -1, (int (*) ()) set_message_1,
5836 s, string, nbytes, multibyte_p);
5837 message_buf_print = 0;
5838}
5839
5840
5841/* Helper function for set_message. Arguments have the same meaning
5842 as there. This function is called with the echo area buffer being
5843 current. */
5844
5845static int
5846set_message_1 (s, string, nbytes, multibyte_p)
5847 char *s;
5848 Lisp_Object string;
5849 int nbytes, multibyte_p;
5850{
5851 xassert (BEG == Z);
5852
5853 /* Change multibyteness of the echo buffer appropriately. */
5854 if (message_enable_multibyte
5855 != !NILP (current_buffer->enable_multibyte_characters))
5856 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
5857
5858 /* Insert new message at BEG. */
5859 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
5860
5861 if (STRINGP (string))
5862 {
5863 int nchars;
5864
5865 if (nbytes == 0)
5866 nbytes = XSTRING (string)->size_byte;
5867 nchars = string_byte_to_char (string, nbytes);
5868
5869 /* This function takes care of single/multibyte conversion. We
5870 just have to ensure that the echo area buffer has the right
5871 setting of enable_multibyte_characters. */
5872 insert_from_string (string, 0, 0, nchars, nbytes, 1);
5873 }
5874 else if (s)
5875 {
5876 if (nbytes == 0)
5877 nbytes = strlen (s);
5878
5879 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
5880 {
5881 /* Convert from multi-byte to single-byte. */
5882 int i, c, n;
5883 unsigned char work[1];
5884
5885 /* Convert a multibyte string to single-byte. */
5886 for (i = 0; i < nbytes; i += n)
5887 {
5888 c = string_char_and_length (s + i, nbytes - i, &n);
5889 work[0] = (SINGLE_BYTE_CHAR_P (c)
5890 ? c
5891 : multibyte_char_to_unibyte (c, Qnil));
5892 insert_1_both (work, 1, 1, 1, 0, 0);
5893 }
5894 }
5895 else if (!multibyte_p
5896 && !NILP (current_buffer->enable_multibyte_characters))
5897 {
5898 /* Convert from single-byte to multi-byte. */
5899 int i, c, n;
5900 unsigned char *msg = (unsigned char *) s;
260a86a0 5901 unsigned char str[MAX_MULTIBYTE_LENGTH];
c6e89d6c
GM
5902
5903 /* Convert a single-byte string to multibyte. */
5904 for (i = 0; i < nbytes; i++)
5905 {
5906 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
5907 n = CHAR_STRING (c, str);
5908 insert_1_both (str, 1, n, 1, 0, 0);
c6e89d6c
GM
5909 }
5910 }
5911 else
5912 insert_1 (s, nbytes, 1, 0, 0);
5913 }
5914
5915 return 0;
5916}
5917
5918
5919/* Clear messages. CURRENT_P non-zero means clear the current
5920 message. LAST_DISPLAYED_P non-zero means clear the message
5921 last displayed. */
5922
5923void
5924clear_message (current_p, last_displayed_p)
5925 int current_p, last_displayed_p;
5926{
5927 if (current_p)
5928 echo_area_buffer[0] = Qnil;
5929
5930 if (last_displayed_p)
5931 echo_area_buffer[1] = Qnil;
5932
5933 message_buf_print = 0;
5934}
5935
5936/* Clear garbaged frames.
5937
5938 This function is used where the old redisplay called
5939 redraw_garbaged_frames which in turn called redraw_frame which in
5940 turn called clear_frame. The call to clear_frame was a source of
5941 flickering. I believe a clear_frame is not necessary. It should
5942 suffice in the new redisplay to invalidate all current matrices,
5943 and ensure a complete redisplay of all windows. */
5944
5945static void
5946clear_garbaged_frames ()
5947{
5f5c8ee5
GM
5948 if (frame_garbaged)
5949 {
5f5c8ee5
GM
5950 Lisp_Object tail, frame;
5951
5952 FOR_EACH_FRAME (tail, frame)
5953 {
5954 struct frame *f = XFRAME (frame);
5955
5956 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
5957 {
5958 clear_current_matrices (f);
5959 f->garbaged = 0;
5960 }
5961 }
5962
5963 frame_garbaged = 0;
5964 ++windows_or_buffers_changed;
5965 }
c6e89d6c 5966}
5f5c8ee5 5967
5f5c8ee5 5968
886bd6f2
GM
5969/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
5970 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 5971 mini-windows height has been changed. */
5f5c8ee5 5972
c6e89d6c
GM
5973static int
5974echo_area_display (update_frame_p)
5975 int update_frame_p;
5976{
5977 Lisp_Object mini_window;
5978 struct window *w;
5979 struct frame *f;
5980 int window_height_changed_p = 0;
886bd6f2 5981 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 5982
886bd6f2 5983 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
5984 w = XWINDOW (mini_window);
5985 f = XFRAME (WINDOW_FRAME (w));
5986
5987 /* Don't display if frame is invisible or not yet initialized. */
5988 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
5989 return 0;
5f5c8ee5 5990
1ab3e082 5991#ifdef HAVE_WINDOW_SYSTEM
c6e89d6c
GM
5992 /* When Emacs starts, selected_frame may be a visible terminal
5993 frame, even if we run under a window system. If we let this
5994 through, a message would be displayed on the terminal. */
622e3754
GM
5995 if (EQ (selected_frame, Vterminal_frame)
5996 && !NILP (Vwindow_system))
c6e89d6c 5997 return 0;
1ab3e082 5998#endif /* HAVE_WINDOW_SYSTEM */
c6e89d6c
GM
5999
6000 /* Redraw garbaged frames. */
6001 if (frame_garbaged)
6002 clear_garbaged_frames ();
6003
6004 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
6005 {
6006 echo_area_window = mini_window;
6007 window_height_changed_p = display_echo_area (w);
5f5c8ee5 6008 w->must_be_updated_p = 1;
c59c668a 6009
5f5c8ee5
GM
6010 if (update_frame_p)
6011 {
c59c668a
GM
6012 /* Not called from redisplay_internal. If we changed
6013 window configuration, we must redisplay thoroughly.
6014 Otherwise, we can do with updating what we displayed
6015 above. */
6016 if (window_height_changed_p)
6017 {
6018 ++windows_or_buffers_changed;
6019 ++update_mode_lines;
6020 redisplay_internal (0);
6021 }
6022 else if (FRAME_WINDOW_P (f))
5f5c8ee5
GM
6023 {
6024 update_single_window (w, 1);
6025 rif->flush_display (f);
6026 }
6027 else
6028 update_frame (f, 1, 1);
6029 }
6030 }
6031 else if (!EQ (mini_window, selected_window))
6032 windows_or_buffers_changed++;
c59c668a
GM
6033
6034 /* Last displayed message is now the current message. */
dd2eb166
GM
6035 echo_area_buffer[1] = echo_area_buffer[0];
6036
5f5c8ee5
GM
6037 /* Prevent redisplay optimization in redisplay_internal by resetting
6038 this_line_start_pos. This is done because the mini-buffer now
6039 displays the message instead of its buffer text. */
6040 if (EQ (mini_window, selected_window))
6041 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
6042
6043 return window_height_changed_p;
5f5c8ee5
GM
6044}
6045
6046
6047\f
6048/***********************************************************************
6049 Frame Titles
6050 ***********************************************************************/
6051
6052
6053#ifdef HAVE_WINDOW_SYSTEM
6054
6055/* A buffer for constructing frame titles in it; allocated from the
6056 heap in init_xdisp and resized as needed in store_frame_title_char. */
6057
6058static char *frame_title_buf;
6059
6060/* The buffer's end, and a current output position in it. */
6061
6062static char *frame_title_buf_end;
6063static char *frame_title_ptr;
6064
6065
6066/* Store a single character C for the frame title in frame_title_buf.
6067 Re-allocate frame_title_buf if necessary. */
6068
6069static void
6070store_frame_title_char (c)
6071 char c;
6072{
6073 /* If output position has reached the end of the allocated buffer,
6074 double the buffer's size. */
6075 if (frame_title_ptr == frame_title_buf_end)
6076 {
6077 int len = frame_title_ptr - frame_title_buf;
6078 int new_size = 2 * len * sizeof *frame_title_buf;
6079 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
6080 frame_title_buf_end = frame_title_buf + new_size;
6081 frame_title_ptr = frame_title_buf + len;
6082 }
6083
6084 *frame_title_ptr++ = c;
6085}
6086
6087
6088/* Store part of a frame title in frame_title_buf, beginning at
6089 frame_title_ptr. STR is the string to store. Do not copy more
6090 than PRECISION number of bytes from STR; PRECISION <= 0 means copy
6091 the whole string. Pad with spaces until FIELD_WIDTH number of
6092 characters have been copied; FIELD_WIDTH <= 0 means don't pad.
6093 Called from display_mode_element when it is used to build a frame
6094 title. */
6095
6096static int
6097store_frame_title (str, field_width, precision)
6098 unsigned char *str;
6099 int field_width, precision;
6100{
6101 int n = 0;
6102
6103 /* Copy at most PRECISION chars from STR. */
6104 while ((precision <= 0 || n < precision)
6105 && *str)
6106 {
6107 store_frame_title_char (*str++);
6108 ++n;
6109 }
6110
6111 /* Fill up with spaces until FIELD_WIDTH reached. */
6112 while (field_width > 0
6113 && n < field_width)
6114 {
6115 store_frame_title_char (' ');
6116 ++n;
6117 }
6118
6119 return n;
6120}
6121
6122
6123/* Set the title of FRAME, if it has changed. The title format is
6124 Vicon_title_format if FRAME is iconified, otherwise it is
6125 frame_title_format. */
6126
6127static void
6128x_consider_frame_title (frame)
6129 Lisp_Object frame;
6130{
6131 struct frame *f = XFRAME (frame);
6132
6133 if (FRAME_WINDOW_P (f)
6134 || FRAME_MINIBUF_ONLY_P (f)
6135 || f->explicit_name)
6136 {
6137 /* Do we have more than one visible frame on this X display? */
6138 Lisp_Object tail;
6139 Lisp_Object fmt;
6140 struct buffer *obuf;
6141 int len;
6142 struct it it;
6143
9472f927 6144 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 6145 {
9472f927 6146 struct frame *tf = XFRAME (XCAR (tail));
5f5c8ee5
GM
6147
6148 if (tf != f
6149 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
6150 && !FRAME_MINIBUF_ONLY_P (tf)
6151 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
6152 break;
6153 }
6154
6155 /* Set global variable indicating that multiple frames exist. */
6156 multiple_frames = CONSP (tail);
6157
6158 /* Switch to the buffer of selected window of the frame. Set up
6159 frame_title_ptr so that display_mode_element will output into it;
6160 then display the title. */
6161 obuf = current_buffer;
6162 Fset_buffer (XWINDOW (f->selected_window)->buffer);
6163 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
6164 frame_title_ptr = frame_title_buf;
6165 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
6166 NULL, DEFAULT_FACE_ID);
6167 len = display_mode_element (&it, 0, -1, -1, fmt);
6168 frame_title_ptr = NULL;
6169 set_buffer_internal (obuf);
6170
6171 /* Set the title only if it's changed. This avoids consing in
6172 the common case where it hasn't. (If it turns out that we've
6173 already wasted too much time by walking through the list with
6174 display_mode_element, then we might need to optimize at a
6175 higher level than this.) */
6176 if (! STRINGP (f->name)
6177 || STRING_BYTES (XSTRING (f->name)) != len
6178 || bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
6179 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
6180 }
6181}
6182
6183#else /* not HAVE_WINDOW_SYSTEM */
6184
6185#define frame_title_ptr ((char *)0)
6186#define store_frame_title(str, mincol, maxcol) 0
6187
6188#endif /* not HAVE_WINDOW_SYSTEM */
6189
6190
6191
6192\f
6193/***********************************************************************
6194 Menu Bars
6195 ***********************************************************************/
6196
6197
6198/* Prepare for redisplay by updating menu-bar item lists when
6199 appropriate. This can call eval. */
6200
6201void
6202prepare_menu_bars ()
6203{
6204 int all_windows;
6205 struct gcpro gcpro1, gcpro2;
6206 struct frame *f;
6207 struct frame *tooltip_frame;
6208
6209#ifdef HAVE_X_WINDOWS
6210 tooltip_frame = tip_frame;
6211#else
6212 tooltip_frame = NULL;
6213#endif
6214
6215 /* Update all frame titles based on their buffer names, etc. We do
6216 this before the menu bars so that the buffer-menu will show the
6217 up-to-date frame titles. */
6218#ifdef HAVE_WINDOW_SYSTEM
6219 if (windows_or_buffers_changed || update_mode_lines)
6220 {
6221 Lisp_Object tail, frame;
6222
6223 FOR_EACH_FRAME (tail, frame)
6224 {
6225 f = XFRAME (frame);
6226 if (f != tooltip_frame
6227 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
6228 x_consider_frame_title (frame);
6229 }
6230 }
6231#endif /* HAVE_WINDOW_SYSTEM */
6232
6233 /* Update the menu bar item lists, if appropriate. This has to be
6234 done before any actual redisplay or generation of display lines. */
6235 all_windows = (update_mode_lines
6236 || buffer_shared > 1
6237 || windows_or_buffers_changed);
6238 if (all_windows)
6239 {
6240 Lisp_Object tail, frame;
6241 int count = specpdl_ptr - specpdl;
6242
6243 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6244
6245 FOR_EACH_FRAME (tail, frame)
6246 {
6247 f = XFRAME (frame);
6248
6249 /* Ignore tooltip frame. */
6250 if (f == tooltip_frame)
6251 continue;
6252
6253 /* If a window on this frame changed size, report that to
6254 the user and clear the size-change flag. */
6255 if (FRAME_WINDOW_SIZES_CHANGED (f))
6256 {
6257 Lisp_Object functions;
6258
6259 /* Clear flag first in case we get an error below. */
6260 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
6261 functions = Vwindow_size_change_functions;
6262 GCPRO2 (tail, functions);
6263
6264 while (CONSP (functions))
6265 {
6266 call1 (XCAR (functions), frame);
6267 functions = XCDR (functions);
6268 }
6269 UNGCPRO;
6270 }
6271
6272 GCPRO1 (tail);
6273 update_menu_bar (f, 0);
6274#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 6275 update_tool_bar (f, 0);
5f5c8ee5
GM
6276#endif
6277 UNGCPRO;
6278 }
6279
6280 unbind_to (count, Qnil);
6281 }
6282 else
6283 {
886bd6f2
GM
6284 struct frame *sf = SELECTED_FRAME ();
6285 update_menu_bar (sf, 1);
5f5c8ee5 6286#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 6287 update_tool_bar (sf, 1);
5f5c8ee5
GM
6288#endif
6289 }
6290
6291 /* Motif needs this. See comment in xmenu.c. Turn it off when
6292 pending_menu_activation is not defined. */
6293#ifdef USE_X_TOOLKIT
6294 pending_menu_activation = 0;
6295#endif
6296}
6297
6298
6299/* Update the menu bar item list for frame F. This has to be done
6300 before we start to fill in any display lines, because it can call
6301 eval.
6302
6303 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
6304
6305static void
6306update_menu_bar (f, save_match_data)
6307 struct frame *f;
6308 int save_match_data;
6309{
6310 Lisp_Object window;
6311 register struct window *w;
6312
6313 window = FRAME_SELECTED_WINDOW (f);
6314 w = XWINDOW (window);
6315
6316 if (update_mode_lines)
6317 w->update_mode_line = Qt;
6318
6319 if (FRAME_WINDOW_P (f)
6320 ?
6321#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6322 FRAME_EXTERNAL_MENU_BAR (f)
6323#else
6324 FRAME_MENU_BAR_LINES (f) > 0
6325#endif
6326 : FRAME_MENU_BAR_LINES (f) > 0)
6327 {
6328 /* If the user has switched buffers or windows, we need to
6329 recompute to reflect the new bindings. But we'll
6330 recompute when update_mode_lines is set too; that means
6331 that people can use force-mode-line-update to request
6332 that the menu bar be recomputed. The adverse effect on
6333 the rest of the redisplay algorithm is about the same as
6334 windows_or_buffers_changed anyway. */
6335 if (windows_or_buffers_changed
6336 || !NILP (w->update_mode_line)
6337 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6338 < BUF_MODIFF (XBUFFER (w->buffer)))
6339 != !NILP (w->last_had_star))
6340 || ((!NILP (Vtransient_mark_mode)
6341 && !NILP (XBUFFER (w->buffer)->mark_active))
6342 != !NILP (w->region_showing)))
6343 {
6344 struct buffer *prev = current_buffer;
6345 int count = specpdl_ptr - specpdl;
6346
6347 set_buffer_internal_1 (XBUFFER (w->buffer));
6348 if (save_match_data)
6349 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6350 if (NILP (Voverriding_local_map_menu_flag))
6351 {
6352 specbind (Qoverriding_terminal_local_map, Qnil);
6353 specbind (Qoverriding_local_map, Qnil);
6354 }
6355
6356 /* Run the Lucid hook. */
6357 call1 (Vrun_hooks, Qactivate_menubar_hook);
6358
6359 /* If it has changed current-menubar from previous value,
6360 really recompute the menu-bar from the value. */
6361 if (! NILP (Vlucid_menu_bar_dirty_flag))
6362 call0 (Qrecompute_lucid_menubar);
6363
6364 safe_run_hooks (Qmenu_bar_update_hook);
6365 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
6366
6367 /* Redisplay the menu bar in case we changed it. */
6368#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
6369 if (FRAME_WINDOW_P (f))
6370 set_frame_menubar (f, 0, 0);
6371 else
6372 /* On a terminal screen, the menu bar is an ordinary screen
6373 line, and this makes it get updated. */
6374 w->update_mode_line = Qt;
6375#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6376 /* In the non-toolkit version, the menu bar is an ordinary screen
6377 line, and this makes it get updated. */
6378 w->update_mode_line = Qt;
6379#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */
6380
6381 unbind_to (count, Qnil);
6382 set_buffer_internal_1 (prev);
6383 }
6384 }
6385}
6386
6387
6388\f
6389/***********************************************************************
e037b9ec 6390 Tool-bars
5f5c8ee5
GM
6391 ***********************************************************************/
6392
6393#ifdef HAVE_WINDOW_SYSTEM
6394
e037b9ec 6395/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
6396 before we start to fill in any display lines. Called from
6397 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
6398 and restore it here. */
6399
6400static void
e037b9ec 6401update_tool_bar (f, save_match_data)
5f5c8ee5
GM
6402 struct frame *f;
6403 int save_match_data;
6404{
e037b9ec
GM
6405 if (WINDOWP (f->tool_bar_window)
6406 && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0)
5f5c8ee5
GM
6407 {
6408 Lisp_Object window;
6409 struct window *w;
6410
6411 window = FRAME_SELECTED_WINDOW (f);
6412 w = XWINDOW (window);
6413
6414 /* If the user has switched buffers or windows, we need to
6415 recompute to reflect the new bindings. But we'll
6416 recompute when update_mode_lines is set too; that means
6417 that people can use force-mode-line-update to request
6418 that the menu bar be recomputed. The adverse effect on
6419 the rest of the redisplay algorithm is about the same as
6420 windows_or_buffers_changed anyway. */
6421 if (windows_or_buffers_changed
6422 || !NILP (w->update_mode_line)
6423 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
6424 < BUF_MODIFF (XBUFFER (w->buffer)))
6425 != !NILP (w->last_had_star))
6426 || ((!NILP (Vtransient_mark_mode)
6427 && !NILP (XBUFFER (w->buffer)->mark_active))
6428 != !NILP (w->region_showing)))
6429 {
6430 struct buffer *prev = current_buffer;
6431 int count = specpdl_ptr - specpdl;
a2889657 6432
5f5c8ee5
GM
6433 /* Set current_buffer to the buffer of the selected
6434 window of the frame, so that we get the right local
6435 keymaps. */
6436 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 6437
5f5c8ee5
GM
6438 /* Save match data, if we must. */
6439 if (save_match_data)
6440 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
6441
6442 /* Make sure that we don't accidentally use bogus keymaps. */
6443 if (NILP (Voverriding_local_map_menu_flag))
6444 {
6445 specbind (Qoverriding_terminal_local_map, Qnil);
6446 specbind (Qoverriding_local_map, Qnil);
1f40cad2 6447 }
1f40cad2 6448
e037b9ec
GM
6449 /* Build desired tool-bar items from keymaps. */
6450 f->desired_tool_bar_items
6451 = tool_bar_items (f->desired_tool_bar_items,
6452 &f->n_desired_tool_bar_items);
5f5c8ee5 6453
e037b9ec 6454 /* Redisplay the tool-bar in case we changed it. */
5f5c8ee5
GM
6455 w->update_mode_line = Qt;
6456
6457 unbind_to (count, Qnil);
6458 set_buffer_internal_1 (prev);
81d478f3 6459 }
a2889657
JB
6460 }
6461}
6462
6c4429a5 6463
e037b9ec
GM
6464/* Set F->desired_tool_bar_string to a Lisp string representing frame
6465 F's desired tool-bar contents. F->desired_tool_bar_items must have
5f5c8ee5
GM
6466 been set up previously by calling prepare_menu_bars. */
6467
a2889657 6468static void
e037b9ec 6469build_desired_tool_bar_string (f)
5f5c8ee5 6470 struct frame *f;
a2889657 6471{
5f5c8ee5
GM
6472 int i, size, size_needed, string_idx;
6473 struct gcpro gcpro1, gcpro2, gcpro3;
6474 Lisp_Object image, plist, props;
a2889657 6475
5f5c8ee5
GM
6476 image = plist = props = Qnil;
6477 GCPRO3 (image, plist, props);
a2889657 6478
e037b9ec 6479 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5
GM
6480 Otherwise, make a new string. */
6481
6482 /* The size of the string we might be able to reuse. */
e037b9ec
GM
6483 size = (STRINGP (f->desired_tool_bar_string)
6484 ? XSTRING (f->desired_tool_bar_string)->size
5f5c8ee5
GM
6485 : 0);
6486
6487 /* Each image in the string we build is preceded by a space,
6488 and there is a space at the end. */
e037b9ec 6489 size_needed = f->n_desired_tool_bar_items + 1;
5f5c8ee5 6490
e037b9ec 6491 /* Reuse f->desired_tool_bar_string, if possible. */
5f5c8ee5 6492 if (size < size_needed)
e037b9ec 6493 f->desired_tool_bar_string = Fmake_string (make_number (size_needed), ' ');
5f5c8ee5
GM
6494 else
6495 {
6496 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
6497 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 6498 props, f->desired_tool_bar_string);
5f5c8ee5 6499 }
a2889657 6500
5f5c8ee5 6501 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
6502 put a `menu_item' property on tool-bar items with a value that
6503 is the index of the item in F's tool-bar item vector. */
5f5c8ee5 6504 for (i = 0, string_idx = 0;
e037b9ec 6505 i < f->n_desired_tool_bar_items;
5f5c8ee5 6506 ++i, string_idx += 1)
a2889657 6507 {
5f5c8ee5 6508#define PROP(IDX) \
e037b9ec
GM
6509 (XVECTOR (f->desired_tool_bar_items) \
6510 ->contents[i * TOOL_BAR_ITEM_NSLOTS + (IDX)])
5f5c8ee5 6511
e037b9ec
GM
6512 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
6513 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
5f5c8ee5
GM
6514 int margin, relief;
6515 extern Lisp_Object QCrelief, QCmargin, QCalgorithm, Qimage;
6516 extern Lisp_Object Qlaplace;
6517
6518 /* If image is a vector, choose the image according to the
6519 button state. */
e037b9ec 6520 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
6521 if (VECTORP (image))
6522 {
e037b9ec 6523 enum tool_bar_item_image idx;
5f5c8ee5
GM
6524
6525 if (enabled_p)
6526 idx = (selected_p
e037b9ec
GM
6527 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
6528 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
6529 else
6530 idx = (selected_p
e037b9ec
GM
6531 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
6532 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
5f5c8ee5
GM
6533
6534 xassert (XVECTOR (image)->size >= idx);
6535 image = XVECTOR (image)->contents[idx];
6536 }
6537
6538 /* Ignore invalid image specifications. */
6539 if (!valid_image_p (image))
6540 continue;
6541
e037b9ec 6542 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
6543 plist = Fcopy_sequence (XCDR (image));
6544
6545 /* Compute margin and relief to draw. */
e037b9ec
GM
6546 relief = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
6547 margin = relief + max (0, tool_bar_button_margin);
5f5c8ee5 6548
e037b9ec 6549 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
6550 {
6551 /* Add a `:relief' property to the image spec if the item is
6552 selected. */
6553 if (selected_p)
6554 {
6555 plist = Fplist_put (plist, QCrelief, make_number (-relief));
6556 margin -= relief;
6557 }
6558 }
6559 else
6560 {
6561 /* If image is selected, display it pressed, i.e. with a
6562 negative relief. If it's not selected, display it with a
6563 raised relief. */
6564 plist = Fplist_put (plist, QCrelief,
6565 (selected_p
6566 ? make_number (-relief)
6567 : make_number (relief)));
6568 margin -= relief;
6569 }
6570
6571 /* Put a margin around the image. */
6572 if (margin)
6573 plist = Fplist_put (plist, QCmargin, make_number (margin));
6574
6575 /* If button is not enabled, make the image appear disabled by
6576 applying an appropriate algorithm to it. */
6577 if (!enabled_p)
6578 plist = Fplist_put (plist, QCalgorithm, Qlaplace);
6579
6580 /* Put a `display' text property on the string for the image to
6581 display. Put a `menu-item' property on the string that gives
e037b9ec 6582 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
6583 vector. */
6584 image = Fcons (Qimage, plist);
6585 props = list4 (Qdisplay, image,
e037b9ec 6586 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS)),
5f5c8ee5
GM
6587 Fadd_text_properties (make_number (string_idx),
6588 make_number (string_idx + 1),
e037b9ec 6589 props, f->desired_tool_bar_string);
5f5c8ee5 6590#undef PROP
a2889657
JB
6591 }
6592
5f5c8ee5
GM
6593 UNGCPRO;
6594}
6595
6596
e037b9ec 6597/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
6598
6599static void
e037b9ec 6600display_tool_bar_line (it)
5f5c8ee5
GM
6601 struct it *it;
6602{
6603 struct glyph_row *row = it->glyph_row;
6604 int max_x = it->last_visible_x;
6605 struct glyph *last;
6606
6607 prepare_desired_row (row);
6608 row->y = it->current_y;
6609
6610 while (it->current_x < max_x)
a2889657 6611 {
5f5c8ee5 6612 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 6613
5f5c8ee5
GM
6614 /* Get the next display element. */
6615 if (!get_next_display_element (it))
6616 break;
73af359d 6617
5f5c8ee5
GM
6618 /* Produce glyphs. */
6619 x_before = it->current_x;
6620 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
6621 PRODUCE_GLYPHS (it);
daa37602 6622
5f5c8ee5
GM
6623 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
6624 i = 0;
6625 x = x_before;
6626 while (i < nglyphs)
6627 {
6628 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
6629
6630 if (x + glyph->pixel_width > max_x)
6631 {
6632 /* Glyph doesn't fit on line. */
6633 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
6634 it->current_x = x;
6635 goto out;
6636 }
daa37602 6637
5f5c8ee5
GM
6638 ++it->hpos;
6639 x += glyph->pixel_width;
6640 ++i;
6641 }
6642
6643 /* Stop at line ends. */
6644 if (ITERATOR_AT_END_OF_LINE_P (it))
6645 break;
6646
6647 set_iterator_to_next (it);
a2889657 6648 }
a2889657 6649
5f5c8ee5 6650 out:;
a2889657 6651
5f5c8ee5
GM
6652 row->displays_text_p = row->used[TEXT_AREA] != 0;
6653 extend_face_to_end_of_line (it);
6654 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
6655 last->right_box_line_p = 1;
6656 compute_line_metrics (it);
6657
e037b9ec 6658 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
6659 if (!row->displays_text_p)
6660 {
312246d1
GM
6661 row->height = row->phys_height = it->last_visible_y - row->y;
6662 row->ascent = row->phys_ascent = 0;
5f5c8ee5
GM
6663 }
6664
6665 row->full_width_p = 1;
6666 row->continued_p = 0;
6667 row->truncated_on_left_p = 0;
6668 row->truncated_on_right_p = 0;
6669
6670 it->current_x = it->hpos = 0;
6671 it->current_y += row->height;
6672 ++it->vpos;
6673 ++it->glyph_row;
a2889657 6674}
96a410bc 6675
5f5c8ee5 6676
e037b9ec 6677/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 6678 items of frame F visible. */
96a410bc 6679
d39b6696 6680static int
e037b9ec 6681tool_bar_lines_needed (f)
5f5c8ee5 6682 struct frame *f;
d39b6696 6683{
e037b9ec 6684 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5
GM
6685 struct it it;
6686
e037b9ec
GM
6687 /* Initialize an iterator for iteration over
6688 F->desired_tool_bar_string in the tool-bar window of frame F. */
6689 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
6690 it.first_visible_x = 0;
6691 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
e037b9ec 6692 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
6693
6694 while (!ITERATOR_AT_END_P (&it))
6695 {
6696 it.glyph_row = w->desired_matrix->rows;
6697 clear_glyph_row (it.glyph_row);
e037b9ec 6698 display_tool_bar_line (&it);
5f5c8ee5
GM
6699 }
6700
6701 return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
d39b6696 6702}
96a410bc 6703
5f5c8ee5 6704
e037b9ec 6705/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
6706 height should be changed. */
6707
6708static int
e037b9ec 6709redisplay_tool_bar (f)
5f5c8ee5 6710 struct frame *f;
96a410bc 6711{
5f5c8ee5
GM
6712 struct window *w;
6713 struct it it;
6714 struct glyph_row *row;
6715 int change_height_p = 0;
6716
e037b9ec
GM
6717 /* If frame hasn't a tool-bar window or if it is zero-height, don't
6718 do anything. This means you must start with tool-bar-lines
5f5c8ee5 6719 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
6720 can turn off tool-bars by specifying tool-bar-lines zero. */
6721 if (!WINDOWP (f->tool_bar_window)
6722 || (w = XWINDOW (f->tool_bar_window),
5f5c8ee5
GM
6723 XFASTINT (w->height) == 0))
6724 return 0;
96a410bc 6725
e037b9ec
GM
6726 /* Set up an iterator for the tool-bar window. */
6727 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5
GM
6728 it.first_visible_x = 0;
6729 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
6730 row = it.glyph_row;
3450d04c 6731
e037b9ec
GM
6732 /* Build a string that represents the contents of the tool-bar. */
6733 build_desired_tool_bar_string (f);
6734 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 6735
e037b9ec 6736 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 6737 while (it.current_y < it.last_visible_y)
e037b9ec 6738 display_tool_bar_line (&it);
3450d04c 6739
e037b9ec 6740 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
6741 window, so don't do it. */
6742 w->desired_matrix->no_scrolling_p = 1;
6743 w->must_be_updated_p = 1;
3450d04c 6744
e037b9ec 6745 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
6746 {
6747 int nlines;
6748
6749 /* If there are blank lines at the end, except for a partially
6750 visible blank line at the end that is smaller than
e037b9ec 6751 CANON_Y_UNIT, change the tool-bar's height. */
5f5c8ee5
GM
6752 row = it.glyph_row - 1;
6753 if (!row->displays_text_p
6754 && row->height >= CANON_Y_UNIT (f))
6755 change_height_p = 1;
6756
e037b9ec
GM
6757 /* If row displays tool-bar items, but is partially visible,
6758 change the tool-bar's height. */
5f5c8ee5
GM
6759 if (row->displays_text_p
6760 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
6761 change_height_p = 1;
6762
e037b9ec 6763 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
6764 frame parameter. */
6765 if (change_height_p
e037b9ec 6766 && (nlines = tool_bar_lines_needed (f),
5f5c8ee5
GM
6767 nlines != XFASTINT (w->height)))
6768 {
e037b9ec 6769 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5
GM
6770 Lisp_Object frame;
6771
6772 XSETFRAME (frame, f);
6773 clear_glyph_matrix (w->desired_matrix);
6774 Fmodify_frame_parameters (frame,
e037b9ec 6775 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
6776 make_number (nlines)),
6777 Qnil));
6778 fonts_changed_p = 1;
6779 }
6780 }
3450d04c 6781
5f5c8ee5 6782 return change_height_p;
96a410bc 6783}
90adcf20 6784
5f5c8ee5 6785
e037b9ec
GM
6786/* Get information about the tool-bar item which is displayed in GLYPH
6787 on frame F. Return in *PROP_IDX the index where tool-bar item
6788 properties start in F->current_tool_bar_items. Value is zero if
6789 GLYPH doesn't display a tool-bar item. */
5f5c8ee5
GM
6790
6791int
e037b9ec 6792tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
6793 struct frame *f;
6794 struct glyph *glyph;
6795 int *prop_idx;
90adcf20 6796{
5f5c8ee5
GM
6797 Lisp_Object prop;
6798 int success_p;
6799
6800 /* Get the text property `menu-item' at pos. The value of that
6801 property is the start index of this item's properties in
e037b9ec 6802 F->current_tool_bar_items. */
5f5c8ee5 6803 prop = Fget_text_property (make_number (glyph->charpos),
e037b9ec 6804 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
6805 if (INTEGERP (prop))
6806 {
6807 *prop_idx = XINT (prop);
6808 success_p = 1;
6809 }
6810 else
6811 success_p = 0;
90adcf20 6812
5f5c8ee5
GM
6813 return success_p;
6814}
6815
6816#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 6817
feb0c42f 6818
5f5c8ee5
GM
6819\f
6820/************************************************************************
6821 Horizontal scrolling
6822 ************************************************************************/
feb0c42f 6823
5f5c8ee5
GM
6824static int hscroll_window_tree P_ ((Lisp_Object));
6825static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 6826
5f5c8ee5
GM
6827/* For all leaf windows in the window tree rooted at WINDOW, set their
6828 hscroll value so that PT is (i) visible in the window, and (ii) so
6829 that it is not within a certain margin at the window's left and
6830 right border. Value is non-zero if any window's hscroll has been
6831 changed. */
6832
6833static int
6834hscroll_window_tree (window)
6835 Lisp_Object window;
6836{
6837 int hscrolled_p = 0;
6838
6839 while (WINDOWP (window))
90adcf20 6840 {
5f5c8ee5
GM
6841 struct window *w = XWINDOW (window);
6842
6843 if (WINDOWP (w->hchild))
6844 hscrolled_p |= hscroll_window_tree (w->hchild);
6845 else if (WINDOWP (w->vchild))
6846 hscrolled_p |= hscroll_window_tree (w->vchild);
6847 else if (w->cursor.vpos >= 0)
6848 {
6849 int hscroll_margin, text_area_x, text_area_y;
6850 int text_area_width, text_area_height;
92a90e89
GM
6851 struct glyph_row *current_cursor_row
6852 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
6853 struct glyph_row *desired_cursor_row
6854 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
6855 struct glyph_row *cursor_row
6856 = (desired_cursor_row->enabled_p
6857 ? desired_cursor_row
6858 : current_cursor_row);
a2725ab2 6859
5f5c8ee5
GM
6860 window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
6861 &text_area_width, &text_area_height);
90adcf20 6862
5f5c8ee5
GM
6863 /* Scroll when cursor is inside this scroll margin. */
6864 hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
6865
6866 if ((XFASTINT (w->hscroll)
6867 && w->cursor.x < hscroll_margin)
92a90e89
GM
6868 || (cursor_row->enabled_p
6869 && cursor_row->truncated_on_right_p
5f5c8ee5 6870 && (w->cursor.x > text_area_width - hscroll_margin)))
08b610e4 6871 {
5f5c8ee5
GM
6872 struct it it;
6873 int hscroll;
6874 struct buffer *saved_current_buffer;
6875 int pt;
6876
6877 /* Find point in a display of infinite width. */
6878 saved_current_buffer = current_buffer;
6879 current_buffer = XBUFFER (w->buffer);
6880
6881 if (w == XWINDOW (selected_window))
6882 pt = BUF_PT (current_buffer);
6883 else
08b610e4 6884 {
5f5c8ee5
GM
6885 pt = marker_position (w->pointm);
6886 pt = max (BEGV, pt);
6887 pt = min (ZV, pt);
6888 }
6889
6890 /* Move iterator to pt starting at cursor_row->start in
6891 a line with infinite width. */
6892 init_to_row_start (&it, w, cursor_row);
6893 it.last_visible_x = INFINITY;
6894 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
6895 current_buffer = saved_current_buffer;
6896
6897 /* Center cursor in window. */
6898 hscroll = (max (0, it.current_x - text_area_width / 2)
6899 / CANON_X_UNIT (it.f));
6900
6901 /* Don't call Fset_window_hscroll if value hasn't
6902 changed because it will prevent redisplay
6903 optimizations. */
6904 if (XFASTINT (w->hscroll) != hscroll)
6905 {
6906 Fset_window_hscroll (window, make_number (hscroll));
6907 hscrolled_p = 1;
08b610e4 6908 }
08b610e4 6909 }
08b610e4 6910 }
a2725ab2 6911
5f5c8ee5 6912 window = w->next;
90adcf20 6913 }
cd6dfed6 6914
5f5c8ee5
GM
6915 /* Value is non-zero if hscroll of any leaf window has been changed. */
6916 return hscrolled_p;
6917}
6918
6919
6920/* Set hscroll so that cursor is visible and not inside horizontal
6921 scroll margins for all windows in the tree rooted at WINDOW. See
6922 also hscroll_window_tree above. Value is non-zero if any window's
6923 hscroll has been changed. If it has, desired matrices on the frame
6924 of WINDOW are cleared. */
6925
6926static int
6927hscroll_windows (window)
6928 Lisp_Object window;
6929{
6930 int hscrolled_p = hscroll_window_tree (window);
6931 if (hscrolled_p)
6932 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
6933 return hscrolled_p;
90adcf20 6934}
5f5c8ee5
GM
6935
6936
90adcf20 6937\f
5f5c8ee5
GM
6938/************************************************************************
6939 Redisplay
6940 ************************************************************************/
6941
6942/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
6943 to a non-zero value. This is sometimes handy to have in a debugger
6944 session. */
6945
6946#if GLYPH_DEBUG
a2889657 6947
5f5c8ee5
GM
6948/* First and last unchanged row for try_window_id. */
6949
6950int debug_first_unchanged_at_end_vpos;
6951int debug_last_unchanged_at_beg_vpos;
6952
6953/* Delta vpos and y. */
6954
6955int debug_dvpos, debug_dy;
6956
6957/* Delta in characters and bytes for try_window_id. */
6958
6959int debug_delta, debug_delta_bytes;
6960
6961/* Values of window_end_pos and window_end_vpos at the end of
6962 try_window_id. */
6963
6964int debug_end_pos, debug_end_vpos;
6965
6966/* Append a string to W->desired_matrix->method. FMT is a printf
6967 format string. A1...A9 are a supplement for a variable-length
6968 argument list. If trace_redisplay_p is non-zero also printf the
6969 resulting string to stderr. */
6970
6971static void
6972debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
6973 struct window *w;
6974 char *fmt;
6975 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
6976{
6977 char buffer[512];
6978 char *method = w->desired_matrix->method;
6979 int len = strlen (method);
6980 int size = sizeof w->desired_matrix->method;
6981 int remaining = size - len - 1;
6982
6983 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
6984 if (len && remaining)
6985 {
6986 method[len] = '|';
6987 --remaining, ++len;
6988 }
6989
6990 strncpy (method + len, buffer, remaining);
6991
6992 if (trace_redisplay_p)
6993 fprintf (stderr, "%p (%s): %s\n",
6994 w,
6995 ((BUFFERP (w->buffer)
6996 && STRINGP (XBUFFER (w->buffer)->name))
6997 ? (char *) XSTRING (XBUFFER (w->buffer)->name)->data
6998 : "no buffer"),
6999 buffer);
7000}
a2889657 7001
5f5c8ee5 7002#endif /* GLYPH_DEBUG */
90adcf20 7003
a2889657 7004
5f5c8ee5
GM
7005/* This counter is used to clear the face cache every once in a while
7006 in redisplay_internal. It is incremented for each redisplay.
7007 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
7008 cleared. */
0d231165 7009
5f5c8ee5 7010#define CLEAR_FACE_CACHE_COUNT 10000
463f6b91
RS
7011static int clear_face_cache_count;
7012
20de20dc 7013/* Record the previous terminal frame we displayed. */
5f5c8ee5
GM
7014
7015static struct frame *previous_terminal_frame;
7016
7017/* Non-zero while redisplay_internal is in progress. */
7018
7019int redisplaying_p;
7020
7021
7022/* Value is non-zero if all changes in window W, which displays
7023 current_buffer, are in the text between START and END. START is a
7024 buffer position, END is given as a distance from Z. Used in
7025 redisplay_internal for display optimization. */
7026
7027static INLINE int
7028text_outside_line_unchanged_p (w, start, end)
7029 struct window *w;
7030 int start, end;
7031{
7032 int unchanged_p = 1;
7033
7034 /* If text or overlays have changed, see where. */
7035 if (XFASTINT (w->last_modified) < MODIFF
7036 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
7037 {
7038 /* Gap in the line? */
7039 if (GPT < start || Z - GPT < end)
7040 unchanged_p = 0;
7041
7042 /* Changes start in front of the line, or end after it? */
7043 if (unchanged_p
9142dd5b
GM
7044 && (BEG_UNCHANGED < start - 1
7045 || END_UNCHANGED < end))
5f5c8ee5
GM
7046 unchanged_p = 0;
7047
7048 /* If selective display, can't optimize if changes start at the
7049 beginning of the line. */
7050 if (unchanged_p
7051 && INTEGERP (current_buffer->selective_display)
7052 && XINT (current_buffer->selective_display) > 0
9142dd5b 7053 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5
GM
7054 unchanged_p = 0;
7055 }
7056
7057 return unchanged_p;
7058}
7059
7060
7061/* Do a frame update, taking possible shortcuts into account. This is
7062 the main external entry point for redisplay.
7063
7064 If the last redisplay displayed an echo area message and that message
7065 is no longer requested, we clear the echo area or bring back the
7066 mini-buffer if that is in use. */
20de20dc 7067
a2889657
JB
7068void
7069redisplay ()
e9874cee
RS
7070{
7071 redisplay_internal (0);
7072}
7073
260a86a0
KH
7074/* Return 1 if point moved out of or into a composition. Otherwise
7075 return 0. PREV_BUF and PREV_PT are the last point buffer and
7076 position. BUF and PT are the current point buffer and position. */
7077
7078int
7079check_point_in_composition (prev_buf, prev_pt, buf, pt)
7080 struct buffer *prev_buf, *buf;
7081 int prev_pt, pt;
7082{
7083 int start, end;
7084 Lisp_Object prop;
7085 Lisp_Object buffer;
7086
7087 XSETBUFFER (buffer, buf);
7088 /* Check a composition at the last point if point moved within the
7089 same buffer. */
7090 if (prev_buf == buf)
7091 {
7092 if (prev_pt == pt)
7093 /* Point didn't move. */
7094 return 0;
7095
7096 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
7097 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
7098 && COMPOSITION_VALID_P (start, end, prop)
7099 && start < prev_pt && end > prev_pt)
7100 /* The last point was within the composition. Return 1 iff
7101 point moved out of the composition. */
7102 return (pt <= start || pt >= end);
7103 }
7104
7105 /* Check a composition at the current point. */
7106 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
7107 && find_composition (pt, -1, &start, &end, &prop, buffer)
7108 && COMPOSITION_VALID_P (start, end, prop)
7109 && start < pt && end > pt);
7110}
5f5c8ee5 7111
9142dd5b
GM
7112/* Reconsider the setting of B->clip_changed which is displayed
7113 in window W. */
7114
7115static INLINE void
7116reconsider_clip_changes (w, b)
7117 struct window *w;
7118 struct buffer *b;
7119{
7120 if (b->prevent_redisplay_optimizations_p)
7121 b->clip_changed = 1;
7122 else if (b->clip_changed
7123 && !NILP (w->window_end_valid)
7124 && w->current_matrix->buffer == b
7125 && w->current_matrix->zv == BUF_ZV (b)
7126 && w->current_matrix->begv == BUF_BEGV (b))
7127 b->clip_changed = 0;
260a86a0
KH
7128
7129 /* If display wasn't paused, and W is not a tool bar window, see if
7130 point has been moved into or out of a composition. In that case,
7131 we set b->clip_changed to 1 to force updating the screen. If
7132 b->clip_changed has already been set to 1, we can skip this
7133 check. */
7134 if (!b->clip_changed
7135 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
7136 {
7137 int pt;
7138
7139 if (w == XWINDOW (selected_window))
7140 pt = BUF_PT (current_buffer);
7141 else
7142 pt = marker_position (w->pointm);
7143
7144 if ((w->current_matrix->buffer != XBUFFER (w->buffer)
7145 || pt != w->last_point)
7146 && check_point_in_composition (w->current_matrix->buffer,
7147 w->last_point,
7148 XBUFFER (w->buffer), pt))
7149 b->clip_changed = 1;
7150 }
9142dd5b
GM
7151}
7152
7153
5f5c8ee5
GM
7154/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
7155 response to any user action; therefore, we should preserve the echo
7156 area. (Actually, our caller does that job.) Perhaps in the future
7157 avoid recentering windows if it is not necessary; currently that
7158 causes some problems. */
e9874cee
RS
7159
7160static void
7161redisplay_internal (preserve_echo_area)
7162 int preserve_echo_area;
a2889657 7163{
5f5c8ee5
GM
7164 struct window *w = XWINDOW (selected_window);
7165 struct frame *f = XFRAME (w->frame);
7166 int pause;
a2889657 7167 int must_finish = 0;
5f5c8ee5 7168 struct text_pos tlbufpos, tlendpos;
89819bdd 7169 int number_of_visible_frames;
28514cd9 7170 int count;
886bd6f2 7171 struct frame *sf = SELECTED_FRAME ();
a2889657 7172
5f5c8ee5
GM
7173 /* Non-zero means redisplay has to consider all windows on all
7174 frames. Zero means, only selected_window is considered. */
7175 int consider_all_windows_p;
7176
7177 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
7178
7179 /* No redisplay if running in batch mode or frame is not yet fully
7180 initialized, or redisplay is explicitly turned off by setting
7181 Vinhibit_redisplay. */
7182 if (noninteractive
7183 || !NILP (Vinhibit_redisplay)
7184 || !f->glyphs_initialized_p)
a2889657
JB
7185 return;
7186
5f5c8ee5
GM
7187 /* The flag redisplay_performed_directly_p is set by
7188 direct_output_for_insert when it already did the whole screen
7189 update necessary. */
7190 if (redisplay_performed_directly_p)
7191 {
7192 redisplay_performed_directly_p = 0;
7193 if (!hscroll_windows (selected_window))
7194 return;
7195 }
7196
15f0cf78
RS
7197#ifdef USE_X_TOOLKIT
7198 if (popup_activated ())
7199 return;
7200#endif
7201
28514cd9 7202 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 7203 if (redisplaying_p)
735c094c
KH
7204 return;
7205
28514cd9
GM
7206 /* Record a function that resets redisplaying_p to its old value
7207 when we leave this function. */
7208 count = specpdl_ptr - specpdl;
7209 record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
7210 ++redisplaying_p;
7211
8b32d885
RS
7212 retry:
7213
9142dd5b
GM
7214 reconsider_clip_changes (w, current_buffer);
7215
5f5c8ee5
GM
7216 /* If new fonts have been loaded that make a glyph matrix adjustment
7217 necessary, do it. */
7218 if (fonts_changed_p)
7219 {
7220 adjust_glyphs (NULL);
7221 ++windows_or_buffers_changed;
7222 fonts_changed_p = 0;
7223 }
7224
886bd6f2
GM
7225 if (! FRAME_WINDOW_P (sf)
7226 && previous_terminal_frame != sf)
20de20dc 7227 {
5f5c8ee5
GM
7228 /* Since frames on an ASCII terminal share the same display
7229 area, displaying a different frame means redisplay the whole
7230 thing. */
20de20dc 7231 windows_or_buffers_changed++;
886bd6f2
GM
7232 SET_FRAME_GARBAGED (sf);
7233 XSETFRAME (Vterminal_frame, sf);
20de20dc 7234 }
886bd6f2 7235 previous_terminal_frame = sf;
20de20dc 7236
5f5c8ee5
GM
7237 /* Set the visible flags for all frames. Do this before checking
7238 for resized or garbaged frames; they want to know if their frames
7239 are visible. See the comment in frame.h for
7240 FRAME_SAMPLE_VISIBILITY. */
d724d989 7241 {
35f56f96 7242 Lisp_Object tail, frame;
d724d989 7243
89819bdd
RS
7244 number_of_visible_frames = 0;
7245
35f56f96 7246 FOR_EACH_FRAME (tail, frame)
f82aff7c 7247 {
5f5c8ee5
GM
7248 struct frame *f = XFRAME (frame);
7249
7250 FRAME_SAMPLE_VISIBILITY (f);
7251 if (FRAME_VISIBLE_P (f))
7252 ++number_of_visible_frames;
7253 clear_desired_matrices (f);
f82aff7c 7254 }
d724d989
JB
7255 }
7256
44fa5b1e 7257 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 7258 do_pending_window_change (1);
a2889657 7259
5f5c8ee5 7260 /* Clear frames marked as garbaged. */
44fa5b1e 7261 if (frame_garbaged)
c6e89d6c 7262 clear_garbaged_frames ();
a2889657 7263
e037b9ec 7264 /* Build menubar and tool-bar items. */
f82aff7c
RS
7265 prepare_menu_bars ();
7266
28995e67 7267 if (windows_or_buffers_changed)
a2889657
JB
7268 update_mode_lines++;
7269
538f13d4
RS
7270 /* Detect case that we need to write or remove a star in the mode line. */
7271 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
7272 {
7273 w->update_mode_line = Qt;
7274 if (buffer_shared > 1)
7275 update_mode_lines++;
7276 }
7277
5f5c8ee5 7278 /* If %c is in the mode line, update it if needed. */
28995e67
RS
7279 if (!NILP (w->column_number_displayed)
7280 /* This alternative quickly identifies a common case
7281 where no change is needed. */
7282 && !(PT == XFASTINT (w->last_point)
8850a573
RS
7283 && XFASTINT (w->last_modified) >= MODIFF
7284 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
7285 && XFASTINT (w->column_number_displayed) != current_column ())
7286 w->update_mode_line = Qt;
7287
44fa5b1e 7288 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 7289
5f5c8ee5
GM
7290 /* The variable buffer_shared is set in redisplay_window and
7291 indicates that we redisplay a buffer in different windows. See
7292 there. */
7293 consider_all_windows_p = update_mode_lines || buffer_shared > 1;
a2889657
JB
7294
7295 /* If specs for an arrow have changed, do thorough redisplay
7296 to ensure we remove any arrow that should no longer exist. */
d45de95b 7297 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 7298 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 7299 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 7300
90adcf20
RS
7301 /* Normally the message* functions will have already displayed and
7302 updated the echo area, but the frame may have been trashed, or
7303 the update may have been preempted, so display the echo area
c6e89d6c
GM
7304 again here. Checking both message buffers captures the case that
7305 the echo area should be cleared. */
7306 if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
90adcf20 7307 {
c6e89d6c 7308 int window_height_changed_p = echo_area_display (0);
90adcf20 7309 must_finish = 1;
dd2eb166 7310
c6e89d6c
GM
7311 if (fonts_changed_p)
7312 goto retry;
7313 else if (window_height_changed_p)
7314 {
7315 consider_all_windows_p = 1;
7316 ++update_mode_lines;
7317 ++windows_or_buffers_changed;
9142dd5b
GM
7318
7319 /* If window configuration was changed, frames may have been
7320 marked garbaged. Clear them or we will experience
7321 surprises wrt scrolling. */
7322 if (frame_garbaged)
7323 clear_garbaged_frames ();
c6e89d6c 7324 }
90adcf20 7325 }
dd2eb166
GM
7326 else if (w == XWINDOW (minibuf_window)
7327 && (current_buffer->clip_changed
7328 || XFASTINT (w->last_modified) < MODIFF
7329 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 7330 && resize_mini_window (w, 0))
c6e89d6c
GM
7331 {
7332 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
7333 showing if its contents might have changed. */
7334 must_finish = 1;
7335 consider_all_windows_p = 1;
c6e89d6c 7336 ++windows_or_buffers_changed;
dd2eb166 7337 ++update_mode_lines;
9142dd5b
GM
7338
7339 /* If window configuration was changed, frames may have been
7340 marked garbaged. Clear them or we will experience
7341 surprises wrt scrolling. */
7342 if (frame_garbaged)
7343 clear_garbaged_frames ();
c6e89d6c
GM
7344 }
7345
90adcf20 7346
5f5c8ee5
GM
7347 /* If showing the region, and mark has changed, we must redisplay
7348 the whole window. The assignment to this_line_start_pos prevents
7349 the optimization directly below this if-statement. */
bd66d1ba
RS
7350 if (((!NILP (Vtransient_mark_mode)
7351 && !NILP (XBUFFER (w->buffer)->mark_active))
7352 != !NILP (w->region_showing))
82d04750
JB
7353 || (!NILP (w->region_showing)
7354 && !EQ (w->region_showing,
7355 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
7356 CHARPOS (this_line_start_pos) = 0;
7357
7358 /* Optimize the case that only the line containing the cursor in the
7359 selected window has changed. Variables starting with this_ are
7360 set in display_line and record information about the line
7361 containing the cursor. */
7362 tlbufpos = this_line_start_pos;
7363 tlendpos = this_line_end_pos;
7364 if (!consider_all_windows_p
7365 && CHARPOS (tlbufpos) > 0
7366 && NILP (w->update_mode_line)
73af359d 7367 && !current_buffer->clip_changed
44fa5b1e 7368 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 7369 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 7370 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
7371 && this_line_buffer == current_buffer
7372 && current_buffer == XBUFFER (w->buffer)
265a9e55 7373 && NILP (w->force_start)
5f5c8ee5
GM
7374 /* Point must be on the line that we have info recorded about. */
7375 && PT >= CHARPOS (tlbufpos)
7376 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
7377 /* All text outside that line, including its final newline,
7378 must be unchanged */
5f5c8ee5
GM
7379 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
7380 CHARPOS (tlendpos)))
7381 {
7382 if (CHARPOS (tlbufpos) > BEGV
7383 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
7384 && (CHARPOS (tlbufpos) == ZV
7385 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
7386 /* Former continuation line has disappeared by becoming empty */
7387 goto cancel;
7388 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 7389 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
7390 || MINI_WINDOW_P (w))
7391 {
1c9241f5
KH
7392 /* We have to handle the case of continuation around a
7393 wide-column character (See the comment in indent.c around
7394 line 885).
7395
7396 For instance, in the following case:
7397
7398 -------- Insert --------
7399 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
7400 J_I_ ==> J_I_ `^^' are cursors.
7401 ^^ ^^
7402 -------- --------
7403
7404 As we have to redraw the line above, we should goto cancel. */
7405
5f5c8ee5
GM
7406 struct it it;
7407 int line_height_before = this_line_pixel_height;
7408
7409 /* Note that start_display will handle the case that the
7410 line starting at tlbufpos is a continuation lines. */
7411 start_display (&it, w, tlbufpos);
7412
7413 /* Implementation note: It this still necessary? */
7414 if (it.current_x != this_line_start_x)
1c9241f5
KH
7415 goto cancel;
7416
5f5c8ee5
GM
7417 TRACE ((stderr, "trying display optimization 1\n"));
7418 w->cursor.vpos = -1;
a2889657 7419 overlay_arrow_seen = 0;
5f5c8ee5
GM
7420 it.vpos = this_line_vpos;
7421 it.current_y = this_line_y;
7422 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
7423 display_line (&it);
7424
a2889657 7425 /* If line contains point, is not continued,
5f5c8ee5
GM
7426 and ends at same distance from eob as before, we win */
7427 if (w->cursor.vpos >= 0
7428 /* Line is not continued, otherwise this_line_start_pos
7429 would have been set to 0 in display_line. */
7430 && CHARPOS (this_line_start_pos)
7431 /* Line ends as before. */
7432 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
7433 /* Line has same height as before. Otherwise other lines
7434 would have to be shifted up or down. */
7435 && this_line_pixel_height == line_height_before)
a2889657 7436 {
5f5c8ee5
GM
7437 /* If this is not the window's last line, we must adjust
7438 the charstarts of the lines below. */
7439 if (it.current_y < it.last_visible_y)
7440 {
7441 struct glyph_row *row
7442 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
7443 int delta, delta_bytes;
7444
7445 if (Z - CHARPOS (tlendpos) == ZV)
7446 {
7447 /* This line ends at end of (accessible part of)
7448 buffer. There is no newline to count. */
7449 delta = (Z
7450 - CHARPOS (tlendpos)
7451 - MATRIX_ROW_START_CHARPOS (row));
7452 delta_bytes = (Z_BYTE
7453 - BYTEPOS (tlendpos)
7454 - MATRIX_ROW_START_BYTEPOS (row));
7455 }
7456 else
7457 {
7458 /* This line ends in a newline. Must take
7459 account of the newline and the rest of the
7460 text that follows. */
7461 delta = (Z
7462 - CHARPOS (tlendpos)
7463 - MATRIX_ROW_START_CHARPOS (row));
7464 delta_bytes = (Z_BYTE
7465 - BYTEPOS (tlendpos)
7466 - MATRIX_ROW_START_BYTEPOS (row));
7467 }
7468
7469 increment_glyph_matrix_buffer_positions (w->current_matrix,
7470 this_line_vpos + 1,
7471 w->current_matrix->nrows,
7472 delta, delta_bytes);
85bcef6c 7473 }
46db8486 7474
5f5c8ee5
GM
7475 /* If this row displays text now but previously didn't,
7476 or vice versa, w->window_end_vpos may have to be
7477 adjusted. */
7478 if ((it.glyph_row - 1)->displays_text_p)
7479 {
7480 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
7481 XSETINT (w->window_end_vpos, this_line_vpos);
7482 }
7483 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
7484 && this_line_vpos > 0)
7485 XSETINT (w->window_end_vpos, this_line_vpos - 1);
7486 w->window_end_valid = Qnil;
7487
7488 /* Update hint: No need to try to scroll in update_window. */
7489 w->desired_matrix->no_scrolling_p = 1;
7490
7491#if GLYPH_DEBUG
7492 *w->desired_matrix->method = 0;
7493 debug_method_add (w, "optimization 1");
7494#endif
a2889657
JB
7495 goto update;
7496 }
7497 else
7498 goto cancel;
7499 }
5f5c8ee5
GM
7500 else if (/* Cursor position hasn't changed. */
7501 PT == XFASTINT (w->last_point)
b6f0fe04
RS
7502 /* Make sure the cursor was last displayed
7503 in this window. Otherwise we have to reposition it. */
5f5c8ee5
GM
7504 && 0 <= w->cursor.vpos
7505 && XINT (w->height) > w->cursor.vpos)
a2889657
JB
7506 {
7507 if (!must_finish)
7508 {
c6e89d6c 7509 do_pending_window_change (1);
5f5c8ee5
GM
7510
7511 /* We used to always goto end_of_redisplay here, but this
7512 isn't enough if we have a blinking cursor. */
7513 if (w->cursor_off_p == w->last_cursor_off_p)
7514 goto end_of_redisplay;
a2889657
JB
7515 }
7516 goto update;
7517 }
8b51f1e3
KH
7518 /* If highlighting the region, or if the cursor is in the echo area,
7519 then we can't just move the cursor. */
bd66d1ba
RS
7520 else if (! (!NILP (Vtransient_mark_mode)
7521 && !NILP (current_buffer->mark_active))
293a54ce
RS
7522 && (w == XWINDOW (current_buffer->last_selected_window)
7523 || highlight_nonselected_windows)
8b51f1e3 7524 && NILP (w->region_showing)
8f897821 7525 && NILP (Vshow_trailing_whitespace)
8b51f1e3 7526 && !cursor_in_echo_area)
a2889657 7527 {
5f5c8ee5
GM
7528 struct it it;
7529 struct glyph_row *row;
7530
7531 /* Skip from tlbufpos to PT and see where it is. Note that
7532 PT may be in invisible text. If so, we will end at the
7533 next visible position. */
7534 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
7535 NULL, DEFAULT_FACE_ID);
7536 it.current_x = this_line_start_x;
7537 it.current_y = this_line_y;
7538 it.vpos = this_line_vpos;
7539
7540 /* The call to move_it_to stops in front of PT, but
7541 moves over before-strings. */
7542 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
7543
7544 if (it.vpos == this_line_vpos
7545 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
7546 row->enabled_p))
a2889657 7547 {
5f5c8ee5
GM
7548 xassert (this_line_vpos == it.vpos);
7549 xassert (this_line_y == it.current_y);
7550 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
a2889657
JB
7551 goto update;
7552 }
7553 else
7554 goto cancel;
7555 }
5f5c8ee5 7556
a2889657 7557 cancel:
5f5c8ee5
GM
7558 /* Text changed drastically or point moved off of line. */
7559 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
7560 }
7561
5f5c8ee5
GM
7562 CHARPOS (this_line_start_pos) = 0;
7563 consider_all_windows_p |= buffer_shared > 1;
7564 ++clear_face_cache_count;
a2889657 7565
5f5c8ee5
GM
7566
7567 /* Build desired matrices. If consider_all_windows_p is non-zero,
7568 do it for all windows on all frames. Otherwise do it for
7569 selected_window, only. */
463f6b91 7570
5f5c8ee5 7571 if (consider_all_windows_p)
a2889657 7572 {
35f56f96 7573 Lisp_Object tail, frame;
a2889657 7574
5f5c8ee5
GM
7575 /* Clear the face cache eventually. */
7576 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 7577 {
5f5c8ee5 7578 clear_face_cache (0);
463f6b91
RS
7579 clear_face_cache_count = 0;
7580 }
31b24551 7581
5f5c8ee5
GM
7582 /* Recompute # windows showing selected buffer. This will be
7583 incremented each time such a window is displayed. */
a2889657
JB
7584 buffer_shared = 0;
7585
35f56f96 7586 FOR_EACH_FRAME (tail, frame)
30c566e4 7587 {
5f5c8ee5 7588 struct frame *f = XFRAME (frame);
886bd6f2 7589 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 7590 {
5f5c8ee5
GM
7591 /* Mark all the scroll bars to be removed; we'll redeem
7592 the ones we want when we redisplay their windows. */
9769686d
RS
7593 if (condemn_scroll_bars_hook)
7594 (*condemn_scroll_bars_hook) (f);
30c566e4 7595
f21ef775 7596 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 7597 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 7598
5f5c8ee5
GM
7599 /* Any scroll bars which redisplay_windows should have
7600 nuked should now go away. */
9769686d
RS
7601 if (judge_scroll_bars_hook)
7602 (*judge_scroll_bars_hook) (f);
7603 }
30c566e4 7604 }
a2889657 7605 }
886bd6f2
GM
7606 else if (FRAME_VISIBLE_P (sf)
7607 && !FRAME_OBSCURED_P (sf))
5f5c8ee5
GM
7608 redisplay_window (selected_window, 1);
7609
7610
7611 /* Compare desired and current matrices, perform output. */
7612
7613update:
7614
7615 /* If fonts changed, display again. */
7616 if (fonts_changed_p)
7617 goto retry;
a2889657 7618
a2889657
JB
7619 /* Prevent various kinds of signals during display update.
7620 stdio is not robust about handling signals,
7621 which can cause an apparent I/O error. */
7622 if (interrupt_input)
7623 unrequest_sigio ();
7624 stop_polling ();
7625
5f5c8ee5 7626 if (consider_all_windows_p)
a2889657
JB
7627 {
7628 Lisp_Object tail;
92a90e89
GM
7629 struct frame *f;
7630 int hscrolled_p;
a2889657
JB
7631
7632 pause = 0;
92a90e89 7633 hscrolled_p = 0;
a2889657 7634
92a90e89 7635 /* See if we have to hscroll. */
9472f927 7636 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
92a90e89
GM
7637 if (FRAMEP (XCAR (tail)))
7638 {
7639 f = XFRAME (XCAR (tail));
7640
7641 if ((FRAME_WINDOW_P (f)
886bd6f2 7642 || f == sf)
92a90e89
GM
7643 && FRAME_VISIBLE_P (f)
7644 && !FRAME_OBSCURED_P (f)
7645 && hscroll_windows (f->root_window))
7646 hscrolled_p = 1;
7647 }
7648
7649 if (hscrolled_p)
7650 goto retry;
a2889657 7651
92a90e89
GM
7652 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
7653 {
9472f927 7654 if (!FRAMEP (XCAR (tail)))
a2889657
JB
7655 continue;
7656
9472f927 7657 f = XFRAME (XCAR (tail));
1af9f229 7658
886bd6f2 7659 if ((FRAME_WINDOW_P (f) || f == sf)
f21ef775 7660 && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
a2889657 7661 {
5f5c8ee5
GM
7662 /* Mark all windows as to be updated. */
7663 set_window_update_flags (XWINDOW (f->root_window), 1);
44fa5b1e 7664 pause |= update_frame (f, 0, 0);
a2889657 7665 if (!pause)
efc63ef0
RS
7666 {
7667 mark_window_display_accurate (f->root_window, 1);
7668 if (frame_up_to_date_hook != 0)
7669 (*frame_up_to_date_hook) (f);
7670 }
a2889657
JB
7671 }
7672 }
7673 }
7674 else
6e8290aa 7675 {
886bd6f2
GM
7676 if (FRAME_VISIBLE_P (sf)
7677 && !FRAME_OBSCURED_P (sf))
5f5c8ee5 7678 {
92a90e89
GM
7679 if (hscroll_windows (selected_window))
7680 goto retry;
7681
5f5c8ee5 7682 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 7683 pause = update_frame (sf, 0, 0);
5f5c8ee5 7684 }
4d641a15
KH
7685 else
7686 pause = 0;
d724d989 7687
8de2d90b 7688 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
7689 function. If the echo area is on another frame, that may
7690 have put text on a frame other than the selected one, so the
7691 above call to update_frame would not have caught it. Catch
8de2d90b
JB
7692 it here. */
7693 {
84faf44c 7694 Lisp_Object mini_window;
5f5c8ee5 7695 struct frame *mini_frame;
84faf44c 7696
886bd6f2 7697 mini_window = FRAME_MINIBUF_WINDOW (sf);
84faf44c 7698 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
8de2d90b 7699
886bd6f2 7700 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
5f5c8ee5
GM
7701 {
7702 XWINDOW (mini_window)->must_be_updated_p = 1;
7703 pause |= update_frame (mini_frame, 0, 0);
7704 if (!pause && hscroll_windows (mini_window))
7705 goto retry;
7706 }
8de2d90b 7707 }
6e8290aa 7708 }
a2889657 7709
5f5c8ee5
GM
7710 /* If display was paused because of pending input, make sure we do a
7711 thorough update the next time. */
a2889657
JB
7712 if (pause)
7713 {
5f5c8ee5
GM
7714 /* Prevent the optimization at the beginning of
7715 redisplay_internal that tries a single-line update of the
7716 line containing the cursor in the selected window. */
7717 CHARPOS (this_line_start_pos) = 0;
7718
7719 /* Let the overlay arrow be updated the next time. */
265a9e55 7720 if (!NILP (last_arrow_position))
a2889657
JB
7721 {
7722 last_arrow_position = Qt;
7723 last_arrow_string = Qt;
7724 }
5f5c8ee5
GM
7725
7726 /* If we pause after scrolling, some rows in the current
7727 matrices of some windows are not valid. */
7728 if (!WINDOW_FULL_WIDTH_P (w)
7729 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
7730 update_mode_lines = 1;
7731 }
7732
5f5c8ee5
GM
7733 /* Now text on frame agrees with windows, so put info into the
7734 windows for partial redisplay to follow. */
a2889657
JB
7735 if (!pause)
7736 {
7737 register struct buffer *b = XBUFFER (w->buffer);
7738
9142dd5b
GM
7739 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
7740 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
7741 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
7742 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
a2889657 7743
5f5c8ee5 7744 if (consider_all_windows_p)
886bd6f2 7745 mark_window_display_accurate (FRAME_ROOT_WINDOW (sf), 1);
a2889657
JB
7746 else
7747 {
5f5c8ee5
GM
7748 XSETFASTINT (w->last_point, BUF_PT (b));
7749 w->last_cursor = w->cursor;
7750 w->last_cursor_off_p = w->cursor_off_p;
7751
28995e67 7752 b->clip_changed = 0;
9142dd5b 7753 b->prevent_redisplay_optimizations_p = 0;
a2889657 7754 w->update_mode_line = Qnil;
c2213350 7755 XSETFASTINT (w->last_modified, BUF_MODIFF (b));
8850a573 7756 XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
538f13d4
RS
7757 w->last_had_star
7758 = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
7759 ? Qt : Qnil);
3ee4159a
RS
7760
7761 /* Record if we are showing a region, so can make sure to
7762 update it fully at next redisplay. */
7763 w->region_showing = (!NILP (Vtransient_mark_mode)
293a54ce
RS
7764 && (w == XWINDOW (current_buffer->last_selected_window)
7765 || highlight_nonselected_windows)
3ee4159a
RS
7766 && !NILP (XBUFFER (w->buffer)->mark_active)
7767 ? Fmarker_position (XBUFFER (w->buffer)->mark)
7768 : Qnil);
7769
d2f84654 7770 w->window_end_valid = w->buffer;
d45de95b 7771 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657 7772 last_arrow_string = Voverlay_arrow_string;
efc63ef0 7773 if (frame_up_to_date_hook != 0)
886bd6f2 7774 (*frame_up_to_date_hook) (sf);
9142dd5b
GM
7775
7776 w->current_matrix->buffer = b;
7777 w->current_matrix->begv = BUF_BEGV (b);
7778 w->current_matrix->zv = BUF_ZV (b);
a2889657 7779 }
5f5c8ee5 7780
a2889657
JB
7781 update_mode_lines = 0;
7782 windows_or_buffers_changed = 0;
7783 }
7784
5f5c8ee5
GM
7785 /* Start SIGIO interrupts coming again. Having them off during the
7786 code above makes it less likely one will discard output, but not
7787 impossible, since there might be stuff in the system buffer here.
a2889657 7788 But it is much hairier to try to do anything about that. */
a2889657
JB
7789 if (interrupt_input)
7790 request_sigio ();
7791 start_polling ();
7792
5f5c8ee5
GM
7793 /* If a frame has become visible which was not before, redisplay
7794 again, so that we display it. Expose events for such a frame
7795 (which it gets when becoming visible) don't call the parts of
7796 redisplay constructing glyphs, so simply exposing a frame won't
7797 display anything in this case. So, we have to display these
7798 frames here explicitly. */
11c52c4f
RS
7799 if (!pause)
7800 {
7801 Lisp_Object tail, frame;
7802 int new_count = 0;
7803
7804 FOR_EACH_FRAME (tail, frame)
7805 {
7806 int this_is_visible = 0;
8e83f802
RS
7807
7808 if (XFRAME (frame)->visible)
7809 this_is_visible = 1;
7810 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
7811 if (XFRAME (frame)->visible)
7812 this_is_visible = 1;
11c52c4f
RS
7813
7814 if (this_is_visible)
7815 new_count++;
7816 }
7817
89819bdd 7818 if (new_count != number_of_visible_frames)
11c52c4f
RS
7819 windows_or_buffers_changed++;
7820 }
7821
44fa5b1e 7822 /* Change frame size now if a change is pending. */
c6e89d6c 7823 do_pending_window_change (1);
d8e242fd 7824
8b32d885
RS
7825 /* If we just did a pending size change, or have additional
7826 visible frames, redisplay again. */
3c8c72e0 7827 if (windows_or_buffers_changed && !pause)
8b32d885 7828 goto retry;
5f5c8ee5
GM
7829
7830 end_of_redisplay:;
c6e89d6c 7831
28514cd9 7832 unbind_to (count, Qnil);
a2889657
JB
7833}
7834
5f5c8ee5
GM
7835
7836/* Redisplay, but leave alone any recent echo area message unless
7837 another message has been requested in its place.
a2889657
JB
7838
7839 This is useful in situations where you need to redisplay but no
7840 user action has occurred, making it inappropriate for the message
7841 area to be cleared. See tracking_off and
7842 wait_reading_process_input for examples of these situations. */
7843
8991bb31 7844void
a2889657
JB
7845redisplay_preserve_echo_area ()
7846{
c6e89d6c 7847 if (!NILP (echo_area_buffer[1]))
a2889657 7848 {
c6e89d6c
GM
7849 /* We have a previously displayed message, but no current
7850 message. Redisplay the previous message. */
7851 display_last_displayed_message_p = 1;
e9874cee 7852 redisplay_internal (1);
c6e89d6c 7853 display_last_displayed_message_p = 0;
a2889657
JB
7854 }
7855 else
e9874cee 7856 redisplay_internal (1);
a2889657
JB
7857}
7858
5f5c8ee5 7859
28514cd9
GM
7860/* Function registered with record_unwind_protect in
7861 redisplay_internal. Clears the flag indicating that a redisplay is
7862 in progress. */
7863
7864static Lisp_Object
7865unwind_redisplay (old_redisplaying_p)
7866 Lisp_Object old_redisplaying_p;
7867{
7868 redisplaying_p = XFASTINT (old_redisplaying_p);
c6e89d6c 7869 return Qnil;
28514cd9
GM
7870}
7871
7872
5f5c8ee5
GM
7873/* Mark the display of windows in the window tree rooted at WINDOW as
7874 accurate or inaccurate. If FLAG is non-zero mark display of WINDOW
7875 as accurate. If FLAG is zero arrange for WINDOW to be redisplayed
7876 the next time redisplay_internal is called. */
7877
a2889657 7878void
5f5c8ee5 7879mark_window_display_accurate (window, accurate_p)
a2889657 7880 Lisp_Object window;
5f5c8ee5 7881 int accurate_p;
a2889657 7882{
5f5c8ee5
GM
7883 struct window *w;
7884
7885 for (; !NILP (window); window = w->next)
a2889657
JB
7886 {
7887 w = XWINDOW (window);
7888
5f5c8ee5 7889 if (BUFFERP (w->buffer))
bd66d1ba 7890 {
5f5c8ee5
GM
7891 struct buffer *b = XBUFFER (w->buffer);
7892
c2213350 7893 XSETFASTINT (w->last_modified,
5f5c8ee5 7894 accurate_p ? BUF_MODIFF (b) : 0);
8850a573 7895 XSETFASTINT (w->last_overlay_modified,
5f5c8ee5
GM
7896 accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
7897 w->last_had_star = (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)
7898 ? Qt : Qnil);
bd66d1ba 7899
5f5c8ee5
GM
7900#if 0 /* I don't think this is necessary because display_line does it.
7901 Let's check it. */
bd66d1ba
RS
7902 /* Record if we are showing a region, so can make sure to
7903 update it fully at next redisplay. */
5f5c8ee5
GM
7904 w->region_showing
7905 = (!NILP (Vtransient_mark_mode)
7906 && (w == XWINDOW (current_buffer->last_selected_window)
7907 || highlight_nonselected_windows)
7908 && (!NILP (b->mark_active)
7909 ? Fmarker_position (b->mark)
7910 : Qnil));
7911#endif
7912
7913 if (accurate_p)
7914 {
7915 b->clip_changed = 0;
9142dd5b
GM
7916 b->prevent_redisplay_optimizations_p = 0;
7917 w->current_matrix->buffer = b;
7918 w->current_matrix->begv = BUF_BEGV (b);
7919 w->current_matrix->zv = BUF_ZV (b);
5f5c8ee5
GM
7920 w->last_cursor = w->cursor;
7921 w->last_cursor_off_p = w->cursor_off_p;
7922 if (w == XWINDOW (selected_window))
7923 w->last_point = BUF_PT (b);
7924 else
7925 w->last_point = XMARKER (w->pointm)->charpos;
7926 }
bd66d1ba
RS
7927 }
7928
d2f84654 7929 w->window_end_valid = w->buffer;
a2889657
JB
7930 w->update_mode_line = Qnil;
7931
265a9e55 7932 if (!NILP (w->vchild))
5f5c8ee5 7933 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 7934 if (!NILP (w->hchild))
5f5c8ee5 7935 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
7936 }
7937
5f5c8ee5 7938 if (accurate_p)
a2889657 7939 {
d45de95b 7940 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
7941 last_arrow_string = Voverlay_arrow_string;
7942 }
7943 else
7944 {
5f5c8ee5
GM
7945 /* Force a thorough redisplay the next time by setting
7946 last_arrow_position and last_arrow_string to t, which is
7947 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
7948 last_arrow_position = Qt;
7949 last_arrow_string = Qt;
7950 }
7951}
5f5c8ee5
GM
7952
7953
7954/* Return value in display table DP (Lisp_Char_Table *) for character
7955 C. Since a display table doesn't have any parent, we don't have to
7956 follow parent. Do not call this function directly but use the
7957 macro DISP_CHAR_VECTOR. */
7958
7959Lisp_Object
7960disp_char_vector (dp, c)
7961 struct Lisp_Char_Table *dp;
7962 int c;
7963{
7964 int code[4], i;
7965 Lisp_Object val;
7966
7967 if (SINGLE_BYTE_CHAR_P (c))
7968 return (dp->contents[c]);
7969
7970 SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
260a86a0
KH
7971 if (code[1] < 32)
7972 code[1] = -1;
7973 else if (code[2] < 32)
7974 code[2] = -1;
5f5c8ee5
GM
7975
7976 /* Here, the possible range of code[0] (== charset ID) is
7977 128..max_charset. Since the top level char table contains data
7978 for multibyte characters after 256th element, we must increment
7979 code[0] by 128 to get a correct index. */
7980 code[0] += 128;
7981 code[3] = -1; /* anchor */
7982
7983 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
7984 {
7985 val = dp->contents[code[i]];
7986 if (!SUB_CHAR_TABLE_P (val))
7987 return (NILP (val) ? dp->defalt : val);
7988 }
7989
7990 /* Here, val is a sub char table. We return the default value of
7991 it. */
7992 return (dp->defalt);
7993}
7994
7995
a2889657 7996\f
5f5c8ee5
GM
7997/***********************************************************************
7998 Window Redisplay
7999 ***********************************************************************/
a2725ab2 8000
5f5c8ee5 8001/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
8002
8003static void
5f5c8ee5
GM
8004redisplay_windows (window)
8005 Lisp_Object window;
90adcf20 8006{
5f5c8ee5
GM
8007 while (!NILP (window))
8008 {
8009 struct window *w = XWINDOW (window);
8010
8011 if (!NILP (w->hchild))
8012 redisplay_windows (w->hchild);
8013 else if (!NILP (w->vchild))
8014 redisplay_windows (w->vchild);
8015 else
8016 redisplay_window (window, 0);
a2725ab2 8017
5f5c8ee5
GM
8018 window = w->next;
8019 }
8020}
8021
8022
8023/* Set cursor position of W. PT is assumed to be displayed in ROW.
8024 DELTA is the number of bytes by which positions recorded in ROW
8025 differ from current buffer positions. */
8026
8027void
8028set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
8029 struct window *w;
8030 struct glyph_row *row;
8031 struct glyph_matrix *matrix;
8032 int delta, delta_bytes, dy, dvpos;
8033{
8034 struct glyph *glyph = row->glyphs[TEXT_AREA];
8035 struct glyph *end = glyph + row->used[TEXT_AREA];
8036 int x = row->x;
8037 int pt_old = PT - delta;
8038
8039 /* Skip over glyphs not having an object at the start of the row.
8040 These are special glyphs like truncation marks on terminal
8041 frames. */
8042 if (row->displays_text_p)
8043 while (glyph < end
8044 && !glyph->object
8045 && glyph->charpos < 0)
8046 {
8047 x += glyph->pixel_width;
8048 ++glyph;
8049 }
8050
8051 while (glyph < end
8052 && glyph->object
8053 && (!BUFFERP (glyph->object)
8054 || glyph->charpos < pt_old))
8055 {
8056 x += glyph->pixel_width;
8057 ++glyph;
8058 }
8059
8060 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
8061 w->cursor.x = x;
8062 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
8063 w->cursor.y = row->y + dy;
8064
8065 if (w == XWINDOW (selected_window))
8066 {
8067 if (!row->continued_p
8068 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
8069 && row->x == 0)
8070 {
8071 this_line_buffer = XBUFFER (w->buffer);
8072
8073 CHARPOS (this_line_start_pos)
8074 = MATRIX_ROW_START_CHARPOS (row) + delta;
8075 BYTEPOS (this_line_start_pos)
8076 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
8077
8078 CHARPOS (this_line_end_pos)
8079 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
8080 BYTEPOS (this_line_end_pos)
8081 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
8082
8083 this_line_y = w->cursor.y;
8084 this_line_pixel_height = row->height;
8085 this_line_vpos = w->cursor.vpos;
8086 this_line_start_x = row->x;
8087 }
8088 else
8089 CHARPOS (this_line_start_pos) = 0;
8090 }
8091}
8092
8093
8094/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
8095 start STARTP. Sets the window start of WINDOW to that position.
8096
8097 We assume that the window's buffer is really current. */
5f5c8ee5
GM
8098
8099static INLINE struct text_pos
8100run_window_scroll_functions (window, startp)
8101 Lisp_Object window;
8102 struct text_pos startp;
8103{
8104 struct window *w = XWINDOW (window);
8105 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
8106
8107 if (current_buffer != XBUFFER (w->buffer))
8108 abort ();
8109
5f5c8ee5
GM
8110 if (!NILP (Vwindow_scroll_functions))
8111 {
8112 run_hook_with_args_2 (Qwindow_scroll_functions, window,
8113 make_number (CHARPOS (startp)));
8114 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
8115 /* In case the hook functions switch buffers. */
8116 if (current_buffer != XBUFFER (w->buffer))
8117 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8118 }
90adcf20 8119
5f5c8ee5
GM
8120 return startp;
8121}
8122
8123
8124/* Modify the desired matrix of window W and W->vscroll so that the
8125 line containing the cursor is fully visible. */
8126
8127static void
8128make_cursor_line_fully_visible (w)
8129 struct window *w;
8130{
8131 struct glyph_matrix *matrix;
8132 struct glyph_row *row;
045dee35 8133 int header_line_height;
5f5c8ee5
GM
8134
8135 /* It's not always possible to find the cursor, e.g, when a window
8136 is full of overlay strings. Don't do anything in that case. */
8137 if (w->cursor.vpos < 0)
8138 return;
8139
8140 matrix = w->desired_matrix;
8141 row = MATRIX_ROW (matrix, w->cursor.vpos);
8142
8143 /* If row->y == top y of window display area, the window isn't tall
8144 enough to display a single line. There is nothing we can do
8145 about it. */
045dee35
GM
8146 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
8147 if (row->y == header_line_height)
5f5c8ee5
GM
8148 return;
8149
8150 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
8151 {
8152 int dy = row->height - row->visible_height;
8153 w->vscroll = 0;
8154 w->cursor.y += dy;
8155 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
8156 }
8157 else if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
8158 {
8159 int dy = - (row->height - row->visible_height);
8160 w->vscroll = dy;
8161 w->cursor.y += dy;
8162 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
8163 }
8164
8165 /* When we change the cursor y-position of the selected window,
8166 change this_line_y as well so that the display optimization for
8167 the cursor line of the selected window in redisplay_internal uses
8168 the correct y-position. */
8169 if (w == XWINDOW (selected_window))
8170 this_line_y = w->cursor.y;
8171}
8172
8173
8174/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
8175 non-zero means only WINDOW is redisplayed in redisplay_internal.
8176 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
8177 in redisplay_window to bring a partially visible line into view in
8178 the case that only the cursor has moved.
8179
8180 Value is
8181
8182 1 if scrolling succeeded
8183
8184 0 if scrolling didn't find point.
8185
8186 -1 if new fonts have been loaded so that we must interrupt
8187 redisplay, adjust glyph matrices, and try again. */
8188
8189static int
8190try_scrolling (window, just_this_one_p, scroll_conservatively,
8191 scroll_step, temp_scroll_step)
8192 Lisp_Object window;
8193 int just_this_one_p;
8194 int scroll_conservatively, scroll_step;
8195 int temp_scroll_step;
8196{
8197 struct window *w = XWINDOW (window);
8198 struct frame *f = XFRAME (w->frame);
8199 struct text_pos scroll_margin_pos;
8200 struct text_pos pos;
8201 struct text_pos startp;
8202 struct it it;
8203 Lisp_Object window_end;
8204 int this_scroll_margin;
8205 int dy = 0;
8206 int scroll_max;
8207 int line_height, rc;
8208 int amount_to_scroll = 0;
8209 Lisp_Object aggressive;
8210 int height;
8211
8212#if GLYPH_DEBUG
8213 debug_method_add (w, "try_scrolling");
78614721 8214#endif
5f5c8ee5
GM
8215
8216 SET_TEXT_POS_FROM_MARKER (startp, w->start);
8217
8218 /* Compute scroll margin height in pixels. We scroll when point is
8219 within this distance from the top or bottom of the window. */
8220 if (scroll_margin > 0)
90adcf20 8221 {
5f5c8ee5
GM
8222 this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
8223 this_scroll_margin *= CANON_Y_UNIT (f);
8224 }
8225 else
8226 this_scroll_margin = 0;
8227
8228 /* Compute how much we should try to scroll maximally to bring point
8229 into view. */
8230 if (scroll_step)
8231 scroll_max = scroll_step;
8232 else if (scroll_conservatively)
8233 scroll_max = scroll_conservatively;
8234 else if (temp_scroll_step)
8235 scroll_max = temp_scroll_step;
8236 else if (NUMBERP (current_buffer->scroll_down_aggressively)
8237 || NUMBERP (current_buffer->scroll_up_aggressively))
8238 /* We're trying to scroll because of aggressive scrolling
8239 but no scroll_step is set. Choose an arbitrary one. Maybe
8240 there should be a variable for this. */
8241 scroll_max = 10;
8242 else
8243 scroll_max = 0;
8244 scroll_max *= CANON_Y_UNIT (f);
8245
8246 /* Decide whether we have to scroll down. Start at the window end
8247 and move this_scroll_margin up to find the position of the scroll
8248 margin. */
8249 window_end = Fwindow_end (window, Qt);
8250 CHARPOS (scroll_margin_pos) = XINT (window_end);
8251 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
8252 if (this_scroll_margin)
8253 {
8254 start_display (&it, w, scroll_margin_pos);
8255 move_it_vertically (&it, - this_scroll_margin);
8256 scroll_margin_pos = it.current.pos;
8257 }
8258
8259 if (PT >= CHARPOS (scroll_margin_pos))
8260 {
8261 int y0;
8262
8263 /* Point is in the scroll margin at the bottom of the window, or
8264 below. Compute a new window start that makes point visible. */
8265
8266 /* Compute the distance from the scroll margin to PT.
8267 Give up if the distance is greater than scroll_max. */
8268 start_display (&it, w, scroll_margin_pos);
8269 y0 = it.current_y;
8270 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8271 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8272 line_height = (it.max_ascent + it.max_descent
8273 ? it.max_ascent + it.max_descent
8274 : last_height);
8275 dy = it.current_y + line_height - y0;
8276 if (dy > scroll_max)
8277 return 0;
8278
8279 /* Move the window start down. If scrolling conservatively,
8280 move it just enough down to make point visible. If
8281 scroll_step is set, move it down by scroll_step. */
8282 start_display (&it, w, startp);
8283
8284 if (scroll_conservatively)
8285 amount_to_scroll = dy;
8286 else if (scroll_step || temp_scroll_step)
8287 amount_to_scroll = scroll_max;
8288 else
90adcf20 8289 {
5f5c8ee5
GM
8290 aggressive = current_buffer->scroll_down_aggressively;
8291 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8292 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8293 if (NUMBERP (aggressive))
8294 amount_to_scroll = XFLOATINT (aggressive) * height;
8295 }
a2725ab2 8296
5f5c8ee5
GM
8297 if (amount_to_scroll <= 0)
8298 return 0;
a2725ab2 8299
5f5c8ee5
GM
8300 move_it_vertically (&it, amount_to_scroll);
8301 startp = it.current.pos;
8302 }
8303 else
8304 {
8305 /* See if point is inside the scroll margin at the top of the
8306 window. */
8307 scroll_margin_pos = startp;
8308 if (this_scroll_margin)
8309 {
8310 start_display (&it, w, startp);
8311 move_it_vertically (&it, this_scroll_margin);
8312 scroll_margin_pos = it.current.pos;
8313 }
8314
8315 if (PT < CHARPOS (scroll_margin_pos))
8316 {
8317 /* Point is in the scroll margin at the top of the window or
8318 above what is displayed in the window. */
8319 int y0;
8320
8321 /* Compute the vertical distance from PT to the scroll
8322 margin position. Give up if distance is greater than
8323 scroll_max. */
8324 SET_TEXT_POS (pos, PT, PT_BYTE);
8325 start_display (&it, w, pos);
8326 y0 = it.current_y;
8327 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
8328 it.last_visible_y, -1,
8329 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8330 dy = it.current_y - y0;
8331 if (dy > scroll_max)
8332 return 0;
8333
8334 /* Compute new window start. */
8335 start_display (&it, w, startp);
8336
8337 if (scroll_conservatively)
8338 amount_to_scroll = dy;
8339 else if (scroll_step || temp_scroll_step)
8340 amount_to_scroll = scroll_max;
538f13d4 8341 else
5f5c8ee5
GM
8342 {
8343 aggressive = current_buffer->scroll_up_aggressively;
8344 height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
045dee35 8345 - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
8346 if (NUMBERP (aggressive))
8347 amount_to_scroll = XFLOATINT (aggressive) * height;
8348 }
a2725ab2 8349
5f5c8ee5
GM
8350 if (amount_to_scroll <= 0)
8351 return 0;
8352
8353 move_it_vertically (&it, - amount_to_scroll);
8354 startp = it.current.pos;
90adcf20
RS
8355 }
8356 }
a2889657 8357
5f5c8ee5
GM
8358 /* Run window scroll functions. */
8359 startp = run_window_scroll_functions (window, startp);
90adcf20 8360
5f5c8ee5
GM
8361 /* Display the window. Give up if new fonts are loaded, or if point
8362 doesn't appear. */
8363 if (!try_window (window, startp))
8364 rc = -1;
8365 else if (w->cursor.vpos < 0)
8366 {
8367 clear_glyph_matrix (w->desired_matrix);
8368 rc = 0;
8369 }
8370 else
8371 {
8372 /* Maybe forget recorded base line for line number display. */
8373 if (!just_this_one_p
8374 || current_buffer->clip_changed
9142dd5b 8375 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5
GM
8376 w->base_line_number = Qnil;
8377
8378 /* If cursor ends up on a partially visible line, shift display
8379 lines up or down. */
8380 make_cursor_line_fully_visible (w);
8381 rc = 1;
8382 }
8383
8384 return rc;
a2889657
JB
8385}
8386
5f5c8ee5
GM
8387
8388/* Compute a suitable window start for window W if display of W starts
8389 on a continuation line. Value is non-zero if a new window start
8390 was computed.
8391
8392 The new window start will be computed, based on W's width, starting
8393 from the start of the continued line. It is the start of the
8394 screen line with the minimum distance from the old start W->start. */
8395
8396static int
8397compute_window_start_on_continuation_line (w)
8398 struct window *w;
1f1ff51d 8399{
5f5c8ee5
GM
8400 struct text_pos pos, start_pos;
8401 int window_start_changed_p = 0;
1f1ff51d 8402
5f5c8ee5 8403 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 8404
5f5c8ee5
GM
8405 /* If window start is on a continuation line... Window start may be
8406 < BEGV in case there's invisible text at the start of the
8407 buffer (M-x rmail, for example). */
8408 if (CHARPOS (start_pos) > BEGV
8409 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 8410 {
5f5c8ee5
GM
8411 struct it it;
8412 struct glyph_row *row;
f3751a65
GM
8413
8414 /* Handle the case that the window start is out of range. */
8415 if (CHARPOS (start_pos) < BEGV)
8416 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
8417 else if (CHARPOS (start_pos) > ZV)
8418 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
5f5c8ee5
GM
8419
8420 /* Find the start of the continued line. This should be fast
8421 because scan_buffer is fast (newline cache). */
045dee35 8422 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
8423 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
8424 row, DEFAULT_FACE_ID);
8425 reseat_at_previous_visible_line_start (&it);
8426
8427 /* If the line start is "too far" away from the window start,
8428 say it takes too much time to compute a new window start. */
8429 if (CHARPOS (start_pos) - IT_CHARPOS (it)
8430 < XFASTINT (w->height) * XFASTINT (w->width))
8431 {
8432 int min_distance, distance;
8433
8434 /* Move forward by display lines to find the new window
8435 start. If window width was enlarged, the new start can
8436 be expected to be > the old start. If window width was
8437 decreased, the new window start will be < the old start.
8438 So, we're looking for the display line start with the
8439 minimum distance from the old window start. */
8440 pos = it.current.pos;
8441 min_distance = INFINITY;
8442 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
8443 distance < min_distance)
8444 {
8445 min_distance = distance;
8446 pos = it.current.pos;
8447 move_it_by_lines (&it, 1, 0);
8448 }
8449
8450 /* Set the window start there. */
8451 SET_MARKER_FROM_TEXT_POS (w->start, pos);
8452 window_start_changed_p = 1;
8453 }
1f1ff51d 8454 }
5f5c8ee5
GM
8455
8456 return window_start_changed_p;
1f1ff51d
KH
8457}
8458
5f5c8ee5
GM
8459
8460/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
8461 selected_window is redisplayed. */
90adcf20 8462
a2889657 8463static void
5f5c8ee5 8464redisplay_window (window, just_this_one_p)
a2889657 8465 Lisp_Object window;
5f5c8ee5 8466 int just_this_one_p;
a2889657 8467{
5f5c8ee5
GM
8468 struct window *w = XWINDOW (window);
8469 struct frame *f = XFRAME (w->frame);
8470 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 8471 struct buffer *old = current_buffer;
5f5c8ee5 8472 struct text_pos lpoint, opoint, startp;
e481f960 8473 int update_mode_line;
5f5c8ee5
GM
8474 int tem;
8475 struct it it;
8476 /* Record it now because it's overwritten. */
8477 int current_matrix_up_to_date_p = 0;
5ba50c51 8478 int really_switched_buffer = 0;
5f5c8ee5 8479 int temp_scroll_step = 0;
2e54982e 8480 int count = specpdl_ptr - specpdl;
a2889657 8481
5f5c8ee5
GM
8482 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8483 opoint = lpoint;
a2889657 8484
5f5c8ee5
GM
8485 /* W must be a leaf window here. */
8486 xassert (!NILP (w->buffer));
8487#if GLYPH_DEBUG
8488 *w->desired_matrix->method = 0;
8489#endif
2e54982e
RS
8490
8491 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
8492
8493 reconsider_clip_changes (w, buffer);
8494
5f5c8ee5
GM
8495 /* Has the mode line to be updated? */
8496 update_mode_line = (!NILP (w->update_mode_line)
8497 || update_mode_lines
8498 || buffer->clip_changed);
8de2d90b
JB
8499
8500 if (MINI_WINDOW_P (w))
8501 {
5f5c8ee5 8502 if (w == XWINDOW (echo_area_window)
c6e89d6c 8503 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
8504 {
8505 if (update_mode_line)
8506 /* We may have to update a tty frame's menu bar or a
e037b9ec 8507 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
8508 goto finish_menu_bars;
8509 else
8510 /* We've already displayed the echo area glyphs in this window. */
8511 goto finish_scroll_bars;
8512 }
73af359d 8513 else if (w != XWINDOW (minibuf_window))
8de2d90b 8514 {
5f5c8ee5
GM
8515 /* W is a mini-buffer window, but it's not the currently
8516 active one, so clear it. */
8517 int yb = window_text_bottom_y (w);
8518 struct glyph_row *row;
8519 int y;
8520
8521 for (y = 0, row = w->desired_matrix->rows;
8522 y < yb;
8523 y += row->height, ++row)
8524 blank_row (w, row, y);
88f22aff 8525 goto finish_scroll_bars;
8de2d90b
JB
8526 }
8527 }
a2889657 8528
5f5c8ee5
GM
8529 /* Otherwise set up data on this window; select its buffer and point
8530 value. */
e481f960 8531 if (update_mode_line)
5ba50c51 8532 {
5f5c8ee5
GM
8533 /* Really select the buffer, for the sake of buffer-local
8534 variables. */
5ba50c51
RS
8535 set_buffer_internal_1 (XBUFFER (w->buffer));
8536 really_switched_buffer = 1;
8537 }
e481f960
RS
8538 else
8539 set_buffer_temp (XBUFFER (w->buffer));
5f5c8ee5
GM
8540 SET_TEXT_POS (opoint, PT, PT_BYTE);
8541
8542 current_matrix_up_to_date_p
8543 = (!NILP (w->window_end_valid)
8544 && !current_buffer->clip_changed
8545 && XFASTINT (w->last_modified) >= MODIFF
8546 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 8547
5f5c8ee5
GM
8548 /* When windows_or_buffers_changed is non-zero, we can't rely on
8549 the window end being valid, so set it to nil there. */
8550 if (windows_or_buffers_changed)
8551 {
8552 /* If window starts on a continuation line, maybe adjust the
8553 window start in case the window's width changed. */
8554 if (XMARKER (w->start)->buffer == current_buffer)
8555 compute_window_start_on_continuation_line (w);
8556
8557 w->window_end_valid = Qnil;
8558 }
12adba34 8559
5f5c8ee5
GM
8560 /* Some sanity checks. */
8561 CHECK_WINDOW_END (w);
8562 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 8563 abort ();
5f5c8ee5 8564 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 8565 abort ();
a2889657 8566
28995e67
RS
8567 /* If %c is in mode line, update it if needed. */
8568 if (!NILP (w->column_number_displayed)
8569 /* This alternative quickly identifies a common case
8570 where no change is needed. */
8571 && !(PT == XFASTINT (w->last_point)
8850a573
RS
8572 && XFASTINT (w->last_modified) >= MODIFF
8573 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
28995e67
RS
8574 && XFASTINT (w->column_number_displayed) != current_column ())
8575 update_mode_line = 1;
8576
5f5c8ee5
GM
8577 /* Count number of windows showing the selected buffer. An indirect
8578 buffer counts as its base buffer. */
8579 if (!just_this_one_p)
42640f83
RS
8580 {
8581 struct buffer *current_base, *window_base;
8582 current_base = current_buffer;
8583 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
8584 if (current_base->base_buffer)
8585 current_base = current_base->base_buffer;
8586 if (window_base->base_buffer)
8587 window_base = window_base->base_buffer;
8588 if (current_base == window_base)
8589 buffer_shared++;
8590 }
a2889657 8591
5f5c8ee5
GM
8592 /* Point refers normally to the selected window. For any other
8593 window, set up appropriate value. */
a2889657
JB
8594 if (!EQ (window, selected_window))
8595 {
12adba34
RS
8596 int new_pt = XMARKER (w->pointm)->charpos;
8597 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 8598 if (new_pt < BEGV)
a2889657 8599 {
f67a0f51 8600 new_pt = BEGV;
12adba34
RS
8601 new_pt_byte = BEGV_BYTE;
8602 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 8603 }
f67a0f51 8604 else if (new_pt > (ZV - 1))
a2889657 8605 {
f67a0f51 8606 new_pt = ZV;
12adba34
RS
8607 new_pt_byte = ZV_BYTE;
8608 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 8609 }
5f5c8ee5 8610
f67a0f51 8611 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 8612 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
8613 }
8614
f4faa47c 8615 /* If any of the character widths specified in the display table
5f5c8ee5
GM
8616 have changed, invalidate the width run cache. It's true that
8617 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
8618 redisplay goes (non-fatally) haywire when the display table is
8619 changed, so why should we worry about doing any better? */
8620 if (current_buffer->width_run_cache)
8621 {
f908610f 8622 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
8623
8624 if (! disptab_matches_widthtab (disptab,
8625 XVECTOR (current_buffer->width_table)))
8626 {
8627 invalidate_region_cache (current_buffer,
8628 current_buffer->width_run_cache,
8629 BEG, Z);
8630 recompute_width_table (current_buffer, disptab);
8631 }
8632 }
8633
a2889657 8634 /* If window-start is screwed up, choose a new one. */
a2889657
JB
8635 if (XMARKER (w->start)->buffer != current_buffer)
8636 goto recenter;
8637
5f5c8ee5 8638 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 8639
cf0df6ab
RS
8640 /* If someone specified a new starting point but did not insist,
8641 check whether it can be used. */
cfad01b4
GM
8642 if (!NILP (w->optional_new_start)
8643 && CHARPOS (startp) >= BEGV
8644 && CHARPOS (startp) <= ZV)
cf0df6ab
RS
8645 {
8646 w->optional_new_start = Qnil;
5f5c8ee5
GM
8647 /* This takes a mini-buffer prompt into account. */
8648 start_display (&it, w, startp);
8649 move_it_to (&it, PT, 0, it.last_visible_y, -1,
8650 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
8651 if (IT_CHARPOS (it) == PT)
cf0df6ab
RS
8652 w->force_start = Qt;
8653 }
8654
8de2d90b 8655 /* Handle case where place to start displaying has been specified,
aa6d10fa 8656 unless the specified location is outside the accessible range. */
9472f927
GM
8657 if (!NILP (w->force_start)
8658 || w->frozen_window_start_p)
a2889657 8659 {
e63574d7 8660 w->force_start = Qnil;
5f5c8ee5 8661 w->vscroll = 0;
b5174a51 8662 w->window_end_valid = Qnil;
5f5c8ee5
GM
8663
8664 /* Forget any recorded base line for line number display. */
8665 if (!current_matrix_up_to_date_p
8666 || current_buffer->clip_changed)
8667 w->base_line_number = Qnil;
8668
75c43375
RS
8669 /* Redisplay the mode line. Select the buffer properly for that.
8670 Also, run the hook window-scroll-functions
8671 because we have scrolled. */
e63574d7
RS
8672 /* Note, we do this after clearing force_start because
8673 if there's an error, it is better to forget about force_start
8674 than to get into an infinite loop calling the hook functions
8675 and having them get more errors. */
75c43375
RS
8676 if (!update_mode_line
8677 || ! NILP (Vwindow_scroll_functions))
e481f960 8678 {
5ba50c51
RS
8679 if (!really_switched_buffer)
8680 {
8681 set_buffer_temp (old);
8682 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 8683 really_switched_buffer = 1;
5ba50c51 8684 }
5f5c8ee5 8685
e481f960
RS
8686 update_mode_line = 1;
8687 w->update_mode_line = Qt;
5f5c8ee5 8688 startp = run_window_scroll_functions (window, startp);
e481f960 8689 }
5f5c8ee5 8690
c2213350 8691 XSETFASTINT (w->last_modified, 0);
8850a573 8692 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5
GM
8693 if (CHARPOS (startp) < BEGV)
8694 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
8695 else if (CHARPOS (startp) > ZV)
8696 SET_TEXT_POS (startp, ZV, ZV_BYTE);
8697
8698 /* Redisplay, then check if cursor has been set during the
8699 redisplay. Give up if new fonts were loaded. */
8700 if (!try_window (window, startp))
8701 {
8702 w->force_start = Qt;
8703 clear_glyph_matrix (w->desired_matrix);
8704 goto restore_buffers;
8705 }
8706
9472f927 8707 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5
GM
8708 {
8709 /* If point does not appear, or on a line that is not fully
8710 visible, move point so it does appear. The desired
8711 matrix has been built above, so we can use it. */
8712 int height = window_box_height (w) / 2;
8713 struct glyph_row *row = MATRIX_ROW (w->desired_matrix, 0);
8714
8715 while (row->y < height)
8716 ++row;
8717
8718 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
8719 MATRIX_ROW_START_BYTEPOS (row));
8720
90adcf20 8721 if (w != XWINDOW (selected_window))
12adba34 8722 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
8723 else if (current_buffer == old)
8724 SET_TEXT_POS (lpoint, PT, PT_BYTE);
8725
8726 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
8727
8728 /* If we are highlighting the region, then we just changed
8729 the region, so redisplay to show it. */
df0b5ea1
RS
8730 if (!NILP (Vtransient_mark_mode)
8731 && !NILP (current_buffer->mark_active))
6f27fa9b 8732 {
5f5c8ee5
GM
8733 clear_glyph_matrix (w->desired_matrix);
8734 if (!try_window (window, startp))
8735 goto restore_buffers;
6f27fa9b 8736 }
a2889657 8737 }
5f5c8ee5
GM
8738
8739 make_cursor_line_fully_visible (w);
8740#if GLYPH_DEBUG
8741 debug_method_add (w, "forced window start");
8742#endif
a2889657
JB
8743 goto done;
8744 }
8745
5f5c8ee5
GM
8746 /* Handle case where text has not changed, only point, and it has
8747 not moved off the frame. */
8748 if (current_matrix_up_to_date_p
8749 /* Point may be in this window. */
8750 && PT >= CHARPOS (startp)
8751 /* If we don't check this, we are called to move the cursor in a
8752 horizontally split window with a current matrix that doesn't
8753 fit the display. */
8754 && !windows_or_buffers_changed
8755 /* Selective display hasn't changed. */
8756 && !current_buffer->clip_changed
b1aa6cb3
RS
8757 /* If force-mode-line-update was called, really redisplay;
8758 that's how redisplay is forced after e.g. changing
8759 buffer-invisibility-spec. */
632ab665 8760 && NILP (w->update_mode_line)
5f5c8ee5
GM
8761 /* Can't use this case if highlighting a region. When a
8762 region exists, cursor movement has to do more than just
8763 set the cursor. */
8764 && !(!NILP (Vtransient_mark_mode)
8765 && !NILP (current_buffer->mark_active))
bd66d1ba 8766 && NILP (w->region_showing)
8f897821 8767 && NILP (Vshow_trailing_whitespace)
5f5c8ee5
GM
8768 /* Right after splitting windows, last_point may be nil. */
8769 && INTEGERP (w->last_point)
8770 /* This code is not used for mini-buffer for the sake of the case
8771 of redisplaying to replace an echo area message; since in
8772 that case the mini-buffer contents per se are usually
8773 unchanged. This code is of no real use in the mini-buffer
8774 since the handling of this_line_start_pos, etc., in redisplay
8775 handles the same cases. */
d45de95b 8776 && !EQ (window, minibuf_window)
5f5c8ee5
GM
8777 /* When splitting windows or for new windows, it happens that
8778 redisplay is called with a nil window_end_vpos or one being
8779 larger than the window. This should really be fixed in
8780 window.c. I don't have this on my list, now, so we do
8781 approximately the same as the old redisplay code. --gerd. */
8782 && INTEGERP (w->window_end_vpos)
8783 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
8784 && (FRAME_WINDOW_P (f)
8785 || !MARKERP (Voverlay_arrow_position)
377dbd97 8786 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
a2889657 8787 {
5f5c8ee5
GM
8788 int this_scroll_margin;
8789 struct glyph_row *row;
8790 int scroll_p;
a2889657 8791
5f5c8ee5
GM
8792#if GLYPH_DEBUG
8793 debug_method_add (w, "cursor movement");
8794#endif
9afd2168 8795
5f5c8ee5
GM
8796 /* Scroll if point within this distance from the top or bottom
8797 of the window. This is a pixel value. */
8798 this_scroll_margin = max (0, scroll_margin);
8799 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
8800 this_scroll_margin *= CANON_Y_UNIT (f);
8801
8802 /* Start with the row the cursor was displayed during the last
8803 not paused redisplay. Give up if that row is not valid. */
8804 if (w->last_cursor.vpos >= w->current_matrix->nrows)
8805 goto try_to_scroll;
8806 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
8807 if (row->mode_line_p)
8808 ++row;
8809 if (!row->enabled_p)
8810 goto try_to_scroll;
8811
8812 scroll_p = 0;
8813 if (PT > XFASTINT (w->last_point))
8814 {
8815 /* Point has moved forward. */
8816 int last_y = window_text_bottom_y (w) - this_scroll_margin;
8817
8818 while ((MATRIX_ROW_END_CHARPOS (row) < PT
8819 /* The end position of a row equals the start
8820 position of the next row. If PT is there, we
8821 would rather display it in the next line, except
8822 when this line ends in ZV. */
8823 || (MATRIX_ROW_END_CHARPOS (row) == PT
8824 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
8825 || !row->ends_at_zv_p)))
8826 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
8827 {
8828 xassert (row->enabled_p);
8829 ++row;
8830 }
9afd2168 8831
5f5c8ee5
GM
8832 /* If within the scroll margin, scroll. Note that
8833 MATRIX_ROW_BOTTOM_Y gives the pixel position at which the
8834 next line would be drawn, and that this_scroll_margin can
8835 be zero. */
8836 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
8837 || PT > MATRIX_ROW_END_CHARPOS (row)
8838 /* Line is completely visible last line in window and PT
8839 is to be set in the next line. */
8840 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
8841 && PT == MATRIX_ROW_END_CHARPOS (row)
8842 && !row->ends_at_zv_p
8843 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
8844 scroll_p = 1;
8845 }
8846 else if (PT < XFASTINT (w->last_point))
a2889657 8847 {
5f5c8ee5
GM
8848 /* Cursor has to be moved backward. Note that PT >=
8849 CHARPOS (startp) because of the outer if-statement. */
8850 while (!row->mode_line_p
8851 && (MATRIX_ROW_START_CHARPOS (row) > PT
8852 || (MATRIX_ROW_START_CHARPOS (row) == PT
8853 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
8854 && (row->y > this_scroll_margin
8855 || CHARPOS (startp) == BEGV))
a2889657 8856 {
5f5c8ee5
GM
8857 xassert (row->enabled_p);
8858 --row;
a2889657 8859 }
abb4c08f 8860
5f5c8ee5
GM
8861 /* Consider the following case: Window starts at BEGV, there
8862 is invisible, intangible text at BEGV, so that display
8863 starts at some point START > BEGV. It can happen that
8864 we are called with PT somewhere between BEGV and START.
8865 Try to handle that case. */
8866 if (row < w->current_matrix->rows
8867 || row->mode_line_p)
8868 {
8869 row = w->current_matrix->rows;
8870 if (row->mode_line_p)
8871 ++row;
8872 }
8873
8874 /* Due to newlines in overlay strings, we may have to skip
8875 forward over overlay strings. */
8876 while (MATRIX_ROW_END_CHARPOS (row) == PT
8877 && MATRIX_ROW_ENDS_IN_OVERLAY_STRING_P (row)
8878 && !row->ends_at_zv_p)
8879 ++row;
8880
8881 /* If within the scroll margin, scroll. */
8882 if (row->y < this_scroll_margin
8883 && CHARPOS (startp) != BEGV)
8884 scroll_p = 1;
8885 }
8886
8887 /* if PT is not in the glyph row, give up. */
8888 if (PT < MATRIX_ROW_START_CHARPOS (row)
8889 || PT > MATRIX_ROW_END_CHARPOS (row))
8890 goto try_to_scroll;
8891
8892 /* If we end up in a partially visible line, let's make it fully
8893 visible. This can be done most easily by using the existing
8894 scrolling code. */
8895 if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
8896 {
8897 temp_scroll_step = 1;
8898 goto try_to_scroll;
a2889657 8899 }
5f5c8ee5
GM
8900 else if (scroll_p)
8901 goto try_to_scroll;
8902
8903 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
8904 goto done;
a2889657 8905 }
5f5c8ee5 8906
a2889657
JB
8907 /* If current starting point was originally the beginning of a line
8908 but no longer is, find a new starting point. */
265a9e55 8909 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
8910 && !(CHARPOS (startp) <= BEGV
8911 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 8912 {
5f5c8ee5
GM
8913#if GLYPH_DEBUG
8914 debug_method_add (w, "recenter 1");
8915#endif
a2889657
JB
8916 goto recenter;
8917 }
5f5c8ee5
GM
8918
8919 /* Try scrolling with try_window_id. */
9142dd5b
GM
8920 else if (/* Windows and buffers haven't changed. */
8921 !windows_or_buffers_changed
5f5c8ee5
GM
8922 /* Window must be either use window-based redisplay or
8923 be full width. */
8924 && (FRAME_WINDOW_P (f)
c59c668a 8925 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)))
5f5c8ee5
GM
8926 && !MINI_WINDOW_P (w)
8927 /* Point is not known NOT to appear in window. */
8928 && PT >= CHARPOS (startp)
a2889657 8929 && XFASTINT (w->last_modified)
5f5c8ee5
GM
8930 /* Window is not hscrolled. */
8931 && XFASTINT (w->hscroll) == 0
8932 /* Selective display has not changed. */
8933 && !current_buffer->clip_changed
8934 /* Current matrix is up to date. */
8935 && !NILP (w->window_end_valid)
8936 /* Can't use this case if highlighting a region because
8937 a cursor movement will do more than just set the cursor. */
bd66d1ba
RS
8938 && !(!NILP (Vtransient_mark_mode)
8939 && !NILP (current_buffer->mark_active))
8940 && NILP (w->region_showing)
8f897821 8941 && NILP (Vshow_trailing_whitespace)
5f5c8ee5 8942 /* Overlay arrow position and string not changed. */
d45de95b 8943 && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
a2889657 8944 && EQ (last_arrow_string, Voverlay_arrow_string)
5f5c8ee5
GM
8945 /* Value is > 0 if update has been done, it is -1 if we
8946 know that the same window start will not work. It is 0
8947 if unsuccessful for some other reason. */
8948 && (tem = try_window_id (w)) != 0)
a2889657 8949 {
5f5c8ee5
GM
8950#if GLYPH_DEBUG
8951 debug_method_add (w, "try_window_id");
8952#endif
8953
8954 if (fonts_changed_p)
8955 goto restore_buffers;
a2889657
JB
8956 if (tem > 0)
8957 goto done;
5f5c8ee5
GM
8958 /* Otherwise try_window_id has returned -1 which means that we
8959 don't want the alternative below this comment to execute. */
a2889657 8960 }
5f5c8ee5
GM
8961 else if (CHARPOS (startp) >= BEGV
8962 && CHARPOS (startp) <= ZV
8963 && PT >= CHARPOS (startp)
8964 && (CHARPOS (startp) < ZV
e9874cee 8965 /* Avoid starting at end of buffer. */
5f5c8ee5 8966 || CHARPOS (startp) == BEGV
8850a573
RS
8967 || (XFASTINT (w->last_modified) >= MODIFF
8968 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 8969 {
5f5c8ee5
GM
8970#if GLYPH_DEBUG
8971 debug_method_add (w, "same window start");
8972#endif
8973
8974 /* Try to redisplay starting at same place as before.
8975 If point has not moved off frame, accept the results. */
8976 if (!current_matrix_up_to_date_p
8977 /* Don't use try_window_reusing_current_matrix in this case
8978 because it can have changed the buffer. */
8979 || !NILP (Vwindow_scroll_functions)
8980 || MINI_WINDOW_P (w)
8981 || !try_window_reusing_current_matrix (w))
8982 {
8983 IF_DEBUG (debug_method_add (w, "1"));
8984 try_window (window, startp);
8985 }
8986
8987 if (fonts_changed_p)
8988 goto restore_buffers;
8989
8990 if (w->cursor.vpos >= 0)
aa6d10fa 8991 {
5f5c8ee5
GM
8992 if (!just_this_one_p
8993 || current_buffer->clip_changed
9142dd5b 8994 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
8995 /* Forget any recorded base line for line number display. */
8996 w->base_line_number = Qnil;
5f5c8ee5
GM
8997
8998 make_cursor_line_fully_visible (w);
aa6d10fa
RS
8999 goto done;
9000 }
a2889657 9001 else
5f5c8ee5 9002 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
9003 }
9004
5f5c8ee5
GM
9005 try_to_scroll:
9006
c2213350 9007 XSETFASTINT (w->last_modified, 0);
8850a573 9008 XSETFASTINT (w->last_overlay_modified, 0);
5f5c8ee5 9009
e481f960
RS
9010 /* Redisplay the mode line. Select the buffer properly for that. */
9011 if (!update_mode_line)
9012 {
5ba50c51
RS
9013 if (!really_switched_buffer)
9014 {
9015 set_buffer_temp (old);
9016 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 9017 really_switched_buffer = 1;
5ba50c51 9018 }
e481f960
RS
9019 update_mode_line = 1;
9020 w->update_mode_line = Qt;
9021 }
a2889657 9022
5f5c8ee5
GM
9023 /* Try to scroll by specified few lines. */
9024 if ((scroll_conservatively
9025 || scroll_step
9026 || temp_scroll_step
9027 || NUMBERP (current_buffer->scroll_up_aggressively)
9028 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 9029 && !current_buffer->clip_changed
5f5c8ee5
GM
9030 && CHARPOS (startp) >= BEGV
9031 && CHARPOS (startp) <= ZV)
0789adb2 9032 {
5f5c8ee5
GM
9033 /* The function returns -1 if new fonts were loaded, 1 if
9034 successful, 0 if not successful. */
9035 int rc = try_scrolling (window, just_this_one_p,
9036 scroll_conservatively,
9037 scroll_step,
9038 temp_scroll_step);
9039 if (rc > 0)
9040 goto done;
9041 else if (rc < 0)
9042 goto restore_buffers;
9043 }
f9c8af06 9044
5f5c8ee5 9045 /* Finally, just choose place to start which centers point */
5936754e 9046
5f5c8ee5 9047 recenter:
44173109 9048
5f5c8ee5
GM
9049#if GLYPH_DEBUG
9050 debug_method_add (w, "recenter");
9051#endif
0789adb2 9052
5f5c8ee5 9053 /* w->vscroll = 0; */
0789adb2 9054
5f5c8ee5
GM
9055 /* Forget any previously recorded base line for line number display. */
9056 if (!current_matrix_up_to_date_p
9057 || current_buffer->clip_changed)
9058 w->base_line_number = Qnil;
9059
9060 /* Move backward half the height of the window. */
9061 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
9062 it.current_y = it.last_visible_y;
9063 move_it_vertically_backward (&it, it.last_visible_y / 2);
9064 xassert (IT_CHARPOS (it) >= BEGV);
9065
9066 /* The function move_it_vertically_backward may move over more
9067 than the specified y-distance. If it->w is small, e.g. a
9068 mini-buffer window, we may end up in front of the window's
9069 display area. Start displaying at the start of the line
9070 containing PT in this case. */
9071 if (it.current_y <= 0)
9072 {
9073 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
9074 move_it_vertically (&it, 0);
9075 xassert (IT_CHARPOS (it) <= PT);
9076 it.current_y = 0;
0789adb2
RS
9077 }
9078
5f5c8ee5
GM
9079 it.current_x = it.hpos = 0;
9080
9081 /* Set startp here explicitly in case that helps avoid an infinite loop
9082 in case the window-scroll-functions functions get errors. */
9083 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
9084
9085 /* Run scroll hooks. */
9086 startp = run_window_scroll_functions (window, it.current.pos);
9087
9088 /* Redisplay the window. */
9089 if (!current_matrix_up_to_date_p
9090 || windows_or_buffers_changed
9091 /* Don't use try_window_reusing_current_matrix in this case
9092 because it can have changed the buffer. */
9093 || !NILP (Vwindow_scroll_functions)
9094 || !just_this_one_p
9095 || MINI_WINDOW_P (w)
9096 || !try_window_reusing_current_matrix (w))
9097 try_window (window, startp);
9098
9099 /* If new fonts have been loaded (due to fontsets), give up. We
9100 have to start a new redisplay since we need to re-adjust glyph
9101 matrices. */
9102 if (fonts_changed_p)
9103 goto restore_buffers;
9104
9105 /* If cursor did not appear assume that the middle of the window is
9106 in the first line of the window. Do it again with the next line.
9107 (Imagine a window of height 100, displaying two lines of height
9108 60. Moving back 50 from it->last_visible_y will end in the first
9109 line.) */
9110 if (w->cursor.vpos < 0)
a2889657 9111 {
5f5c8ee5
GM
9112 if (!NILP (w->window_end_valid)
9113 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 9114 {
5f5c8ee5
GM
9115 clear_glyph_matrix (w->desired_matrix);
9116 move_it_by_lines (&it, 1, 0);
9117 try_window (window, it.current.pos);
a2889657 9118 }
5f5c8ee5 9119 else if (PT < IT_CHARPOS (it))
a2889657 9120 {
5f5c8ee5
GM
9121 clear_glyph_matrix (w->desired_matrix);
9122 move_it_by_lines (&it, -1, 0);
9123 try_window (window, it.current.pos);
9124 }
9125 else
9126 {
9127 /* Not much we can do about it. */
a2889657 9128 }
a2889657 9129 }
010494d0 9130
5f5c8ee5
GM
9131 /* Consider the following case: Window starts at BEGV, there is
9132 invisible, intangible text at BEGV, so that display starts at
9133 some point START > BEGV. It can happen that we are called with
9134 PT somewhere between BEGV and START. Try to handle that case. */
9135 if (w->cursor.vpos < 0)
835766b6 9136 {
5f5c8ee5
GM
9137 struct glyph_row *row = w->current_matrix->rows;
9138 if (row->mode_line_p)
9139 ++row;
9140 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 9141 }
5f5c8ee5
GM
9142
9143 make_cursor_line_fully_visible (w);
b5174a51 9144
74d481ac
GM
9145 done:
9146
5f5c8ee5
GM
9147 SET_TEXT_POS_FROM_MARKER (startp, w->start);
9148 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
9149 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
9150 ? Qt : Qnil);
a2889657 9151
5f5c8ee5 9152 /* Display the mode line, if we must. */
e481f960 9153 if ((update_mode_line
aa6d10fa 9154 /* If window not full width, must redo its mode line
5f5c8ee5
GM
9155 if (a) the window to its side is being redone and
9156 (b) we do a frame-based redisplay. This is a consequence
9157 of how inverted lines are drawn in frame-based redisplay. */
9158 || (!just_this_one_p
9159 && !FRAME_WINDOW_P (f)
9160 && !WINDOW_FULL_WIDTH_P (w))
9161 /* Line number to display. */
155ef550 9162 || INTEGERP (w->base_line_pos)
5f5c8ee5 9163 /* Column number is displayed and different from the one displayed. */
155ef550
KH
9164 || (!NILP (w->column_number_displayed)
9165 && XFASTINT (w->column_number_displayed) != current_column ()))
5f5c8ee5
GM
9166 /* This means that the window has a mode line. */
9167 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 9168 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 9169 {
5f5c8ee5
GM
9170 display_mode_lines (w);
9171
9172 /* If mode line height has changed, arrange for a thorough
9173 immediate redisplay using the correct mode line height. */
9174 if (WINDOW_WANTS_MODELINE_P (w)
9175 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 9176 {
5f5c8ee5
GM
9177 fonts_changed_p = 1;
9178 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
9179 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 9180 }
5f5c8ee5
GM
9181
9182 /* If top line height has changed, arrange for a thorough
9183 immediate redisplay using the correct mode line height. */
045dee35
GM
9184 if (WINDOW_WANTS_HEADER_LINE_P (w)
9185 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
9186 {
9187 fonts_changed_p = 1;
045dee35
GM
9188 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
9189 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9190 }
9191
9192 if (fonts_changed_p)
9193 goto restore_buffers;
5ba50c51 9194 }
5f5c8ee5
GM
9195
9196 if (!line_number_displayed
9197 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
9198 {
9199 w->base_line_pos = Qnil;
9200 w->base_line_number = Qnil;
9201 }
a2889657 9202
5f5c8ee5
GM
9203 finish_menu_bars:
9204
7ce2c095 9205 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 9206 if (update_mode_line
5f5c8ee5
GM
9207 && EQ (FRAME_SELECTED_WINDOW (f), window))
9208 {
9209 int redisplay_menu_p = 0;
9210
9211 if (FRAME_WINDOW_P (f))
9212 {
dc937613 9213#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
5f5c8ee5 9214 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 9215#else
5f5c8ee5 9216 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 9217#endif
5f5c8ee5
GM
9218 }
9219 else
9220 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
9221
9222 if (redisplay_menu_p)
9223 display_menu_bar (w);
9224
9225#ifdef HAVE_WINDOW_SYSTEM
e037b9ec
GM
9226 if (WINDOWP (f->tool_bar_window)
9227 && (FRAME_TOOL_BAR_LINES (f) > 0
9228 || auto_resize_tool_bars_p))
9229 redisplay_tool_bar (f);
5f5c8ee5
GM
9230#endif
9231 }
7ce2c095 9232
88f22aff 9233 finish_scroll_bars:
5f5c8ee5 9234
88f22aff 9235 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
30c566e4 9236 {
b1d1124b 9237 int start, end, whole;
30c566e4 9238
b1d1124b 9239 /* Calculate the start and end positions for the current window.
3505ea70
JB
9240 At some point, it would be nice to choose between scrollbars
9241 which reflect the whole buffer size, with special markers
9242 indicating narrowing, and scrollbars which reflect only the
9243 visible region.
9244
5f5c8ee5 9245 Note that mini-buffers sometimes aren't displaying any text. */
c6e89d6c 9246 if (!MINI_WINDOW_P (w)
5f5c8ee5 9247 || (w == XWINDOW (minibuf_window)
c6e89d6c 9248 && NILP (echo_area_buffer[0])))
b1d1124b 9249 {
8a9311d7 9250 whole = ZV - BEGV;
4d641a15 9251 start = marker_position (w->start) - BEGV;
b1d1124b
JB
9252 /* I don't think this is guaranteed to be right. For the
9253 moment, we'll pretend it is. */
5f5c8ee5 9254 end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
3505ea70 9255
5f5c8ee5
GM
9256 if (end < start)
9257 end = start;
9258 if (whole < (end - start))
9259 whole = end - start;
b1d1124b
JB
9260 }
9261 else
9262 start = end = whole = 0;
30c566e4 9263
88f22aff 9264 /* Indicate what this scroll bar ought to be displaying now. */
7eb9ba41 9265 (*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
30c566e4 9266
5f5c8ee5
GM
9267 /* Note that we actually used the scroll bar attached to this
9268 window, so it shouldn't be deleted at the end of redisplay. */
88f22aff 9269 (*redeem_scroll_bar_hook) (w);
30c566e4 9270 }
b1d1124b 9271
5f5c8ee5
GM
9272 restore_buffers:
9273
9274 /* Restore current_buffer and value of point in it. */
9275 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
5ba50c51 9276 if (really_switched_buffer)
f72df6ac 9277 set_buffer_internal_1 (old);
e481f960
RS
9278 else
9279 set_buffer_temp (old);
5f5c8ee5 9280 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
9281
9282 unbind_to (count, Qnil);
a2889657 9283}
a2889657 9284
5f5c8ee5
GM
9285
9286/* Build the complete desired matrix of WINDOW with a window start
9287 buffer position POS. Value is non-zero if successful. It is zero
9288 if fonts were loaded during redisplay which makes re-adjusting
9289 glyph matrices necessary. */
9290
9291int
a2889657
JB
9292try_window (window, pos)
9293 Lisp_Object window;
5f5c8ee5
GM
9294 struct text_pos pos;
9295{
9296 struct window *w = XWINDOW (window);
9297 struct it it;
9298 struct glyph_row *last_text_row = NULL;
9cbab4ff 9299
5f5c8ee5
GM
9300 /* Make POS the new window start. */
9301 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 9302
5f5c8ee5
GM
9303 /* Mark cursor position as unknown. No overlay arrow seen. */
9304 w->cursor.vpos = -1;
a2889657 9305 overlay_arrow_seen = 0;
642eefc6 9306
5f5c8ee5
GM
9307 /* Initialize iterator and info to start at POS. */
9308 start_display (&it, w, pos);
a2889657 9309
5f5c8ee5
GM
9310 /* Display all lines of W. */
9311 while (it.current_y < it.last_visible_y)
9312 {
9313 if (display_line (&it))
9314 last_text_row = it.glyph_row - 1;
9315 if (fonts_changed_p)
9316 return 0;
9317 }
a2889657 9318
5f5c8ee5
GM
9319 /* If bottom moved off end of frame, change mode line percentage. */
9320 if (XFASTINT (w->window_end_pos) <= 0
9321 && Z != IT_CHARPOS (it))
a2889657
JB
9322 w->update_mode_line = Qt;
9323
5f5c8ee5
GM
9324 /* Set window_end_pos to the offset of the last character displayed
9325 on the window from the end of current_buffer. Set
9326 window_end_vpos to its row number. */
9327 if (last_text_row)
9328 {
9329 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
9330 w->window_end_bytepos
9331 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9332 XSETFASTINT (w->window_end_pos,
9333 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9334 XSETFASTINT (w->window_end_vpos,
9335 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9336 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
9337 ->displays_text_p);
9338 }
9339 else
9340 {
9341 w->window_end_bytepos = 0;
9342 XSETFASTINT (w->window_end_pos, 0);
9343 XSETFASTINT (w->window_end_vpos, 0);
9344 }
9345
a2889657
JB
9346 /* But that is not valid info until redisplay finishes. */
9347 w->window_end_valid = Qnil;
5f5c8ee5 9348 return 1;
a2889657 9349}
5f5c8ee5
GM
9350
9351
a2889657 9352\f
5f5c8ee5
GM
9353/************************************************************************
9354 Window redisplay reusing current matrix when buffer has not changed
9355 ************************************************************************/
9356
9357/* Try redisplay of window W showing an unchanged buffer with a
9358 different window start than the last time it was displayed by
9359 reusing its current matrix. Value is non-zero if successful.
9360 W->start is the new window start. */
a2889657
JB
9361
9362static int
5f5c8ee5
GM
9363try_window_reusing_current_matrix (w)
9364 struct window *w;
a2889657 9365{
5f5c8ee5
GM
9366 struct frame *f = XFRAME (w->frame);
9367 struct glyph_row *row, *bottom_row;
9368 struct it it;
9369 struct run run;
9370 struct text_pos start, new_start;
9371 int nrows_scrolled, i;
9372 struct glyph_row *last_text_row;
9373 struct glyph_row *last_reused_text_row;
9374 struct glyph_row *start_row;
9375 int start_vpos, min_y, max_y;
9376
9377 /* Right now this function doesn't handle terminal frames. */
9378 if (!FRAME_WINDOW_P (f))
9379 return 0;
a2889657 9380
5f5c8ee5
GM
9381 /* Can't do this if region may have changed. */
9382 if ((!NILP (Vtransient_mark_mode)
9383 && !NILP (current_buffer->mark_active))
8f897821
GM
9384 || !NILP (w->region_showing)
9385 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 9386 return 0;
a2889657 9387
5f5c8ee5 9388 /* If top-line visibility has changed, give up. */
045dee35
GM
9389 if (WINDOW_WANTS_HEADER_LINE_P (w)
9390 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
9391 return 0;
9392
9393 /* Give up if old or new display is scrolled vertically. We could
9394 make this function handle this, but right now it doesn't. */
9395 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9396 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
9397 return 0;
9398
9399 /* The variable new_start now holds the new window start. The old
9400 start `start' can be determined from the current matrix. */
9401 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
9402 start = start_row->start.pos;
9403 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 9404
5f5c8ee5
GM
9405 /* Clear the desired matrix for the display below. */
9406 clear_glyph_matrix (w->desired_matrix);
9407
9408 if (CHARPOS (new_start) <= CHARPOS (start))
9409 {
9410 int first_row_y;
9411
9412 IF_DEBUG (debug_method_add (w, "twu1"));
9413
9414 /* Display up to a row that can be reused. The variable
9415 last_text_row is set to the last row displayed that displays
9416 text. */
9417 start_display (&it, w, new_start);
9418 first_row_y = it.current_y;
9419 w->cursor.vpos = -1;
9420 last_text_row = last_reused_text_row = NULL;
9421 while (it.current_y < it.last_visible_y
9422 && IT_CHARPOS (it) < CHARPOS (start)
9423 && !fonts_changed_p)
9424 if (display_line (&it))
9425 last_text_row = it.glyph_row - 1;
9426
9427 /* A value of current_y < last_visible_y means that we stopped
9428 at the previous window start, which in turn means that we
9429 have at least one reusable row. */
9430 if (it.current_y < it.last_visible_y)
a2889657 9431 {
5f5c8ee5
GM
9432 nrows_scrolled = it.vpos;
9433
9434 /* Find PT if not already found in the lines displayed. */
9435 if (w->cursor.vpos < 0)
a2889657 9436 {
5f5c8ee5
GM
9437 int dy = it.current_y - first_row_y;
9438
9439 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9440 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9441 {
9442 if (PT >= MATRIX_ROW_START_CHARPOS (row)
9443 && PT < MATRIX_ROW_END_CHARPOS (row))
9444 {
9445 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
9446 dy, nrows_scrolled);
9447 break;
9448 }
9449
9450 if (MATRIX_ROW_BOTTOM_Y (row) + dy >= it.last_visible_y)
9451 break;
9452
9453 ++row;
9454 }
9455
9456 /* Give up if point was not found. This shouldn't
9457 happen often; not more often than with try_window
9458 itself. */
9459 if (w->cursor.vpos < 0)
9460 {
9461 clear_glyph_matrix (w->desired_matrix);
9462 return 0;
9463 }
a2889657 9464 }
5f5c8ee5
GM
9465
9466 /* Scroll the display. Do it before the current matrix is
9467 changed. The problem here is that update has not yet
9468 run, i.e. part of the current matrix is not up to date.
9469 scroll_run_hook will clear the cursor, and use the
9470 current matrix to get the height of the row the cursor is
9471 in. */
9472 run.current_y = first_row_y;
9473 run.desired_y = it.current_y;
9474 run.height = it.last_visible_y - it.current_y;
9475 if (run.height > 0)
a2889657 9476 {
5f5c8ee5
GM
9477 update_begin (f);
9478 rif->update_window_begin_hook (w);
9479 rif->scroll_run_hook (w, &run);
9480 rif->update_window_end_hook (w, 0);
9481 update_end (f);
a2889657 9482 }
5f5c8ee5
GM
9483
9484 /* Shift current matrix down by nrows_scrolled lines. */
9485 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9486 rotate_matrix (w->current_matrix,
9487 start_vpos,
9488 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
9489 nrows_scrolled);
9490
9491 /* Disable lines not reused. */
9492 for (i = 0; i < it.vpos; ++i)
9493 MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
9494
9495 /* Re-compute Y positions. */
9496 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix) + nrows_scrolled;
045dee35 9497 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9498 max_y = it.last_visible_y;
9499 while (row < bottom_row)
d2f84654 9500 {
5f5c8ee5
GM
9501 row->y = it.current_y;
9502
9503 if (row->y < min_y)
9504 row->visible_height = row->height - (min_y - row->y);
9505 else if (row->y + row->height > max_y)
9506 row->visible_height
9507 = row->height - (row->y + row->height - max_y);
9508 else
9509 row->visible_height = row->height;
9510
9511 it.current_y += row->height;
9512 ++it.vpos;
9513
9514 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9515 last_reused_text_row = row;
9516 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
9517 break;
9518 ++row;
d2f84654 9519 }
a2889657 9520 }
5f5c8ee5
GM
9521
9522 /* Update window_end_pos etc.; last_reused_text_row is the last
9523 reused row from the current matrix containing text, if any.
9524 The value of last_text_row is the last displayed line
9525 containing text. */
9526 if (last_reused_text_row)
a2889657 9527 {
5f5c8ee5
GM
9528 w->window_end_bytepos
9529 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
9530 XSETFASTINT (w->window_end_pos,
9531 Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
9532 XSETFASTINT (w->window_end_vpos,
9533 MATRIX_ROW_VPOS (last_reused_text_row,
9534 w->current_matrix));
a2889657 9535 }
5f5c8ee5
GM
9536 else if (last_text_row)
9537 {
9538 w->window_end_bytepos
9539 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9540 XSETFASTINT (w->window_end_pos,
9541 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9542 XSETFASTINT (w->window_end_vpos,
9543 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9544 }
9545 else
9546 {
9547 /* This window must be completely empty. */
9548 w->window_end_bytepos = 0;
9549 XSETFASTINT (w->window_end_pos, 0);
9550 XSETFASTINT (w->window_end_vpos, 0);
9551 }
9552 w->window_end_valid = Qnil;
a2889657 9553
5f5c8ee5
GM
9554 /* Update hint: don't try scrolling again in update_window. */
9555 w->desired_matrix->no_scrolling_p = 1;
9556
9557#if GLYPH_DEBUG
9558 debug_method_add (w, "try_window_reusing_current_matrix 1");
9559#endif
9560 return 1;
a2889657 9561 }
5f5c8ee5
GM
9562 else if (CHARPOS (new_start) > CHARPOS (start))
9563 {
9564 struct glyph_row *pt_row, *row;
9565 struct glyph_row *first_reusable_row;
9566 struct glyph_row *first_row_to_display;
9567 int dy;
9568 int yb = window_text_bottom_y (w);
9569
9570 IF_DEBUG (debug_method_add (w, "twu2"));
9571
9572 /* Find the row starting at new_start, if there is one. Don't
9573 reuse a partially visible line at the end. */
9574 first_reusable_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9575 while (first_reusable_row->enabled_p
9576 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
9577 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9578 < CHARPOS (new_start)))
9579 ++first_reusable_row;
9580
9581 /* Give up if there is no row to reuse. */
9582 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
9583 || !first_reusable_row->enabled_p
9584 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
9585 != CHARPOS (new_start)))
5f5c8ee5
GM
9586 return 0;
9587
5f5c8ee5
GM
9588 /* We can reuse fully visible rows beginning with
9589 first_reusable_row to the end of the window. Set
9590 first_row_to_display to the first row that cannot be reused.
9591 Set pt_row to the row containing point, if there is any. */
9592 first_row_to_display = first_reusable_row;
9593 pt_row = NULL;
9594 while (MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb)
9595 {
9596 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
9597 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
9598 pt_row = first_row_to_display;
a2889657 9599
5f5c8ee5
GM
9600 ++first_row_to_display;
9601 }
a2889657 9602
5f5c8ee5
GM
9603 /* Start displaying at the start of first_row_to_display. */
9604 xassert (first_row_to_display->y < yb);
9605 init_to_row_start (&it, w, first_row_to_display);
9606 nrows_scrolled = MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix);
9607 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
9608 - nrows_scrolled);
9609 it.current_y = first_row_to_display->y - first_reusable_row->y;
9610
9611 /* Display lines beginning with first_row_to_display in the
9612 desired matrix. Set last_text_row to the last row displayed
9613 that displays text. */
9614 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
9615 if (pt_row == NULL)
9616 w->cursor.vpos = -1;
9617 last_text_row = NULL;
9618 while (it.current_y < it.last_visible_y && !fonts_changed_p)
9619 if (display_line (&it))
9620 last_text_row = it.glyph_row - 1;
9621
9622 /* Give up If point isn't in a row displayed or reused. */
9623 if (w->cursor.vpos < 0)
9624 {
9625 clear_glyph_matrix (w->desired_matrix);
9626 return 0;
9627 }
12adba34 9628
5f5c8ee5
GM
9629 /* If point is in a reused row, adjust y and vpos of the cursor
9630 position. */
9631 if (pt_row)
9632 {
9633 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
9634 w->current_matrix);
9635 w->cursor.y -= first_reusable_row->y;
a2889657
JB
9636 }
9637
5f5c8ee5
GM
9638 /* Scroll the display. */
9639 run.current_y = first_reusable_row->y;
045dee35 9640 run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9641 run.height = it.last_visible_y - run.current_y;
9642 if (run.height)
9643 {
9644 struct frame *f = XFRAME (WINDOW_FRAME (w));
9645 update_begin (f);
9646 rif->update_window_begin_hook (w);
9647 rif->scroll_run_hook (w, &run);
9648 rif->update_window_end_hook (w, 0);
9649 update_end (f);
9650 }
a2889657 9651
5f5c8ee5
GM
9652 /* Adjust Y positions of reused rows. */
9653 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
9654 row = first_reusable_row;
9655 dy = first_reusable_row->y;
045dee35 9656 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
9657 max_y = it.last_visible_y;
9658 while (row < first_row_to_display)
9659 {
9660 row->y -= dy;
9661 if (row->y < min_y)
9662 row->visible_height = row->height - (min_y - row->y);
9663 else if (row->y + row->height > max_y)
9664 row->visible_height
9665 = row->height - (row->y + row->height - max_y);
9666 else
9667 row->visible_height = row->height;
9668 ++row;
9669 }
a2889657 9670
5f5c8ee5
GM
9671 /* Disable rows not reused. */
9672 while (row < bottom_row)
9673 {
9674 row->enabled_p = 0;
9675 ++row;
9676 }
9677
9678 /* Scroll the current matrix. */
9679 xassert (nrows_scrolled > 0);
9680 rotate_matrix (w->current_matrix,
9681 start_vpos,
9682 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
9683 -nrows_scrolled);
9684
9685 /* Adjust window end. A null value of last_text_row means that
9686 the window end is in reused rows which in turn means that
9687 only its vpos can have changed. */
9688 if (last_text_row)
9689 {
9690 w->window_end_bytepos
9691 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
9692 XSETFASTINT (w->window_end_pos,
9693 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
9694 XSETFASTINT (w->window_end_vpos,
9695 MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
9696 }
9697 else
a2889657 9698 {
e8e536a9 9699 XSETFASTINT (w->window_end_vpos,
5f5c8ee5 9700 XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 9701 }
5f5c8ee5
GM
9702
9703 w->window_end_valid = Qnil;
9704 w->desired_matrix->no_scrolling_p = 1;
9705
9706#if GLYPH_DEBUG
9707 debug_method_add (w, "try_window_reusing_current_matrix 2");
9708#endif
9709 return 1;
a2889657 9710 }
5f5c8ee5
GM
9711
9712 return 0;
9713}
a2889657 9714
a2889657 9715
5f5c8ee5
GM
9716\f
9717/************************************************************************
9718 Window redisplay reusing current matrix when buffer has changed
9719 ************************************************************************/
9720
9721static struct glyph_row *get_last_unchanged_at_beg_row P_ ((struct window *));
9722static struct glyph_row *get_first_unchanged_at_end_row P_ ((struct window *,
9723 int *, int *));
9724static struct glyph_row *
9725find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
9726 struct glyph_row *));
9727
9728
9729/* Return the last row in MATRIX displaying text. If row START is
9730 non-null, start searching with that row. IT gives the dimensions
9731 of the display. Value is null if matrix is empty; otherwise it is
9732 a pointer to the row found. */
9733
9734static struct glyph_row *
9735find_last_row_displaying_text (matrix, it, start)
9736 struct glyph_matrix *matrix;
9737 struct it *it;
9738 struct glyph_row *start;
9739{
9740 struct glyph_row *row, *row_found;
9741
9742 /* Set row_found to the last row in IT->w's current matrix
9743 displaying text. The loop looks funny but think of partially
9744 visible lines. */
9745 row_found = NULL;
9746 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
9747 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9748 {
9749 xassert (row->enabled_p);
9750 row_found = row;
9751 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
9752 break;
9753 ++row;
a2889657 9754 }
5f5c8ee5
GM
9755
9756 return row_found;
9757}
9758
a2889657 9759
5f5c8ee5
GM
9760/* Return the last row in the current matrix of W that is not affected
9761 by changes at the start of current_buffer that occurred since the
9762 last time W was redisplayed. Value is null if no such row exists.
a2889657 9763
5f5c8ee5
GM
9764 The global variable beg_unchanged has to contain the number of
9765 bytes unchanged at the start of current_buffer. BEG +
9766 beg_unchanged is the buffer position of the first changed byte in
9767 current_buffer. Characters at positions < BEG + beg_unchanged are
9768 at the same buffer positions as they were when the current matrix
9769 was built. */
9770
9771static struct glyph_row *
9772get_last_unchanged_at_beg_row (w)
9773 struct window *w;
9774{
9142dd5b 9775 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
9776 struct glyph_row *row;
9777 struct glyph_row *row_found = NULL;
9778 int yb = window_text_bottom_y (w);
9779
9780 /* Find the last row displaying unchanged text. */
9781 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9782 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
9783 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 9784 {
5f5c8ee5
GM
9785 if (/* If row ends before first_changed_pos, it is unchanged,
9786 except in some case. */
9787 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
9788 /* When row ends in ZV and we write at ZV it is not
9789 unchanged. */
9790 && !row->ends_at_zv_p
9791 /* When first_changed_pos is the end of a continued line,
9792 row is not unchanged because it may be no longer
9793 continued. */
9794 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
9795 && row->continued_p))
9796 row_found = row;
9797
9798 /* Stop if last visible row. */
9799 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
9800 break;
9801
9802 ++row;
a2889657
JB
9803 }
9804
5f5c8ee5 9805 return row_found;
a2889657 9806}
5f5c8ee5
GM
9807
9808
9809/* Find the first glyph row in the current matrix of W that is not
9810 affected by changes at the end of current_buffer since the last
9811 time the window was redisplayed. Return in *DELTA the number of
c59c668a
GM
9812 chars by which buffer positions in unchanged text at the end of
9813 current_buffer must be adjusted. Return in *DELTA_BYTES the
9814 corresponding number of bytes. Value is null if no such row
9815 exists, i.e. all rows are affected by changes. */
5f5c8ee5
GM
9816
9817static struct glyph_row *
9818get_first_unchanged_at_end_row (w, delta, delta_bytes)
9819 struct window *w;
9820 int *delta, *delta_bytes;
a2889657 9821{
5f5c8ee5
GM
9822 struct glyph_row *row;
9823 struct glyph_row *row_found = NULL;
c581d710 9824
5f5c8ee5 9825 *delta = *delta_bytes = 0;
b2a76982 9826
5f5c8ee5
GM
9827 /* A value of window_end_pos >= end_unchanged means that the window
9828 end is in the range of changed text. If so, there is no
9829 unchanged row at the end of W's current matrix. */
9830 xassert (!NILP (w->window_end_valid));
9142dd5b 9831 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
9832 return NULL;
9833
9834 /* Set row to the last row in W's current matrix displaying text. */
9835 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
9836
5f5c8ee5
GM
9837 /* If matrix is entirely empty, no unchanged row exists. */
9838 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
9839 {
9840 /* The value of row is the last glyph row in the matrix having a
9841 meaningful buffer position in it. The end position of row
9842 corresponds to window_end_pos. This allows us to translate
9843 buffer positions in the current matrix to current buffer
9844 positions for characters not in changed text. */
9845 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
9846 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
9847 int last_unchanged_pos, last_unchanged_pos_old;
9848 struct glyph_row *first_text_row
9849 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
9850
9851 *delta = Z - Z_old;
9852 *delta_bytes = Z_BYTE - Z_BYTE_old;
9853
9854 /* Set last_unchanged_pos to the buffer position of the last
9855 character in the buffer that has not been changed. Z is the
9856 index + 1 of the last byte in current_buffer, i.e. by
9857 subtracting end_unchanged we get the index of the last
9858 unchanged character, and we have to add BEG to get its buffer
9859 position. */
9142dd5b 9860 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5
GM
9861 last_unchanged_pos_old = last_unchanged_pos - *delta;
9862
9863 /* Search backward from ROW for a row displaying a line that
9864 starts at a minimum position >= last_unchanged_pos_old. */
9865 while (row >= first_text_row)
9866 {
9867 xassert (row->enabled_p);
9868 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (row));
9869
9870 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
9871 row_found = row;
9872 --row;
9873 }
9874 }
9875
9876 xassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
9877 return row_found;
c581d710
RS
9878}
9879
c581d710 9880
5f5c8ee5
GM
9881/* Make sure that glyph rows in the current matrix of window W
9882 reference the same glyph memory as corresponding rows in the
9883 frame's frame matrix. This function is called after scrolling W's
9884 current matrix on a terminal frame in try_window_id and
9885 try_window_reusing_current_matrix. */
9886
9887static void
9888sync_frame_with_window_matrix_rows (w)
9889 struct window *w;
c581d710 9890{
5f5c8ee5
GM
9891 struct frame *f = XFRAME (w->frame);
9892 struct glyph_row *window_row, *window_row_end, *frame_row;
9893
9894 /* Preconditions: W must be a leaf window and full-width. Its frame
9895 must have a frame matrix. */
9896 xassert (NILP (w->hchild) && NILP (w->vchild));
9897 xassert (WINDOW_FULL_WIDTH_P (w));
9898 xassert (!FRAME_WINDOW_P (f));
9899
9900 /* If W is a full-width window, glyph pointers in W's current matrix
9901 have, by definition, to be the same as glyph pointers in the
9902 corresponding frame matrix. */
9903 window_row = w->current_matrix->rows;
9904 window_row_end = window_row + w->current_matrix->nrows;
9905 frame_row = f->current_matrix->rows + XFASTINT (w->top);
9906 while (window_row < window_row_end)
659a218f 9907 {
5f5c8ee5 9908 int area;
f002db93 9909
5f5c8ee5
GM
9910 for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
9911 frame_row->glyphs[area] = window_row->glyphs[area];
f002db93
GM
9912
9913 /* Disable frame rows whose corresponding window rows have
9914 been disabled in try_window_id. */
9915 if (!window_row->enabled_p)
9916 frame_row->enabled_p = 0;
9917
5f5c8ee5 9918 ++window_row, ++frame_row;
659a218f 9919 }
a2889657 9920}
5f5c8ee5
GM
9921
9922
e037b9ec
GM
9923/* Find the glyph row in window W containing CHARPOS. Consider all
9924 rows between START and END (not inclusive). END null means search
9925 all rows to the end of the display area of W. Value is the row
9926 containing CHARPOS or null. */
9927
9928static struct glyph_row *
9929row_containing_pos (w, charpos, start, end)
9930 struct window *w;
9931 int charpos;
9932 struct glyph_row *start, *end;
9933{
9934 struct glyph_row *row = start;
9935 int last_y;
9936
9937 /* If we happen to start on a header-line, skip that. */
9938 if (row->mode_line_p)
9939 ++row;
9940
9941 if ((end && row >= end) || !row->enabled_p)
9942 return NULL;
9943
9944 last_y = window_text_bottom_y (w);
9945
9946 while ((end == NULL || row < end)
9947 && (MATRIX_ROW_END_CHARPOS (row) < charpos
9948 /* The end position of a row equals the start
9949 position of the next row. If CHARPOS is there, we
9950 would rather display it in the next line, except
9951 when this line ends in ZV. */
9952 || (MATRIX_ROW_END_CHARPOS (row) == charpos
9953 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
9954 || !row->ends_at_zv_p)))
9955 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
9956 ++row;
9957
9958 /* Give up if CHARPOS not found. */
9959 if ((end && row >= end)
9960 || charpos < MATRIX_ROW_START_CHARPOS (row)
9961 || charpos > MATRIX_ROW_END_CHARPOS (row))
9962 row = NULL;
9963
9964 return row;
9965}
9966
9967
5f5c8ee5
GM
9968/* Try to redisplay window W by reusing its existing display. W's
9969 current matrix must be up to date when this function is called,
9970 i.e. window_end_valid must not be nil.
9971
9972 Value is
9973
9974 1 if display has been updated
9975 0 if otherwise unsuccessful
9976 -1 if redisplay with same window start is known not to succeed
9977
9978 The following steps are performed:
9979
9980 1. Find the last row in the current matrix of W that is not
9981 affected by changes at the start of current_buffer. If no such row
9982 is found, give up.
9983
9984 2. Find the first row in W's current matrix that is not affected by
9985 changes at the end of current_buffer. Maybe there is no such row.
9986
9987 3. Display lines beginning with the row + 1 found in step 1 to the
9988 row found in step 2 or, if step 2 didn't find a row, to the end of
9989 the window.
9990
9991 4. If cursor is not known to appear on the window, give up.
9992
9993 5. If display stopped at the row found in step 2, scroll the
9994 display and current matrix as needed.
9995
9996 6. Maybe display some lines at the end of W, if we must. This can
9997 happen under various circumstances, like a partially visible line
9998 becoming fully visible, or because newly displayed lines are displayed
9999 in smaller font sizes.
10000
10001 7. Update W's window end information. */
10002
10003 /* Check that window end is what we expect it to be. */
12adba34
RS
10004
10005static int
5f5c8ee5 10006try_window_id (w)
12adba34 10007 struct window *w;
12adba34 10008{
5f5c8ee5
GM
10009 struct frame *f = XFRAME (w->frame);
10010 struct glyph_matrix *current_matrix = w->current_matrix;
10011 struct glyph_matrix *desired_matrix = w->desired_matrix;
10012 struct glyph_row *last_unchanged_at_beg_row;
10013 struct glyph_row *first_unchanged_at_end_row;
10014 struct glyph_row *row;
10015 struct glyph_row *bottom_row;
10016 int bottom_vpos;
10017 struct it it;
10018 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
10019 struct text_pos start_pos;
10020 struct run run;
10021 int first_unchanged_at_end_vpos = 0;
10022 struct glyph_row *last_text_row, *last_text_row_at_end;
10023 struct text_pos start;
10024
10025 SET_TEXT_POS_FROM_MARKER (start, w->start);
10026
10027 /* Check pre-conditions. Window end must be valid, otherwise
10028 the current matrix would not be up to date. */
10029 xassert (!NILP (w->window_end_valid));
10030 xassert (FRAME_WINDOW_P (XFRAME (w->frame))
10031 || (line_ins_del_ok && WINDOW_FULL_WIDTH_P (w)));
10032
10033 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
10034 only if buffer has really changed. The reason is that the gap is
10035 initially at Z for freshly visited files. The code below would
10036 set end_unchanged to 0 in that case. */
bf9249e3 10037 if (MODIFF > SAVE_MODIFF)
5f5c8ee5 10038 {
9142dd5b
GM
10039 if (GPT - BEG < BEG_UNCHANGED)
10040 BEG_UNCHANGED = GPT - BEG;
10041 if (Z - GPT < END_UNCHANGED)
10042 END_UNCHANGED = Z - GPT;
5f5c8ee5 10043 }
bf9249e3
GM
10044
10045 /* Some strange bug seems to be causing that to happen sometimes. */
10046 if (BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
10047 abort ();
5f5c8ee5
GM
10048
10049 /* If window starts after a line end, and the last change is in
10050 front of that newline, then changes don't affect the display.
10051 This case happens with stealth-fontification. */
10052 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
10053 if (CHARPOS (start) > BEGV
9142dd5b 10054 && Z - END_UNCHANGED < CHARPOS (start) - 1
5f5c8ee5
GM
10055 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n'
10056 && PT < MATRIX_ROW_END_CHARPOS (row))
10057 {
10058 /* We have to update window end positions because the buffer's
10059 size has changed. */
10060 w->window_end_pos
10061 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
10062 w->window_end_bytepos
10063 = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
10064 return 1;
10065 }
10066
10067 /* Return quickly if changes are all below what is displayed in the
10068 window, and if PT is in the window. */
9142dd5b 10069 if (BEG_UNCHANGED > MATRIX_ROW_END_CHARPOS (row)
5f5c8ee5
GM
10070 && PT < MATRIX_ROW_END_CHARPOS (row))
10071 {
10072 /* We have to update window end positions because the buffer's
10073 size has changed. */
10074 w->window_end_pos
10075 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
10076 w->window_end_bytepos
10077 = make_number (Z_BYTE - MATRIX_ROW_END_BYTEPOS (row));
10078 return 1;
10079 }
10080
10081 /* Check that window start agrees with the start of the first glyph
10082 row in its current matrix. Check this after we know the window
10083 start is not in changed text, otherwise positions would not be
10084 comparable. */
10085 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
10086 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
10087 return 0;
10088
5f5c8ee5
GM
10089 /* Compute the position at which we have to start displaying new
10090 lines. Some of the lines at the top of the window might be
10091 reusable because they are not displaying changed text. Find the
10092 last row in W's current matrix not affected by changes at the
10093 start of current_buffer. Value is null if changes start in the
10094 first line of window. */
10095 last_unchanged_at_beg_row = get_last_unchanged_at_beg_row (w);
10096 if (last_unchanged_at_beg_row)
10097 {
10098 init_to_row_end (&it, w, last_unchanged_at_beg_row);
10099 start_pos = it.current.pos;
10100
10101 /* Start displaying new lines in the desired matrix at the same
10102 vpos we would use in the current matrix, i.e. below
10103 last_unchanged_at_beg_row. */
10104 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
10105 current_matrix);
10106 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10107 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
10108
10109 xassert (it.hpos == 0 && it.current_x == 0);
10110 }
10111 else
10112 {
10113 /* There are no reusable lines at the start of the window.
10114 Start displaying in the first line. */
10115 start_display (&it, w, start);
10116 start_pos = it.current.pos;
10117 }
10118
5f5c8ee5
GM
10119 /* Find the first row that is not affected by changes at the end of
10120 the buffer. Value will be null if there is no unchanged row, in
10121 which case we must redisplay to the end of the window. delta
10122 will be set to the value by which buffer positions beginning with
10123 first_unchanged_at_end_row have to be adjusted due to text
10124 changes. */
10125 first_unchanged_at_end_row
10126 = get_first_unchanged_at_end_row (w, &delta, &delta_bytes);
10127 IF_DEBUG (debug_delta = delta);
10128 IF_DEBUG (debug_delta_bytes = delta_bytes);
10129
10130 /* Set stop_pos to the buffer position up to which we will have to
10131 display new lines. If first_unchanged_at_end_row != NULL, this
10132 is the buffer position of the start of the line displayed in that
10133 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
10134 that we don't stop at a buffer position. */
10135 stop_pos = 0;
10136 if (first_unchanged_at_end_row)
10137 {
10138 xassert (last_unchanged_at_beg_row == NULL
10139 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
10140
10141 /* If this is a continuation line, move forward to the next one
10142 that isn't. Changes in lines above affect this line.
10143 Caution: this may move first_unchanged_at_end_row to a row
10144 not displaying text. */
10145 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
10146 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
10147 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
10148 < it.last_visible_y))
10149 ++first_unchanged_at_end_row;
10150
10151 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
10152 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
10153 >= it.last_visible_y))
10154 first_unchanged_at_end_row = NULL;
10155 else
10156 {
10157 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
10158 + delta);
10159 first_unchanged_at_end_vpos
10160 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 10161 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
10162 }
10163 }
10164 else if (last_unchanged_at_beg_row == NULL)
10165 return 0;
10166
10167
10168#if GLYPH_DEBUG
10169
10170 /* Either there is no unchanged row at the end, or the one we have
10171 now displays text. This is a necessary condition for the window
10172 end pos calculation at the end of this function. */
10173 xassert (first_unchanged_at_end_row == NULL
10174 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
10175
10176 debug_last_unchanged_at_beg_vpos
10177 = (last_unchanged_at_beg_row
10178 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
10179 : -1);
10180 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
10181
10182#endif /* GLYPH_DEBUG != 0 */
10183
10184
10185 /* Display new lines. Set last_text_row to the last new line
10186 displayed which has text on it, i.e. might end up as being the
10187 line where the window_end_vpos is. */
10188 w->cursor.vpos = -1;
10189 last_text_row = NULL;
10190 overlay_arrow_seen = 0;
10191 while (it.current_y < it.last_visible_y
10192 && !fonts_changed_p
10193 && (first_unchanged_at_end_row == NULL
10194 || IT_CHARPOS (it) < stop_pos))
10195 {
10196 if (display_line (&it))
10197 last_text_row = it.glyph_row - 1;
10198 }
10199
10200 if (fonts_changed_p)
10201 return -1;
10202
10203
10204 /* Compute differences in buffer positions, y-positions etc. for
10205 lines reused at the bottom of the window. Compute what we can
10206 scroll. */
ca42b2e8
GM
10207 if (first_unchanged_at_end_row
10208 /* No lines reused because we displayed everything up to the
10209 bottom of the window. */
10210 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
10211 {
10212 dvpos = (it.vpos
10213 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
10214 current_matrix));
10215 dy = it.current_y - first_unchanged_at_end_row->y;
10216 run.current_y = first_unchanged_at_end_row->y;
10217 run.desired_y = run.current_y + dy;
10218 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
10219 }
10220 else
ca42b2e8
GM
10221 {
10222 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
10223 first_unchanged_at_end_row = NULL;
10224 }
5f5c8ee5
GM
10225 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
10226
8f8ba186 10227
5f5c8ee5
GM
10228 /* Find the cursor if not already found. We have to decide whether
10229 PT will appear on this window (it sometimes doesn't, but this is
10230 not a very frequent case.) This decision has to be made before
10231 the current matrix is altered. A value of cursor.vpos < 0 means
10232 that PT is either in one of the lines beginning at
10233 first_unchanged_at_end_row or below the window. Don't care for
10234 lines that might be displayed later at the window end; as
10235 mentioned, this is not a frequent case. */
10236 if (w->cursor.vpos < 0)
10237 {
5f5c8ee5
GM
10238 /* Cursor in unchanged rows at the top? */
10239 if (PT < CHARPOS (start_pos)
10240 && last_unchanged_at_beg_row)
10241 {
e037b9ec
GM
10242 row = row_containing_pos (w, PT,
10243 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
10244 last_unchanged_at_beg_row + 1);
10245 xassert (row && row <= last_unchanged_at_beg_row);
5f5c8ee5
GM
10246 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
10247 }
10248
10249 /* Start from first_unchanged_at_end_row looking for PT. */
10250 else if (first_unchanged_at_end_row)
10251 {
e037b9ec
GM
10252 row = row_containing_pos (w, PT - delta,
10253 first_unchanged_at_end_row, NULL);
10254 if (row)
468155d7
GM
10255 set_cursor_from_row (w, row, w->current_matrix, delta,
10256 delta_bytes, dy, dvpos);
5f5c8ee5
GM
10257 }
10258
10259 /* Give up if cursor was not found. */
10260 if (w->cursor.vpos < 0)
10261 {
10262 clear_glyph_matrix (w->desired_matrix);
10263 return -1;
10264 }
10265 }
10266
10267 /* Don't let the cursor end in the scroll margins. */
10268 {
10269 int this_scroll_margin, cursor_height;
10270
10271 this_scroll_margin = max (0, scroll_margin);
10272 this_scroll_margin = min (this_scroll_margin,
10273 XFASTINT (w->height) / 4);
10274 this_scroll_margin *= CANON_Y_UNIT (it.f);
10275 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
10276
10277 if ((w->cursor.y < this_scroll_margin
10278 && CHARPOS (start) > BEGV)
10279 /* Don't take scroll margin into account at the bottom because
10280 old redisplay didn't do it either. */
10281 || w->cursor.y + cursor_height > it.last_visible_y)
10282 {
10283 w->cursor.vpos = -1;
10284 clear_glyph_matrix (w->desired_matrix);
10285 return -1;
10286 }
10287 }
10288
10289 /* Scroll the display. Do it before changing the current matrix so
10290 that xterm.c doesn't get confused about where the cursor glyph is
10291 found. */
10292 if (dy)
10293 {
10294 update_begin (f);
10295
10296 if (FRAME_WINDOW_P (f))
10297 {
10298 rif->update_window_begin_hook (w);
10299 rif->scroll_run_hook (w, &run);
10300 rif->update_window_end_hook (w, 0);
10301 }
10302 else
10303 {
10304 /* Terminal frame. In this case, dvpos gives the number of
10305 lines to scroll by; dvpos < 0 means scroll up. */
10306 int first_unchanged_at_end_vpos
10307 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
10308 int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
10309 int end = XFASTINT (w->top) + window_internal_height (w);
10310
10311 /* Perform the operation on the screen. */
10312 if (dvpos > 0)
10313 {
10314 /* Scroll last_unchanged_at_beg_row to the end of the
10315 window down dvpos lines. */
10316 set_terminal_window (end);
10317
10318 /* On dumb terminals delete dvpos lines at the end
10319 before inserting dvpos empty lines. */
10320 if (!scroll_region_ok)
10321 ins_del_lines (end - dvpos, -dvpos);
10322
10323 /* Insert dvpos empty lines in front of
10324 last_unchanged_at_beg_row. */
10325 ins_del_lines (from, dvpos);
10326 }
10327 else if (dvpos < 0)
10328 {
10329 /* Scroll up last_unchanged_at_beg_vpos to the end of
10330 the window to last_unchanged_at_beg_vpos - |dvpos|. */
10331 set_terminal_window (end);
10332
10333 /* Delete dvpos lines in front of
10334 last_unchanged_at_beg_vpos. ins_del_lines will set
10335 the cursor to the given vpos and emit |dvpos| delete
10336 line sequences. */
10337 ins_del_lines (from + dvpos, dvpos);
10338
10339 /* On a dumb terminal insert dvpos empty lines at the
10340 end. */
10341 if (!scroll_region_ok)
10342 ins_del_lines (end + dvpos, -dvpos);
10343 }
10344
10345 set_terminal_window (0);
10346 }
10347
10348 update_end (f);
10349 }
10350
ca42b2e8
GM
10351 /* Shift reused rows of the current matrix to the right position.
10352 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
10353 text. */
10354 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
10355 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
10356 if (dvpos < 0)
10357 {
10358 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
10359 bottom_vpos, dvpos);
10360 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
10361 bottom_vpos, 0);
10362 }
10363 else if (dvpos > 0)
10364 {
10365 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
10366 bottom_vpos, dvpos);
10367 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
10368 first_unchanged_at_end_vpos + dvpos, 0);
10369 }
10370
10371 /* For frame-based redisplay, make sure that current frame and window
10372 matrix are in sync with respect to glyph memory. */
10373 if (!FRAME_WINDOW_P (f))
10374 sync_frame_with_window_matrix_rows (w);
10375
10376 /* Adjust buffer positions in reused rows. */
10377 if (delta)
10378 increment_glyph_matrix_buffer_positions (current_matrix,
10379 first_unchanged_at_end_vpos + dvpos,
10380 bottom_vpos, delta, delta_bytes);
10381
10382 /* Adjust Y positions. */
10383 if (dy)
10384 shift_glyph_matrix (w, current_matrix,
10385 first_unchanged_at_end_vpos + dvpos,
10386 bottom_vpos, dy);
10387
10388 if (first_unchanged_at_end_row)
10389 first_unchanged_at_end_row += dvpos;
10390
10391 /* If scrolling up, there may be some lines to display at the end of
10392 the window. */
10393 last_text_row_at_end = NULL;
10394 if (dy < 0)
10395 {
10396 /* Set last_row to the glyph row in the current matrix where the
10397 window end line is found. It has been moved up or down in
10398 the matrix by dvpos. */
10399 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
10400 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
10401
10402 /* If last_row is the window end line, it should display text. */
10403 xassert (last_row->displays_text_p);
10404
10405 /* If window end line was partially visible before, begin
10406 displaying at that line. Otherwise begin displaying with the
10407 line following it. */
10408 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
10409 {
10410 init_to_row_start (&it, w, last_row);
10411 it.vpos = last_vpos;
10412 it.current_y = last_row->y;
10413 }
10414 else
10415 {
10416 init_to_row_end (&it, w, last_row);
10417 it.vpos = 1 + last_vpos;
10418 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
10419 ++last_row;
10420 }
12adba34 10421
5f5c8ee5
GM
10422 /* We may start in a continuation line. If so, we have to get
10423 the right continuation_lines_width and current_x. */
10424 it.continuation_lines_width = last_row->continuation_lines_width;
10425 it.hpos = it.current_x = 0;
10426
10427 /* Display the rest of the lines at the window end. */
10428 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
10429 while (it.current_y < it.last_visible_y
10430 && !fonts_changed_p)
10431 {
10432 /* Is it always sure that the display agrees with lines in
10433 the current matrix? I don't think so, so we mark rows
10434 displayed invalid in the current matrix by setting their
10435 enabled_p flag to zero. */
10436 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
10437 if (display_line (&it))
10438 last_text_row_at_end = it.glyph_row - 1;
10439 }
10440 }
12adba34 10441
5f5c8ee5
GM
10442 /* Update window_end_pos and window_end_vpos. */
10443 if (first_unchanged_at_end_row
10444 && first_unchanged_at_end_row->y < it.last_visible_y
10445 && !last_text_row_at_end)
10446 {
10447 /* Window end line if one of the preserved rows from the current
10448 matrix. Set row to the last row displaying text in current
10449 matrix starting at first_unchanged_at_end_row, after
10450 scrolling. */
10451 xassert (first_unchanged_at_end_row->displays_text_p);
10452 row = find_last_row_displaying_text (w->current_matrix, &it,
10453 first_unchanged_at_end_row);
10454 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
10455
10456 XSETFASTINT (w->window_end_pos, Z - MATRIX_ROW_END_CHARPOS (row));
10457 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
10458 XSETFASTINT (w->window_end_vpos,
10459 MATRIX_ROW_VPOS (row, w->current_matrix));
10460 }
10461 else if (last_text_row_at_end)
10462 {
10463 XSETFASTINT (w->window_end_pos,
10464 Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
10465 w->window_end_bytepos
10466 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
10467 XSETFASTINT (w->window_end_vpos,
10468 MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
10469 }
10470 else if (last_text_row)
10471 {
10472 /* We have displayed either to the end of the window or at the
10473 end of the window, i.e. the last row with text is to be found
10474 in the desired matrix. */
10475 XSETFASTINT (w->window_end_pos,
10476 Z - MATRIX_ROW_END_CHARPOS (last_text_row));
10477 w->window_end_bytepos
10478 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
10479 XSETFASTINT (w->window_end_vpos,
10480 MATRIX_ROW_VPOS (last_text_row, desired_matrix));
10481 }
10482 else if (first_unchanged_at_end_row == NULL
10483 && last_text_row == NULL
10484 && last_text_row_at_end == NULL)
10485 {
10486 /* Displayed to end of window, but no line containing text was
10487 displayed. Lines were deleted at the end of the window. */
10488 int vpos;
045dee35 10489 int header_line_p = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
10490
10491 for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
045dee35
GM
10492 if ((w->desired_matrix->rows[vpos + header_line_p].enabled_p
10493 && w->desired_matrix->rows[vpos + header_line_p].displays_text_p)
10494 || (!w->desired_matrix->rows[vpos + header_line_p].enabled_p
10495 && w->current_matrix->rows[vpos + header_line_p].displays_text_p))
5f5c8ee5 10496 break;
12adba34 10497
5f5c8ee5
GM
10498 w->window_end_vpos = make_number (vpos);
10499 }
10500 else
10501 abort ();
10502
10503 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
10504 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 10505
5f5c8ee5
GM
10506 /* Record that display has not been completed. */
10507 w->window_end_valid = Qnil;
10508 w->desired_matrix->no_scrolling_p = 1;
10509 return 1;
12adba34 10510}
0f9c0ff0 10511
a2889657 10512
5f5c8ee5
GM
10513\f
10514/***********************************************************************
10515 More debugging support
10516 ***********************************************************************/
a2889657 10517
5f5c8ee5 10518#if GLYPH_DEBUG
a2889657 10519
5f5c8ee5
GM
10520 void dump_glyph_row P_ ((struct glyph_matrix *, int, int));
10521static void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
1c9241f5 10522
31b24551 10523
5f5c8ee5
GM
10524/* Dump the contents of glyph matrix MATRIX on stderr. If
10525 WITH_GLYPHS_P is non-zero, dump glyph contents as well. */
ca26e1c8 10526
5f5c8ee5
GM
10527void
10528dump_glyph_matrix (matrix, with_glyphs_p)
10529 struct glyph_matrix *matrix;
10530 int with_glyphs_p;
10531{
efc63ef0 10532 int i;
5f5c8ee5
GM
10533 for (i = 0; i < matrix->nrows; ++i)
10534 dump_glyph_row (matrix, i, with_glyphs_p);
10535}
31b24551 10536
68a37fa8 10537
5f5c8ee5
GM
10538/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
10539 WITH_GLYPH_SP non-zero means dump glyph contents, too. */
a2889657 10540
5f5c8ee5
GM
10541void
10542dump_glyph_row (matrix, vpos, with_glyphs_p)
10543 struct glyph_matrix *matrix;
10544 int vpos, with_glyphs_p;
10545{
10546 struct glyph_row *row;
10547
10548 if (vpos < 0 || vpos >= matrix->nrows)
10549 return;
10550
10551 row = MATRIX_ROW (matrix, vpos);
10552
10553 fprintf (stderr, "Row Start End Used oEI><O\\CTZF X Y W\n");
10554 fprintf (stderr, "=============================================\n");
10555
10556 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d\n",
10557 row - matrix->rows,
10558 MATRIX_ROW_START_CHARPOS (row),
10559 MATRIX_ROW_END_CHARPOS (row),
10560 row->used[TEXT_AREA],
10561 row->contains_overlapping_glyphs_p,
10562 row->enabled_p,
10563 row->inverse_p,
10564 row->truncated_on_left_p,
10565 row->truncated_on_right_p,
10566 row->overlay_arrow_p,
10567 row->continued_p,
10568 MATRIX_ROW_CONTINUATION_LINE_P (row),
10569 row->displays_text_p,
10570 row->ends_at_zv_p,
10571 row->fill_line_p,
10572 row->x,
10573 row->y,
10574 row->pixel_width);
10575 fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
10576 row->end.overlay_string_index);
10577 fprintf (stderr, "%9d %5d\n",
10578 CHARPOS (row->start.string_pos),
10579 CHARPOS (row->end.string_pos));
10580 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
10581 row->end.dpvec_index);
10582
10583 if (with_glyphs_p)
bd66d1ba 10584 {
5f5c8ee5
GM
10585 struct glyph *glyph, *glyph_end;
10586 int prev_had_glyphs_p;
10587
10588 glyph = row->glyphs[TEXT_AREA];
10589 glyph_end = glyph + row->used[TEXT_AREA];
10590
10591 /* Glyph for a line end in text. */
10592 if (glyph == glyph_end && glyph->charpos > 0)
10593 ++glyph_end;
10594
10595 if (glyph < glyph_end)
bd66d1ba 10596 {
5f5c8ee5
GM
10597 fprintf (stderr, " Glyph Type Pos W Code C Face LR\n");
10598 prev_had_glyphs_p = 1;
bd66d1ba
RS
10599 }
10600 else
5f5c8ee5
GM
10601 prev_had_glyphs_p = 0;
10602
10603 while (glyph < glyph_end)
f7b4b63a 10604 {
5f5c8ee5
GM
10605 if (glyph->type == CHAR_GLYPH)
10606 {
10607 fprintf (stderr,
10608 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10609 glyph - row->glyphs[TEXT_AREA],
10610 'C',
10611 glyph->charpos,
10612 glyph->pixel_width,
43d120d8
KH
10613 glyph->u.ch,
10614 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
10615 ? glyph->u.ch
5f5c8ee5 10616 : '.'),
43d120d8 10617 glyph->face_id,
5f5c8ee5
GM
10618 glyph->left_box_line_p,
10619 glyph->right_box_line_p);
10620 }
10621 else if (glyph->type == STRETCH_GLYPH)
10622 {
10623 fprintf (stderr,
10624 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10625 glyph - row->glyphs[TEXT_AREA],
10626 'S',
10627 glyph->charpos,
10628 glyph->pixel_width,
10629 0,
10630 '.',
bcdda9a4 10631 glyph->face_id,
5f5c8ee5
GM
10632 glyph->left_box_line_p,
10633 glyph->right_box_line_p);
10634 }
10635 else if (glyph->type == IMAGE_GLYPH)
10636 {
10637 fprintf (stderr,
10638 " %5d %4c %6d %3d 0x%05x %c %4d %1.1d%1.1d\n",
10639 glyph - row->glyphs[TEXT_AREA],
10640 'I',
10641 glyph->charpos,
10642 glyph->pixel_width,
43d120d8 10643 glyph->u.img_id,
5f5c8ee5 10644 '.',
bcdda9a4 10645 glyph->face_id,
5f5c8ee5
GM
10646 glyph->left_box_line_p,
10647 glyph->right_box_line_p);
10648 }
10649 ++glyph;
f7b4b63a 10650 }
f4faa47c 10651 }
5f5c8ee5 10652}
f4faa47c 10653
a2889657 10654
5f5c8ee5
GM
10655DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
10656 Sdump_glyph_matrix, 0, 1, "p",
10657 "Dump the current matrix of the selected window to stderr.\n\
10658Shows contents of glyph row structures. With non-nil optional\n\
10659parameter WITH-GLYPHS-P, dump glyphs as well.")
10660 (with_glyphs_p)
10661{
10662 struct window *w = XWINDOW (selected_window);
10663 struct buffer *buffer = XBUFFER (w->buffer);
10664
10665 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
10666 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
10667 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
10668 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
10669 fprintf (stderr, "=============================================\n");
10670 dump_glyph_matrix (w->current_matrix, !NILP (with_glyphs_p));
10671 return Qnil;
10672}
1c2250c2 10673
1fca3fae 10674
5f5c8ee5
GM
10675DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 1, "",
10676 "Dump glyph row ROW to stderr.")
10677 (row)
10678 Lisp_Object row;
10679{
10680 CHECK_NUMBER (row, 0);
10681 dump_glyph_row (XWINDOW (selected_window)->current_matrix, XINT (row), 1);
10682 return Qnil;
10683}
1fca3fae 10684
67481ae5 10685
e037b9ec 10686DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row,
5f5c8ee5
GM
10687 0, 0, "", "")
10688 ()
10689{
886bd6f2
GM
10690 struct frame *sf = SELECTED_FRAME ();
10691 struct glyph_matrix *m = (XWINDOW (sf->tool_bar_window)
5f5c8ee5
GM
10692 ->current_matrix);
10693 dump_glyph_row (m, 0, 1);
10694 return Qnil;
10695}
ca26e1c8 10696
0f9c0ff0 10697
5f5c8ee5
GM
10698DEFUN ("trace-redisplay-toggle", Ftrace_redisplay_toggle,
10699 Strace_redisplay_toggle, 0, 0, "",
10700 "Toggle tracing of redisplay.")
10701 ()
10702{
10703 trace_redisplay_p = !trace_redisplay_p;
10704 return Qnil;
10705}
bf9249e3
GM
10706
10707
10708DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, 1, "",
10709 "Print STRING to stderr.")
10710 (string)
10711 Lisp_Object string;
10712{
10713 CHECK_STRING (string, 0);
10714 fprintf (stderr, "%s", XSTRING (string)->data);
10715 return Qnil;
10716}
5f5c8ee5
GM
10717
10718#endif /* GLYPH_DEBUG */
ca26e1c8 10719
ca26e1c8 10720
5f5c8ee5
GM
10721\f
10722/***********************************************************************
10723 Building Desired Matrix Rows
10724 ***********************************************************************/
a2889657 10725
5f5c8ee5
GM
10726/* Return a temporary glyph row holding the glyphs of an overlay
10727 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 10728
5f5c8ee5
GM
10729static struct glyph_row *
10730get_overlay_arrow_glyph_row (w)
10731 struct window *w;
10732{
10733 struct frame *f = XFRAME (WINDOW_FRAME (w));
10734 struct buffer *buffer = XBUFFER (w->buffer);
10735 struct buffer *old = current_buffer;
10736 unsigned char *arrow_string = XSTRING (Voverlay_arrow_string)->data;
10737 int arrow_len = XSTRING (Voverlay_arrow_string)->size;
10738 unsigned char *arrow_end = arrow_string + arrow_len;
10739 unsigned char *p;
10740 struct it it;
10741 int multibyte_p;
10742 int n_glyphs_before;
10743
10744 set_buffer_temp (buffer);
10745 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
10746 it.glyph_row->used[TEXT_AREA] = 0;
10747 SET_TEXT_POS (it.position, 0, 0);
10748
10749 multibyte_p = !NILP (buffer->enable_multibyte_characters);
10750 p = arrow_string;
10751 while (p < arrow_end)
10752 {
10753 Lisp_Object face, ilisp;
10754
10755 /* Get the next character. */
10756 if (multibyte_p)
4fdb80f2 10757 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
10758 else
10759 it.c = *p, it.len = 1;
10760 p += it.len;
10761
10762 /* Get its face. */
10763 XSETFASTINT (ilisp, p - arrow_string);
10764 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
10765 it.face_id = compute_char_face (f, it.c, face);
10766
10767 /* Compute its width, get its glyphs. */
10768 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 10769 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
10770 PRODUCE_GLYPHS (&it);
10771
10772 /* If this character doesn't fit any more in the line, we have
10773 to remove some glyphs. */
10774 if (it.current_x > it.last_visible_x)
10775 {
10776 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
10777 break;
10778 }
10779 }
10780
10781 set_buffer_temp (old);
10782 return it.glyph_row;
10783}
ca26e1c8 10784
b0a0fbda 10785
5f5c8ee5
GM
10786/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
10787 glyphs are only inserted for terminal frames since we can't really
10788 win with truncation glyphs when partially visible glyphs are
10789 involved. Which glyphs to insert is determined by
10790 produce_special_glyphs. */
67481ae5 10791
5f5c8ee5
GM
10792static void
10793insert_left_trunc_glyphs (it)
10794 struct it *it;
10795{
10796 struct it truncate_it;
10797 struct glyph *from, *end, *to, *toend;
10798
10799 xassert (!FRAME_WINDOW_P (it->f));
10800
10801 /* Get the truncation glyphs. */
10802 truncate_it = *it;
10803 truncate_it.charset = -1;
10804 truncate_it.current_x = 0;
10805 truncate_it.face_id = DEFAULT_FACE_ID;
10806 truncate_it.glyph_row = &scratch_glyph_row;
10807 truncate_it.glyph_row->used[TEXT_AREA] = 0;
10808 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
10809 truncate_it.object = 0;
10810 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
10811
10812 /* Overwrite glyphs from IT with truncation glyphs. */
10813 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
10814 end = from + truncate_it.glyph_row->used[TEXT_AREA];
10815 to = it->glyph_row->glyphs[TEXT_AREA];
10816 toend = to + it->glyph_row->used[TEXT_AREA];
10817
10818 while (from < end)
10819 *to++ = *from++;
10820
10821 /* There may be padding glyphs left over. Remove them. */
10822 from = to;
10823 while (from < toend && CHAR_GLYPH_PADDING_P (*from))
10824 ++from;
10825 while (from < toend)
10826 *to++ = *from++;
10827
10828 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
10829}
e0bfbde6 10830
e0bfbde6 10831
5f5c8ee5 10832/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 10833
5f5c8ee5
GM
10834 Most of the time, ascent and height of a display line will be equal
10835 to the max_ascent and max_height values of the display iterator
10836 structure. This is not the case if
67481ae5 10837
5f5c8ee5
GM
10838 1. We hit ZV without displaying anything. In this case, max_ascent
10839 and max_height will be zero.
1c9241f5 10840
5f5c8ee5
GM
10841 2. We have some glyphs that don't contribute to the line height.
10842 (The glyph row flag contributes_to_line_height_p is for future
10843 pixmap extensions).
f6fd109b 10844
5f5c8ee5
GM
10845 The first case is easily covered by using default values because in
10846 these cases, the line height does not really matter, except that it
10847 must not be zero. */
67481ae5 10848
5f5c8ee5
GM
10849static void
10850compute_line_metrics (it)
10851 struct it *it;
10852{
10853 struct glyph_row *row = it->glyph_row;
10854 int area, i;
1c2250c2 10855
5f5c8ee5
GM
10856 if (FRAME_WINDOW_P (it->f))
10857 {
045dee35 10858 int i, header_line_height;
1c2250c2 10859
5f5c8ee5
GM
10860 /* The line may consist of one space only, that was added to
10861 place the cursor on it. If so, the row's height hasn't been
10862 computed yet. */
10863 if (row->height == 0)
10864 {
10865 if (it->max_ascent + it->max_descent == 0)
312246d1 10866 it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
5f5c8ee5
GM
10867 row->ascent = it->max_ascent;
10868 row->height = it->max_ascent + it->max_descent;
312246d1
GM
10869 row->phys_ascent = it->max_phys_ascent;
10870 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
10871 }
10872
10873 /* Compute the width of this line. */
10874 row->pixel_width = row->x;
10875 for (i = 0; i < row->used[TEXT_AREA]; ++i)
10876 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
10877
10878 xassert (row->pixel_width >= 0);
10879 xassert (row->ascent >= 0 && row->height > 0);
10880
312246d1
GM
10881 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
10882 || MATRIX_ROW_OVERLAPS_PRED_P (row));
10883
10884 /* If first line's physical ascent is larger than its logical
10885 ascent, use the physical ascent, and make the row taller.
10886 This makes accented characters fully visible. */
10887 if (row == it->w->desired_matrix->rows
10888 && row->phys_ascent > row->ascent)
10889 {
10890 row->height += row->phys_ascent - row->ascent;
10891 row->ascent = row->phys_ascent;
10892 }
10893
5f5c8ee5
GM
10894 /* Compute how much of the line is visible. */
10895 row->visible_height = row->height;
10896
045dee35
GM
10897 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
10898 if (row->y < header_line_height)
10899 row->visible_height -= header_line_height - row->y;
5f5c8ee5
GM
10900 else
10901 {
10902 int max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
10903 if (row->y + row->height > max_y)
10904 row->visible_height -= row->y + row->height - max_y;
10905 }
10906 }
10907 else
10908 {
10909 row->pixel_width = row->used[TEXT_AREA];
312246d1
GM
10910 row->ascent = row->phys_ascent = 0;
10911 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 10912 }
67481ae5 10913
5f5c8ee5
GM
10914 /* Compute a hash code for this row. */
10915 row->hash = 0;
10916 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
10917 for (i = 0; i < row->used[area]; ++i)
10918 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
10919 + row->glyphs[area][i].u.val
43d120d8
KH
10920 + row->glyphs[area][i].face_id
10921 + row->glyphs[area][i].padding_p
5f5c8ee5 10922 + (row->glyphs[area][i].type << 2));
a2889657 10923
5f5c8ee5 10924 it->max_ascent = it->max_descent = 0;
312246d1 10925 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 10926}
12adba34 10927
ca26e1c8 10928
5f5c8ee5
GM
10929/* Append one space to the glyph row of iterator IT if doing a
10930 window-based redisplay. DEFAULT_FACE_P non-zero means let the
10931 space have the default face, otherwise let it have the same face as
80c6cb1f 10932 IT->face_id. Value is non-zero if a space was added.
c6e89d6c
GM
10933
10934 This function is called to make sure that there is always one glyph
10935 at the end of a glyph row that the cursor can be set on under
10936 window-systems. (If there weren't such a glyph we would not know
10937 how wide and tall a box cursor should be displayed).
10938
10939 At the same time this space let's a nicely handle clearing to the
10940 end of the line if the row ends in italic text. */
ca26e1c8 10941
80c6cb1f 10942static int
5f5c8ee5
GM
10943append_space (it, default_face_p)
10944 struct it *it;
10945 int default_face_p;
10946{
10947 if (FRAME_WINDOW_P (it->f))
10948 {
10949 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 10950
5f5c8ee5
GM
10951 if (it->glyph_row->glyphs[TEXT_AREA] + n
10952 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 10953 {
5f5c8ee5
GM
10954 /* Save some values that must not be changed. */
10955 int saved_x = it->current_x;
10956 struct text_pos saved_pos;
10957 int saved_what = it->what;
10958 int saved_face_id = it->face_id;
10959 int saved_charset = it->charset;
10960 Lisp_Object saved_object;
10961
10962 saved_object = it->object;
10963 saved_pos = it->position;
10964
10965 it->what = IT_CHARACTER;
10966 bzero (&it->position, sizeof it->position);
10967 it->object = 0;
10968 it->c = ' ';
10969 it->len = 1;
10970 it->charset = CHARSET_ASCII;
10971
10972 if (default_face_p)
10973 it->face_id = DEFAULT_FACE_ID;
10974 if (it->multibyte_p)
10975 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, CHARSET_ASCII);
10976 else
10977 it->face_id = FACE_FOR_CHARSET (it->f, it->face_id, -1);
1842fc1a 10978
5f5c8ee5
GM
10979 PRODUCE_GLYPHS (it);
10980
10981 it->current_x = saved_x;
10982 it->object = saved_object;
10983 it->position = saved_pos;
10984 it->what = saved_what;
10985 it->face_id = saved_face_id;
10986 it->charset = saved_charset;
80c6cb1f 10987 return 1;
5f5c8ee5
GM
10988 }
10989 }
80c6cb1f
GM
10990
10991 return 0;
5f5c8ee5 10992}
12adba34 10993
1842fc1a 10994
5f5c8ee5
GM
10995/* Extend the face of the last glyph in the text area of IT->glyph_row
10996 to the end of the display line. Called from display_line.
10997 If the glyph row is empty, add a space glyph to it so that we
10998 know the face to draw. Set the glyph row flag fill_line_p. */
10999
11000static void
11001extend_face_to_end_of_line (it)
11002 struct it *it;
11003{
11004 struct face *face;
11005 struct frame *f = it->f;
1842fc1a 11006
5f5c8ee5
GM
11007 /* If line is already filled, do nothing. */
11008 if (it->current_x >= it->last_visible_x)
11009 return;
11010
11011 /* Face extension extends the background and box of IT->face_id
11012 to the end of the line. If the background equals the background
11013 of the frame, we haven't to do anything. */
11014 face = FACE_FROM_ID (f, it->face_id);
11015 if (FRAME_WINDOW_P (f)
11016 && face->box == FACE_NO_BOX
11017 && face->background == FRAME_BACKGROUND_PIXEL (f)
11018 && !face->stipple)
11019 return;
1842fc1a 11020
5f5c8ee5
GM
11021 /* Set the glyph row flag indicating that the face of the last glyph
11022 in the text area has to be drawn to the end of the text area. */
11023 it->glyph_row->fill_line_p = 1;
545e04f6 11024
5f5c8ee5
GM
11025 /* If current charset of IT is not ASCII, make sure we have the
11026 ASCII face. This will be automatically undone the next time
11027 get_next_display_element returns a character from a different
11028 charset. Note that the charset will always be ASCII in unibyte
11029 text. */
11030 if (it->charset != CHARSET_ASCII)
11031 {
11032 it->charset = CHARSET_ASCII;
11033 it->face_id = FACE_FOR_CHARSET (f, it->face_id, CHARSET_ASCII);
11034 }
545e04f6 11035
5f5c8ee5
GM
11036 if (FRAME_WINDOW_P (f))
11037 {
11038 /* If the row is empty, add a space with the current face of IT,
11039 so that we know which face to draw. */
11040 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 11041 {
5f5c8ee5 11042 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
43d120d8 11043 it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
5f5c8ee5 11044 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 11045 }
5f5c8ee5
GM
11046 }
11047 else
11048 {
11049 /* Save some values that must not be changed. */
11050 int saved_x = it->current_x;
11051 struct text_pos saved_pos;
11052 Lisp_Object saved_object;
11053 int saved_what = it->what;
11054
11055 saved_object = it->object;
11056 saved_pos = it->position;
11057
11058 it->what = IT_CHARACTER;
11059 bzero (&it->position, sizeof it->position);
11060 it->object = 0;
11061 it->c = ' ';
11062 it->len = 1;
11063
11064 PRODUCE_GLYPHS (it);
11065
11066 while (it->current_x <= it->last_visible_x)
11067 PRODUCE_GLYPHS (it);
11068
11069 /* Don't count these blanks really. It would let us insert a left
11070 truncation glyph below and make us set the cursor on them, maybe. */
11071 it->current_x = saved_x;
11072 it->object = saved_object;
11073 it->position = saved_pos;
11074 it->what = saved_what;
11075 }
11076}
12adba34 11077
545e04f6 11078
5f5c8ee5
GM
11079/* Value is non-zero if text starting at CHARPOS in current_buffer is
11080 trailing whitespace. */
1c9241f5 11081
5f5c8ee5
GM
11082static int
11083trailing_whitespace_p (charpos)
11084 int charpos;
11085{
11086 int bytepos = CHAR_TO_BYTE (charpos);
11087 int c = 0;
7bbe686f 11088
5f5c8ee5
GM
11089 while (bytepos < ZV_BYTE
11090 && (c = FETCH_CHAR (bytepos),
11091 c == ' ' || c == '\t'))
11092 ++bytepos;
0d09d1e6 11093
8f897821
GM
11094 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
11095 {
11096 if (bytepos != PT_BYTE)
11097 return 1;
11098 }
11099 return 0;
5f5c8ee5 11100}
31b24551 11101
545e04f6 11102
5f5c8ee5 11103/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 11104
5f5c8ee5
GM
11105void
11106highlight_trailing_whitespace (f, row)
11107 struct frame *f;
11108 struct glyph_row *row;
11109{
11110 int used = row->used[TEXT_AREA];
11111
11112 if (used)
11113 {
11114 struct glyph *start = row->glyphs[TEXT_AREA];
11115 struct glyph *glyph = start + used - 1;
11116
11117 /* Skip over the space glyph inserted to display the
11118 cursor at the end of a line. */
11119 if (glyph->type == CHAR_GLYPH
43d120d8 11120 && glyph->u.ch == ' '
5f5c8ee5
GM
11121 && glyph->object == 0)
11122 --glyph;
11123
11124 /* If last glyph is a space or stretch, and it's trailing
11125 whitespace, set the face of all trailing whitespace glyphs in
11126 IT->glyph_row to `trailing-whitespace'. */
11127 if (glyph >= start
11128 && BUFFERP (glyph->object)
11129 && (glyph->type == STRETCH_GLYPH
11130 || (glyph->type == CHAR_GLYPH
43d120d8 11131 && glyph->u.ch == ' '))
5f5c8ee5 11132 && trailing_whitespace_p (glyph->charpos))
545e04f6 11133 {
5f5c8ee5
GM
11134 int face_id = lookup_named_face (f, Qtrailing_whitespace,
11135 CHARSET_ASCII);
11136
11137 while (glyph >= start
11138 && BUFFERP (glyph->object)
11139 && (glyph->type == STRETCH_GLYPH
11140 || (glyph->type == CHAR_GLYPH
43d120d8
KH
11141 && glyph->u.ch == ' ')))
11142 (glyph--)->face_id = face_id;
545e04f6 11143 }
a2889657 11144 }
5f5c8ee5 11145}
a2889657 11146
5fcbb24d 11147
5f5c8ee5
GM
11148/* Construct the glyph row IT->glyph_row in the desired matrix of
11149 IT->w from text at the current position of IT. See dispextern.h
11150 for an overview of struct it. Value is non-zero if
11151 IT->glyph_row displays text, as opposed to a line displaying ZV
11152 only. */
11153
11154static int
11155display_line (it)
11156 struct it *it;
11157{
11158 struct glyph_row *row = it->glyph_row;
11159
11160 /* We always start displaying at hpos zero even if hscrolled. */
11161 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 11162
5f5c8ee5
GM
11163 /* We must not display in a row that's not a text row. */
11164 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
11165 < it->w->desired_matrix->nrows);
12adba34 11166
5f5c8ee5
GM
11167 /* Is IT->w showing the region? */
11168 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 11169
5f5c8ee5
GM
11170 /* Clear the result glyph row and enable it. */
11171 prepare_desired_row (row);
12adba34 11172
5f5c8ee5
GM
11173 row->y = it->current_y;
11174 row->start = it->current;
11175 row->continuation_lines_width = it->continuation_lines_width;
11176 row->displays_text_p = 1;
11177
11178 /* Arrange the overlays nicely for our purposes. Usually, we call
11179 display_line on only one line at a time, in which case this
11180 can't really hurt too much, or we call it on lines which appear
11181 one after another in the buffer, in which case all calls to
11182 recenter_overlay_lists but the first will be pretty cheap. */
11183 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
11184
5f5c8ee5
GM
11185 /* Move over display elements that are not visible because we are
11186 hscrolled. This may stop at an x-position < IT->first_visible_x
11187 if the first glyph is partially visible or if we hit a line end. */
11188 if (it->current_x < it->first_visible_x)
11189 move_it_in_display_line_to (it, ZV, it->first_visible_x,
11190 MOVE_TO_POS | MOVE_TO_X);
11191
11192 /* Get the initial row height. This is either the height of the
11193 text hscrolled, if there is any, or zero. */
11194 row->ascent = it->max_ascent;
11195 row->height = it->max_ascent + it->max_descent;
312246d1
GM
11196 row->phys_ascent = it->max_phys_ascent;
11197 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
11198
11199 /* Loop generating characters. The loop is left with IT on the next
11200 character to display. */
11201 while (1)
11202 {
11203 int n_glyphs_before, hpos_before, x_before;
11204 int x, i, nglyphs;
11205
11206 /* Retrieve the next thing to display. Value is zero if end of
11207 buffer reached. */
11208 if (!get_next_display_element (it))
11209 {
11210 /* Maybe add a space at the end of this line that is used to
1b335865
GM
11211 display the cursor there under X. Set the charpos of the
11212 first glyph of blank lines not corresponding to any text
11213 to -1. */
11214 if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
11215 || row->used[TEXT_AREA] == 0)
a2889657 11216 {
5f5c8ee5
GM
11217 row->glyphs[TEXT_AREA]->charpos = -1;
11218 row->displays_text_p = 0;
11219
11220 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines))
11221 row->indicate_empty_line_p = 1;
a2889657 11222 }
5f5c8ee5
GM
11223
11224 it->continuation_lines_width = 0;
11225 row->ends_at_zv_p = 1;
11226 break;
a2889657 11227 }
a2889657 11228
5f5c8ee5
GM
11229 /* Now, get the metrics of what we want to display. This also
11230 generates glyphs in `row' (which is IT->glyph_row). */
11231 n_glyphs_before = row->used[TEXT_AREA];
11232 x = it->current_x;
11233 PRODUCE_GLYPHS (it);
a2889657 11234
5f5c8ee5
GM
11235 /* If this display element was in marginal areas, continue with
11236 the next one. */
11237 if (it->area != TEXT_AREA)
a2889657 11238 {
5f5c8ee5
GM
11239 row->ascent = max (row->ascent, it->max_ascent);
11240 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11241 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11242 row->phys_height = max (row->phys_height,
11243 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11244 set_iterator_to_next (it);
11245 continue;
11246 }
5936754e 11247
5f5c8ee5
GM
11248 /* Does the display element fit on the line? If we truncate
11249 lines, we should draw past the right edge of the window. If
11250 we don't truncate, we want to stop so that we can display the
11251 continuation glyph before the right margin. If lines are
11252 continued, there are two possible strategies for characters
11253 resulting in more than 1 glyph (e.g. tabs): Display as many
11254 glyphs as possible in this line and leave the rest for the
11255 continuation line, or display the whole element in the next
11256 line. Original redisplay did the former, so we do it also. */
11257 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
11258 hpos_before = it->hpos;
11259 x_before = x;
11260
11261 if (nglyphs == 1
11262 && it->current_x < it->last_visible_x)
11263 {
11264 ++it->hpos;
11265 row->ascent = max (row->ascent, it->max_ascent);
11266 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11267 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11268 row->phys_height = max (row->phys_height,
11269 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11270 if (it->current_x - it->pixel_width < it->first_visible_x)
11271 row->x = x - it->first_visible_x;
11272 }
11273 else
11274 {
11275 int new_x;
11276 struct glyph *glyph;
11277
11278 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 11279 {
5f5c8ee5
GM
11280 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
11281 new_x = x + glyph->pixel_width;
11282
11283 if (/* Lines are continued. */
11284 !it->truncate_lines_p
11285 && (/* Glyph doesn't fit on the line. */
11286 new_x > it->last_visible_x
11287 /* Or it fits exactly on a window system frame. */
11288 || (new_x == it->last_visible_x
11289 && FRAME_WINDOW_P (it->f))))
a2889657 11290 {
5f5c8ee5
GM
11291 /* End of a continued line. */
11292
11293 if (it->hpos == 0
11294 || (new_x == it->last_visible_x
11295 && FRAME_WINDOW_P (it->f)))
11296 {
11297 /* Current glyph fits exactly on the line. We
11298 must continue the line because we can't draw
11299 the cursor after the glyph. */
11300 row->continued_p = 1;
11301 it->current_x = new_x;
11302 it->continuation_lines_width += new_x;
11303 ++it->hpos;
11304 if (i == nglyphs - 1)
11305 set_iterator_to_next (it);
11306 }
11307 else
5936754e 11308 {
5f5c8ee5
GM
11309 /* Display element draws past the right edge of
11310 the window. Restore positions to values
11311 before the element. The next line starts
11312 with current_x before the glyph that could
11313 not be displayed, so that TAB works right. */
11314 row->used[TEXT_AREA] = n_glyphs_before + i;
11315
11316 /* Display continuation glyphs. */
11317 if (!FRAME_WINDOW_P (it->f))
11318 produce_special_glyphs (it, IT_CONTINUATION);
11319 row->continued_p = 1;
11320
11321 it->current_x = x;
11322 it->continuation_lines_width += x;
5936754e 11323 }
5f5c8ee5
GM
11324 break;
11325 }
11326 else if (new_x > it->first_visible_x)
11327 {
11328 /* Increment number of glyphs actually displayed. */
11329 ++it->hpos;
11330
11331 if (x < it->first_visible_x)
11332 /* Glyph is partially visible, i.e. row starts at
11333 negative X position. */
11334 row->x = x - it->first_visible_x;
11335 }
11336 else
11337 {
11338 /* Glyph is completely off the left margin of the
11339 window. This should not happen because of the
11340 move_it_in_display_line at the start of
11341 this function. */
11342 abort ();
a2889657 11343 }
a2889657 11344 }
5f5c8ee5
GM
11345
11346 row->ascent = max (row->ascent, it->max_ascent);
11347 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
11348 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
11349 row->phys_height = max (row->phys_height,
11350 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
11351
11352 /* End of this display line if row is continued. */
11353 if (row->continued_p)
11354 break;
a2889657 11355 }
a2889657 11356
5f5c8ee5
GM
11357 /* Is this a line end? If yes, we're also done, after making
11358 sure that a non-default face is extended up to the right
11359 margin of the window. */
11360 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 11361 {
5f5c8ee5
GM
11362 int used_before = row->used[TEXT_AREA];
11363
11364 /* Add a space at the end of the line that is used to
11365 display the cursor there. */
11366 append_space (it, 0);
11367
11368 /* Extend the face to the end of the line. */
11369 extend_face_to_end_of_line (it);
11370
11371 /* Make sure we have the position. */
11372 if (used_before == 0)
11373 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
11374
11375 /* Consume the line end. This skips over invisible lines. */
11376 set_iterator_to_next (it);
11377 it->continuation_lines_width = 0;
11378 break;
1c9241f5 11379 }
a2889657 11380
5f5c8ee5
GM
11381 /* Proceed with next display element. Note that this skips
11382 over lines invisible because of selective display. */
11383 set_iterator_to_next (it);
b1d1124b 11384
5f5c8ee5
GM
11385 /* If we truncate lines, we are done when the last displayed
11386 glyphs reach past the right margin of the window. */
11387 if (it->truncate_lines_p
11388 && (FRAME_WINDOW_P (it->f)
11389 ? (it->current_x >= it->last_visible_x)
11390 : (it->current_x > it->last_visible_x)))
75d13c64 11391 {
5f5c8ee5
GM
11392 /* Maybe add truncation glyphs. */
11393 if (!FRAME_WINDOW_P (it->f))
11394 {
11395 --it->glyph_row->used[TEXT_AREA];
11396 produce_special_glyphs (it, IT_TRUNCATION);
11397 }
11398
11399 row->truncated_on_right_p = 1;
11400 it->continuation_lines_width = 0;
312246d1 11401 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
11402 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
11403 it->hpos = hpos_before;
11404 it->current_x = x_before;
11405 break;
75d13c64 11406 }
a2889657 11407 }
a2889657 11408
5f5c8ee5
GM
11409 /* If line is not empty and hscrolled, maybe insert truncation glyphs
11410 at the left window margin. */
11411 if (it->first_visible_x
11412 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
11413 {
11414 if (!FRAME_WINDOW_P (it->f))
11415 insert_left_trunc_glyphs (it);
11416 row->truncated_on_left_p = 1;
11417 }
a2889657 11418
5f5c8ee5
GM
11419 /* If the start of this line is the overlay arrow-position, then
11420 mark this glyph row as the one containing the overlay arrow.
11421 This is clearly a mess with variable size fonts. It would be
11422 better to let it be displayed like cursors under X. */
e24c997d 11423 if (MARKERP (Voverlay_arrow_position)
a2889657 11424 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
11425 && (MATRIX_ROW_START_CHARPOS (row)
11426 == marker_position (Voverlay_arrow_position))
e24c997d 11427 && STRINGP (Voverlay_arrow_string)
a2889657
JB
11428 && ! overlay_arrow_seen)
11429 {
5f5c8ee5
GM
11430 /* Overlay arrow in window redisplay is a bitmap. */
11431 if (!FRAME_WINDOW_P (it->f))
c4628384 11432 {
5f5c8ee5
GM
11433 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
11434 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
11435 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
11436 struct glyph *p = row->glyphs[TEXT_AREA];
11437 struct glyph *p2, *end;
11438
11439 /* Copy the arrow glyphs. */
11440 while (glyph < arrow_end)
11441 *p++ = *glyph++;
11442
11443 /* Throw away padding glyphs. */
11444 p2 = p;
11445 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
11446 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
11447 ++p2;
11448 if (p2 > p)
212e4f87 11449 {
5f5c8ee5
GM
11450 while (p2 < end)
11451 *p++ = *p2++;
11452 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 11453 }
c4628384 11454 }
5f5c8ee5 11455
a2889657 11456 overlay_arrow_seen = 1;
5f5c8ee5 11457 row->overlay_arrow_p = 1;
a2889657
JB
11458 }
11459
5f5c8ee5
GM
11460 /* Compute pixel dimensions of this line. */
11461 compute_line_metrics (it);
11462
11463 /* Remember the position at which this line ends. */
11464 row->end = it->current;
11465
11466 /* Maybe set the cursor. If you change this, it's probably a good
11467 idea to also change the code in redisplay_window for cursor
11468 movement in an unchanged window. */
11469 if (it->w->cursor.vpos < 0
11470 && PT >= MATRIX_ROW_START_CHARPOS (row)
11471 && MATRIX_ROW_END_CHARPOS (row) >= PT
11472 && !(MATRIX_ROW_END_CHARPOS (row) == PT
11473 && (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)
11474 || !row->ends_at_zv_p)))
11475 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
11476
11477 /* Highlight trailing whitespace. */
8f897821 11478 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
11479 highlight_trailing_whitespace (it->f, it->glyph_row);
11480
11481 /* Prepare for the next line. This line starts horizontally at (X
11482 HPOS) = (0 0). Vertical positions are incremented. As a
11483 convenience for the caller, IT->glyph_row is set to the next
11484 row to be used. */
11485 it->current_x = it->hpos = 0;
11486 it->current_y += row->height;
11487 ++it->vpos;
11488 ++it->glyph_row;
11489 return row->displays_text_p;
a2889657 11490}
5f5c8ee5
GM
11491
11492
a2889657 11493\f
5f5c8ee5
GM
11494/***********************************************************************
11495 Menu Bar
11496 ***********************************************************************/
11497
11498/* Redisplay the menu bar in the frame for window W.
11499
11500 The menu bar of X frames that don't have X toolkit support is
11501 displayed in a special window W->frame->menu_bar_window.
11502
11503 The menu bar of terminal frames is treated specially as far as
11504 glyph matrices are concerned. Menu bar lines are not part of
11505 windows, so the update is done directly on the frame matrix rows
11506 for the menu bar. */
7ce2c095
RS
11507
11508static void
11509display_menu_bar (w)
11510 struct window *w;
11511{
5f5c8ee5
GM
11512 struct frame *f = XFRAME (WINDOW_FRAME (w));
11513 struct it it;
11514 Lisp_Object items;
8351baf2 11515 int i;
7ce2c095 11516
5f5c8ee5 11517 /* Don't do all this for graphical frames. */
dc937613 11518#ifdef HAVE_NTGUI
d129c4c2
KH
11519 if (!NILP (Vwindow_system))
11520 return;
dc937613 11521#endif
dc937613 11522#ifdef USE_X_TOOLKIT
d3413a53 11523 if (FRAME_X_P (f))
7ce2c095 11524 return;
5f5c8ee5
GM
11525#endif
11526
11527#ifdef USE_X_TOOLKIT
11528 xassert (!FRAME_WINDOW_P (f));
52377a47 11529 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5
GM
11530 it.first_visible_x = 0;
11531 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11532#else /* not USE_X_TOOLKIT */
11533 if (FRAME_WINDOW_P (f))
11534 {
11535 /* Menu bar lines are displayed in the desired matrix of the
11536 dummy window menu_bar_window. */
11537 struct window *menu_w;
11538 xassert (WINDOWP (f->menu_bar_window));
11539 menu_w = XWINDOW (f->menu_bar_window);
11540 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 11541 MENU_FACE_ID);
5f5c8ee5
GM
11542 it.first_visible_x = 0;
11543 it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
11544 }
11545 else
11546 {
11547 /* This is a TTY frame, i.e. character hpos/vpos are used as
11548 pixel x/y. */
11549 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 11550 MENU_FACE_ID);
5f5c8ee5
GM
11551 it.first_visible_x = 0;
11552 it.last_visible_x = FRAME_WIDTH (f);
11553 }
11554#endif /* not USE_X_TOOLKIT */
11555
11556 /* Clear all rows of the menu bar. */
11557 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
11558 {
11559 struct glyph_row *row = it.glyph_row + i;
11560 clear_glyph_row (row);
11561 row->enabled_p = 1;
11562 row->full_width_p = 1;
11563 }
7ce2c095 11564
5f5c8ee5
GM
11565 /* Make the first line of the menu bar appear in reverse video. */
11566 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
7ce2c095 11567
5f5c8ee5
GM
11568 /* Display all items of the menu bar. */
11569 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 11570 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 11571 {
5f5c8ee5
GM
11572 Lisp_Object string;
11573
11574 /* Stop at nil string. */
8351baf2
RS
11575 string = XVECTOR (items)->contents[i + 1];
11576 if (NILP (string))
11577 break;
2d66ad19 11578
5f5c8ee5
GM
11579 /* Remember where item was displayed. */
11580 XSETFASTINT (XVECTOR (items)->contents[i + 3], it.hpos);
7ce2c095 11581
5f5c8ee5
GM
11582 /* Display the item, pad with one space. */
11583 if (it.current_x < it.last_visible_x)
11584 display_string (NULL, string, Qnil, 0, 0, &it,
11585 XSTRING (string)->size + 1, 0, 0, -1);
7ce2c095
RS
11586 }
11587
2d66ad19 11588 /* Fill out the line with spaces. */
5f5c8ee5
GM
11589 if (it.current_x < it.last_visible_x)
11590 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 11591
5f5c8ee5
GM
11592 /* Compute the total height of the lines. */
11593 compute_line_metrics (&it);
7ce2c095 11594}
5f5c8ee5
GM
11595
11596
7ce2c095 11597\f
5f5c8ee5
GM
11598/***********************************************************************
11599 Mode Line
11600 ***********************************************************************/
11601
11602/* Display the mode and/or top line of window W. */
a2889657
JB
11603
11604static void
5f5c8ee5 11605display_mode_lines (w)
a2889657
JB
11606 struct window *w;
11607{
5f5c8ee5 11608 /* These will be set while the mode line specs are processed. */
aa6d10fa 11609 line_number_displayed = 0;
155ef550 11610 w->column_number_displayed = Qnil;
aa6d10fa 11611
5f5c8ee5 11612 if (WINDOW_WANTS_MODELINE_P (w))
045dee35
GM
11613 display_mode_line (w, MODE_LINE_FACE_ID,
11614 current_buffer->mode_line_format);
5f5c8ee5 11615
045dee35
GM
11616 if (WINDOW_WANTS_HEADER_LINE_P (w))
11617 display_mode_line (w, HEADER_LINE_FACE_ID,
11618 current_buffer->header_line_format);
5f5c8ee5 11619}
03b294dc 11620
03b294dc 11621
5f5c8ee5 11622/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 11623 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
5f5c8ee5 11624 FORMAT is the mode line format to display. */
03b294dc 11625
5f5c8ee5
GM
11626static void
11627display_mode_line (w, face_id, format)
11628 struct window *w;
11629 enum face_id face_id;
11630 Lisp_Object format;
11631{
11632 struct it it;
11633 struct face *face;
03b294dc 11634
5f5c8ee5
GM
11635 init_iterator (&it, w, -1, -1, NULL, face_id);
11636 prepare_desired_row (it.glyph_row);
11637
11638 /* Temporarily make frame's keyboard the current kboard so that
11639 kboard-local variables in the mode_line_format will get the right
11640 values. */
11641 push_frame_kboard (it.f);
11642 display_mode_element (&it, 0, 0, 0, format);
11643 pop_frame_kboard ();
a2889657 11644
5f5c8ee5
GM
11645 /* Fill up with spaces. */
11646 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
11647
11648 compute_line_metrics (&it);
11649 it.glyph_row->full_width_p = 1;
11650 it.glyph_row->mode_line_p = 1;
11651 it.glyph_row->inverse_p = mode_line_inverse_video != 0;
11652 it.glyph_row->continued_p = 0;
11653 it.glyph_row->truncated_on_left_p = 0;
11654 it.glyph_row->truncated_on_right_p = 0;
11655
11656 /* Make a 3D mode-line have a shadow at its right end. */
11657 face = FACE_FROM_ID (it.f, face_id);
11658 extend_face_to_end_of_line (&it);
11659 if (face->box != FACE_NO_BOX)
d7eb09a0 11660 {
5f5c8ee5
GM
11661 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
11662 + it.glyph_row->used[TEXT_AREA] - 1);
11663 last->right_box_line_p = 1;
d7eb09a0 11664 }
a2889657
JB
11665}
11666
a2889657 11667
5f5c8ee5
GM
11668/* Contribute ELT to the mode line for window IT->w. How it
11669 translates into text depends on its data type.
a2889657 11670
5f5c8ee5 11671 IT describes the display environment in which we display, as usual.
a2889657
JB
11672
11673 DEPTH is the depth in recursion. It is used to prevent
11674 infinite recursion here.
11675
5f5c8ee5
GM
11676 FIELD_WIDTH is the number of characters the display of ELT should
11677 occupy in the mode line, and PRECISION is the maximum number of
11678 characters to display from ELT's representation. See
11679 display_string for details. *
a2889657 11680
5f5c8ee5 11681 Returns the hpos of the end of the text generated by ELT. */
a2889657
JB
11682
11683static int
5f5c8ee5
GM
11684display_mode_element (it, depth, field_width, precision, elt)
11685 struct it *it;
a2889657 11686 int depth;
5f5c8ee5
GM
11687 int field_width, precision;
11688 Lisp_Object elt;
a2889657 11689{
5f5c8ee5
GM
11690 int n = 0, field, prec;
11691
a2889657
JB
11692 tail_recurse:
11693 if (depth > 10)
11694 goto invalid;
11695
11696 depth++;
11697
0220c518 11698 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
11699 {
11700 case Lisp_String:
11701 {
11702 /* A string: output it and check for %-constructs within it. */
5f5c8ee5
GM
11703 unsigned char c;
11704 unsigned char *this = XSTRING (elt)->data;
11705 unsigned char *lisp_string = this;
11706
11707 while ((precision <= 0 || n < precision)
11708 && *this
11709 && (frame_title_ptr
11710 || it->current_x < it->last_visible_x))
a2889657
JB
11711 {
11712 unsigned char *last = this;
5f5c8ee5
GM
11713
11714 /* Advance to end of string or next format specifier. */
a2889657
JB
11715 while ((c = *this++) != '\0' && c != '%')
11716 ;
5f5c8ee5 11717
a2889657
JB
11718 if (this - 1 != last)
11719 {
5f5c8ee5
GM
11720 /* Output to end of string or up to '%'. Field width
11721 is length of string. Don't output more than
11722 PRECISION allows us. */
11723 prec = --this - last;
11724 if (precision > 0 && prec > precision - n)
11725 prec = precision - n;
11726
d39b6696 11727 if (frame_title_ptr)
5f5c8ee5 11728 n += store_frame_title (last, prec, prec);
d39b6696 11729 else
5f5c8ee5
GM
11730 n += display_string (NULL, elt, Qnil, 0, last - lisp_string,
11731 it, 0, prec, 0, -1);
a2889657
JB
11732 }
11733 else /* c == '%' */
11734 {
5f5c8ee5
GM
11735 unsigned char *percent_position = this;
11736
11737 /* Get the specified minimum width. Zero means
11738 don't pad. */
11739 field = 0;
a2889657 11740 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 11741 field = field * 10 + c - '0';
a2889657 11742
5f5c8ee5
GM
11743 /* Don't pad beyond the total padding allowed. */
11744 if (field_width - n > 0 && field > field_width - n)
11745 field = field_width - n;
a2889657 11746
5f5c8ee5
GM
11747 /* Note that either PRECISION <= 0 or N < PRECISION. */
11748 prec = precision - n;
11749
a2889657 11750 if (c == 'M')
5f5c8ee5
GM
11751 n += display_mode_element (it, depth, field, prec,
11752 Vglobal_mode_string);
a2889657 11753 else if (c != 0)
d39b6696 11754 {
5f5c8ee5
GM
11755 unsigned char *spec
11756 = decode_mode_spec (it->w, c, field, prec);
11757
d39b6696 11758 if (frame_title_ptr)
5f5c8ee5 11759 n += store_frame_title (spec, field, prec);
d39b6696 11760 else
5f5c8ee5
GM
11761 {
11762 int nglyphs_before
11763 = it->glyph_row->used[TEXT_AREA];
11764 int charpos
11765 = percent_position - XSTRING (elt)->data;
11766 int nwritten
11767 = display_string (spec, Qnil, elt, charpos, 0, it,
11768 field, prec, 0, -1);
11769
11770 /* Assign to the glyphs written above the
11771 string where the `%x' came from, position
11772 of the `%'. */
11773 if (nwritten > 0)
11774 {
11775 struct glyph *glyph
11776 = (it->glyph_row->glyphs[TEXT_AREA]
11777 + nglyphs_before);
11778 int i;
11779
11780 for (i = 0; i < nwritten; ++i)
11781 {
11782 glyph[i].object = elt;
11783 glyph[i].charpos = charpos;
11784 }
11785
11786 n += nwritten;
11787 }
11788 }
d39b6696 11789 }
a2889657
JB
11790 }
11791 }
11792 }
11793 break;
11794
11795 case Lisp_Symbol:
11796 /* A symbol: process the value of the symbol recursively
11797 as if it appeared here directly. Avoid error if symbol void.
11798 Special case: if value of symbol is a string, output the string
11799 literally. */
11800 {
11801 register Lisp_Object tem;
11802 tem = Fboundp (elt);
265a9e55 11803 if (!NILP (tem))
a2889657
JB
11804 {
11805 tem = Fsymbol_value (elt);
11806 /* If value is a string, output that string literally:
11807 don't check for % within it. */
e24c997d 11808 if (STRINGP (tem))
d39b6696 11809 {
5f5c8ee5
GM
11810 prec = XSTRING (tem)->size;
11811 if (precision > 0 && prec > precision - n)
11812 prec = precision - n;
d39b6696 11813 if (frame_title_ptr)
5f5c8ee5 11814 n += store_frame_title (XSTRING (tem)->data, -1, prec);
d39b6696 11815 else
5f5c8ee5
GM
11816 n += display_string (NULL, tem, Qnil, 0, 0, it,
11817 0, prec, 0, -1);
d39b6696 11818 }
a2889657 11819 else if (!EQ (tem, elt))
5f5c8ee5
GM
11820 {
11821 /* Give up right away for nil or t. */
11822 elt = tem;
11823 goto tail_recurse;
11824 }
a2889657
JB
11825 }
11826 }
11827 break;
11828
11829 case Lisp_Cons:
11830 {
11831 register Lisp_Object car, tem;
11832
11833 /* A cons cell: three distinct cases.
11834 If first element is a string or a cons, process all the elements
11835 and effectively concatenate them.
11836 If first element is a negative number, truncate displaying cdr to
11837 at most that many characters. If positive, pad (with spaces)
11838 to at least that many characters.
11839 If first element is a symbol, process the cadr or caddr recursively
11840 according to whether the symbol's value is non-nil or nil. */
9472f927 11841 car = XCAR (elt);
5f5c8ee5
GM
11842 if (EQ (car, QCeval) && CONSP (XCDR (elt)))
11843 {
11844 /* An element of the form (:eval FORM) means evaluate FORM
11845 and use the result as mode line elements. */
11846 struct gcpro gcpro1;
11847 Lisp_Object spec;
11848
11849 spec = eval_form (XCAR (XCDR (elt)));
11850 GCPRO1 (spec);
11851 n += display_mode_element (it, depth, field_width - n,
11852 precision - n, spec);
11853 UNGCPRO;
11854 }
11855 else if (SYMBOLP (car))
a2889657
JB
11856 {
11857 tem = Fboundp (car);
9472f927 11858 elt = XCDR (elt);
e24c997d 11859 if (!CONSP (elt))
a2889657
JB
11860 goto invalid;
11861 /* elt is now the cdr, and we know it is a cons cell.
11862 Use its car if CAR has a non-nil value. */
265a9e55 11863 if (!NILP (tem))
a2889657
JB
11864 {
11865 tem = Fsymbol_value (car);
265a9e55 11866 if (!NILP (tem))
9472f927
GM
11867 {
11868 elt = XCAR (elt);
11869 goto tail_recurse;
11870 }
a2889657
JB
11871 }
11872 /* Symbol's value is nil (or symbol is unbound)
11873 Get the cddr of the original list
11874 and if possible find the caddr and use that. */
9472f927 11875 elt = XCDR (elt);
265a9e55 11876 if (NILP (elt))
a2889657 11877 break;
e24c997d 11878 else if (!CONSP (elt))
a2889657 11879 goto invalid;
9472f927 11880 elt = XCAR (elt);
a2889657
JB
11881 goto tail_recurse;
11882 }
e24c997d 11883 else if (INTEGERP (car))
a2889657
JB
11884 {
11885 register int lim = XINT (car);
9472f927 11886 elt = XCDR (elt);
a2889657 11887 if (lim < 0)
5f5c8ee5
GM
11888 {
11889 /* Negative int means reduce maximum width. */
11890 if (precision <= 0)
11891 precision = -lim;
11892 else
11893 precision = min (precision, -lim);
11894 }
a2889657
JB
11895 else if (lim > 0)
11896 {
11897 /* Padding specified. Don't let it be more than
11898 current maximum. */
5f5c8ee5
GM
11899 if (precision > 0)
11900 lim = min (precision, lim);
11901
a2889657
JB
11902 /* If that's more padding than already wanted, queue it.
11903 But don't reduce padding already specified even if
11904 that is beyond the current truncation point. */
5f5c8ee5 11905 field_width = max (lim, field_width);
a2889657
JB
11906 }
11907 goto tail_recurse;
11908 }
e24c997d 11909 else if (STRINGP (car) || CONSP (car))
a2889657
JB
11910 {
11911 register int limit = 50;
5f5c8ee5
GM
11912 /* Limit is to protect against circular lists. */
11913 while (CONSP (elt)
11914 && --limit > 0
11915 && (precision <= 0 || n < precision))
a2889657 11916 {
5f5c8ee5 11917 n += display_mode_element (it, depth, field_width - n,
9472f927
GM
11918 precision - n, XCAR (elt));
11919 elt = XCDR (elt);
a2889657
JB
11920 }
11921 }
11922 }
11923 break;
11924
11925 default:
11926 invalid:
d39b6696 11927 if (frame_title_ptr)
5f5c8ee5 11928 n += store_frame_title ("*invalid*", 0, precision - n);
d39b6696 11929 else
5f5c8ee5
GM
11930 n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
11931 precision - n, 0, 0);
11932 return n;
a2889657
JB
11933 }
11934
5f5c8ee5
GM
11935 /* Pad to FIELD_WIDTH. */
11936 if (field_width > 0 && n < field_width)
11937 {
11938 if (frame_title_ptr)
11939 n += store_frame_title ("", field_width - n, 0);
11940 else
11941 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
11942 0, 0, 0);
11943 }
11944
11945 return n;
a2889657 11946}
5f5c8ee5
GM
11947
11948
766525bc
RS
11949/* Write a null-terminated, right justified decimal representation of
11950 the positive integer D to BUF using a minimal field width WIDTH. */
11951
11952static void
11953pint2str (buf, width, d)
11954 register char *buf;
11955 register int width;
11956 register int d;
11957{
11958 register char *p = buf;
11959
11960 if (d <= 0)
5f5c8ee5 11961 *p++ = '0';
766525bc 11962 else
5f5c8ee5 11963 {
766525bc 11964 while (d > 0)
5f5c8ee5 11965 {
766525bc
RS
11966 *p++ = d % 10 + '0';
11967 d /= 10;
5f5c8ee5
GM
11968 }
11969 }
11970
11971 for (width -= (int) (p - buf); width > 0; --width)
11972 *p++ = ' ';
766525bc
RS
11973 *p-- = '\0';
11974 while (p > buf)
5f5c8ee5 11975 {
766525bc
RS
11976 d = *buf;
11977 *buf++ = *p;
11978 *p-- = d;
5f5c8ee5 11979 }
766525bc
RS
11980}
11981
5f5c8ee5 11982/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
11983 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
11984 type of CODING_SYSTEM. Return updated pointer into BUF. */
11985
6693a99a 11986static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 11987
1c9241f5
KH
11988static char *
11989decode_mode_spec_coding (coding_system, buf, eol_flag)
11990 Lisp_Object coding_system;
11991 register char *buf;
11992 int eol_flag;
11993{
1e1078d6 11994 Lisp_Object val;
916848d8 11995 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
302f2b38
EZ
11996 unsigned char *eol_str;
11997 int eol_str_len;
11998 /* The EOL conversion we are using. */
11999 Lisp_Object eoltype;
1e1078d6 12000
4a09dee0 12001 val = Fget (coding_system, Qcoding_system);
1c9241f5 12002
4a09dee0 12003 if (!VECTORP (val)) /* Not yet decided. */
1c9241f5 12004 {
916848d8
RS
12005 if (multibyte)
12006 *buf++ = '-';
21e989e3 12007 if (eol_flag)
302f2b38 12008 eoltype = eol_mnemonic_undecided;
1e1078d6 12009 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
12010 }
12011 else
12012 {
1e1078d6
RS
12013 Lisp_Object eolvalue;
12014
12015 eolvalue = Fget (coding_system, Qeol_type);
12016
916848d8
RS
12017 if (multibyte)
12018 *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
12019
1c9241f5
KH
12020 if (eol_flag)
12021 {
1e1078d6
RS
12022 /* The EOL conversion that is normal on this system. */
12023
12024 if (NILP (eolvalue)) /* Not yet decided. */
12025 eoltype = eol_mnemonic_undecided;
12026 else if (VECTORP (eolvalue)) /* Not yet decided. */
12027 eoltype = eol_mnemonic_undecided;
12028 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
12029 eoltype = (XFASTINT (eolvalue) == 0
12030 ? eol_mnemonic_unix
12031 : (XFASTINT (eolvalue) == 1
12032 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
12033 }
12034 }
5f5c8ee5 12035
302f2b38
EZ
12036 if (eol_flag)
12037 {
12038 /* Mention the EOL conversion if it is not the usual one. */
12039 if (STRINGP (eoltype))
12040 {
12041 eol_str = XSTRING (eoltype)->data;
12042 eol_str_len = XSTRING (eoltype)->size;
12043 }
f30b3499
KH
12044 else if (INTEGERP (eoltype)
12045 && CHAR_VALID_P (XINT (eoltype), 0))
12046 {
4a09dee0 12047 eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
260a86a0 12048 eol_str_len = CHAR_STRING (XINT (eoltype), eol_str);
f30b3499 12049 }
302f2b38
EZ
12050 else
12051 {
12052 eol_str = invalid_eol_type;
12053 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 12054 }
f30b3499 12055 bcopy (eol_str, buf, eol_str_len);
302f2b38 12056 buf += eol_str_len;
1c9241f5 12057 }
302f2b38 12058
1c9241f5
KH
12059 return buf;
12060}
12061
a2889657 12062/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
12063 generated by character C. PRECISION >= 0 means don't return a
12064 string longer than that value. FIELD_WIDTH > 0 means pad the
12065 string returned with spaces to that value. */
a2889657 12066
11e82b76
JB
12067static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
12068
a2889657 12069static char *
5f5c8ee5 12070decode_mode_spec (w, c, field_width, precision)
a2889657 12071 struct window *w;
68c45bf0 12072 register int c;
5f5c8ee5 12073 int field_width, precision;
a2889657 12074{
0b67772d 12075 Lisp_Object obj;
5f5c8ee5
GM
12076 struct frame *f = XFRAME (WINDOW_FRAME (w));
12077 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 12078 struct buffer *b = XBUFFER (w->buffer);
a2889657 12079
0b67772d 12080 obj = Qnil;
a2889657
JB
12081
12082 switch (c)
12083 {
1af9f229
RS
12084 case '*':
12085 if (!NILP (b->read_only))
12086 return "%";
12087 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12088 return "*";
12089 return "-";
12090
12091 case '+':
12092 /* This differs from %* only for a modified read-only buffer. */
12093 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12094 return "*";
12095 if (!NILP (b->read_only))
12096 return "%";
12097 return "-";
12098
12099 case '&':
12100 /* This differs from %* in ignoring read-only-ness. */
12101 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
12102 return "*";
12103 return "-";
12104
12105 case '%':
12106 return "%";
12107
12108 case '[':
12109 {
12110 int i;
12111 char *p;
12112
12113 if (command_loop_level > 5)
12114 return "[[[... ";
12115 p = decode_mode_spec_buf;
12116 for (i = 0; i < command_loop_level; i++)
12117 *p++ = '[';
12118 *p = 0;
12119 return decode_mode_spec_buf;
12120 }
12121
12122 case ']':
12123 {
12124 int i;
12125 char *p;
12126
12127 if (command_loop_level > 5)
12128 return " ...]]]";
12129 p = decode_mode_spec_buf;
12130 for (i = 0; i < command_loop_level; i++)
12131 *p++ = ']';
12132 *p = 0;
12133 return decode_mode_spec_buf;
12134 }
12135
12136 case '-':
12137 {
1af9f229 12138 register int i;
5f5c8ee5
GM
12139
12140 /* Let lots_of_dashes be a string of infinite length. */
12141 if (field_width <= 0
12142 || field_width > sizeof (lots_of_dashes))
1af9f229 12143 {
5f5c8ee5
GM
12144 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
12145 decode_mode_spec_buf[i] = '-';
12146 decode_mode_spec_buf[i] = '\0';
12147 return decode_mode_spec_buf;
1af9f229 12148 }
5f5c8ee5
GM
12149 else
12150 return lots_of_dashes;
1af9f229
RS
12151 }
12152
a2889657 12153 case 'b':
d39b6696 12154 obj = b->name;
a2889657
JB
12155 break;
12156
1af9f229
RS
12157 case 'c':
12158 {
12159 int col = current_column ();
12160 XSETFASTINT (w->column_number_displayed, col);
5f5c8ee5 12161 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
12162 return decode_mode_spec_buf;
12163 }
12164
12165 case 'F':
12166 /* %F displays the frame name. */
5f5c8ee5 12167 if (!NILP (f->title))
95184b48 12168 return (char *) XSTRING (f->title)->data;
fd8ff63d 12169 if (f->explicit_name || ! FRAME_WINDOW_P (f))
95184b48 12170 return (char *) XSTRING (f->name)->data;
9c6da96f 12171 return "Emacs";
1af9f229 12172
a2889657 12173 case 'f':
d39b6696 12174 obj = b->filename;
a2889657
JB
12175 break;
12176
aa6d10fa
RS
12177 case 'l':
12178 {
12adba34
RS
12179 int startpos = XMARKER (w->start)->charpos;
12180 int startpos_byte = marker_byte_position (w->start);
12181 int line, linepos, linepos_byte, topline;
aa6d10fa 12182 int nlines, junk;
aa6d10fa
RS
12183 int height = XFASTINT (w->height);
12184
12185 /* If we decided that this buffer isn't suitable for line numbers,
12186 don't forget that too fast. */
12187 if (EQ (w->base_line_pos, w->buffer))
766525bc 12188 goto no_value;
5300fd39
RS
12189 /* But do forget it, if the window shows a different buffer now. */
12190 else if (BUFFERP (w->base_line_pos))
12191 w->base_line_pos = Qnil;
aa6d10fa
RS
12192
12193 /* If the buffer is very big, don't waste time. */
d39b6696 12194 if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
aa6d10fa
RS
12195 {
12196 w->base_line_pos = Qnil;
12197 w->base_line_number = Qnil;
766525bc 12198 goto no_value;
aa6d10fa
RS
12199 }
12200
12201 if (!NILP (w->base_line_number)
12202 && !NILP (w->base_line_pos)
12adba34 12203 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
12204 {
12205 line = XFASTINT (w->base_line_number);
12206 linepos = XFASTINT (w->base_line_pos);
12adba34 12207 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
12208 }
12209 else
12210 {
12211 line = 1;
d39b6696 12212 linepos = BUF_BEGV (b);
12adba34 12213 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
12214 }
12215
12216 /* Count lines from base line to window start position. */
12adba34
RS
12217 nlines = display_count_lines (linepos, linepos_byte,
12218 startpos_byte,
12219 startpos, &junk);
aa6d10fa
RS
12220
12221 topline = nlines + line;
12222
12223 /* Determine a new base line, if the old one is too close
12224 or too far away, or if we did not have one.
12225 "Too close" means it's plausible a scroll-down would
12226 go back past it. */
d39b6696 12227 if (startpos == BUF_BEGV (b))
aa6d10fa 12228 {
c2213350
KH
12229 XSETFASTINT (w->base_line_number, topline);
12230 XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
aa6d10fa
RS
12231 }
12232 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 12233 || linepos == BUF_BEGV (b))
aa6d10fa 12234 {
d39b6696 12235 int limit = BUF_BEGV (b);
12adba34 12236 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 12237 int position;
5d121aec 12238 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
12239
12240 if (startpos - distance > limit)
12adba34
RS
12241 {
12242 limit = startpos - distance;
12243 limit_byte = CHAR_TO_BYTE (limit);
12244 }
aa6d10fa 12245
12adba34
RS
12246 nlines = display_count_lines (startpos, startpos_byte,
12247 limit_byte,
12248 - (height * 2 + 30),
aa6d10fa
RS
12249 &position);
12250 /* If we couldn't find the lines we wanted within
5d121aec 12251 line_number_display_limit_width chars per line,
aa6d10fa 12252 give up on line numbers for this window. */
12adba34 12253 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
12254 {
12255 w->base_line_pos = w->buffer;
12256 w->base_line_number = Qnil;
766525bc 12257 goto no_value;
aa6d10fa
RS
12258 }
12259
c2213350 12260 XSETFASTINT (w->base_line_number, topline - nlines);
12adba34 12261 XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
aa6d10fa
RS
12262 }
12263
12264 /* Now count lines from the start pos to point. */
12adba34
RS
12265 nlines = display_count_lines (startpos, startpos_byte,
12266 PT_BYTE, PT, &junk);
aa6d10fa
RS
12267
12268 /* Record that we did display the line number. */
12269 line_number_displayed = 1;
12270
12271 /* Make the string to show. */
5f5c8ee5 12272 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 12273 return decode_mode_spec_buf;
766525bc
RS
12274 no_value:
12275 {
12276 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
12277 int pad = field_width - 2;
12278 while (pad-- > 0)
12279 *p++ = ' ';
12280 *p++ = '?';
12281 *p = '?';
766525bc
RS
12282 return decode_mode_spec_buf;
12283 }
aa6d10fa
RS
12284 }
12285 break;
12286
a2889657 12287 case 'm':
d39b6696 12288 obj = b->mode_name;
a2889657
JB
12289 break;
12290
12291 case 'n':
d39b6696 12292 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
12293 return " Narrow";
12294 break;
12295
a2889657
JB
12296 case 'p':
12297 {
12298 int pos = marker_position (w->start);
d39b6696 12299 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 12300
d39b6696 12301 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 12302 {
d39b6696 12303 if (pos <= BUF_BEGV (b))
a2889657
JB
12304 return "All";
12305 else
12306 return "Bottom";
12307 }
d39b6696 12308 else if (pos <= BUF_BEGV (b))
a2889657
JB
12309 return "Top";
12310 else
12311 {
3c7d31b9
RS
12312 if (total > 1000000)
12313 /* Do it differently for a large value, to avoid overflow. */
12314 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12315 else
12316 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
12317 /* We can't normally display a 3-digit number,
12318 so get us a 2-digit number that is close. */
12319 if (total == 100)
12320 total = 99;
12321 sprintf (decode_mode_spec_buf, "%2d%%", total);
12322 return decode_mode_spec_buf;
12323 }
12324 }
12325
8ffcb79f
RS
12326 /* Display percentage of size above the bottom of the screen. */
12327 case 'P':
12328 {
12329 int toppos = marker_position (w->start);
d39b6696
KH
12330 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
12331 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 12332
d39b6696 12333 if (botpos >= BUF_ZV (b))
8ffcb79f 12334 {
d39b6696 12335 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12336 return "All";
12337 else
12338 return "Bottom";
12339 }
12340 else
12341 {
3c7d31b9
RS
12342 if (total > 1000000)
12343 /* Do it differently for a large value, to avoid overflow. */
12344 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
12345 else
12346 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
12347 /* We can't normally display a 3-digit number,
12348 so get us a 2-digit number that is close. */
12349 if (total == 100)
12350 total = 99;
d39b6696 12351 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
12352 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
12353 else
12354 sprintf (decode_mode_spec_buf, "%2d%%", total);
12355 return decode_mode_spec_buf;
12356 }
12357 }
12358
1af9f229
RS
12359 case 's':
12360 /* status of process */
12361 obj = Fget_buffer_process (w->buffer);
12362 if (NILP (obj))
12363 return "no process";
12364#ifdef subprocesses
12365 obj = Fsymbol_name (Fprocess_status (obj));
12366#endif
12367 break;
d39b6696 12368
1af9f229
RS
12369 case 't': /* indicate TEXT or BINARY */
12370#ifdef MODE_LINE_BINARY_TEXT
12371 return MODE_LINE_BINARY_TEXT (b);
12372#else
12373 return "T";
12374#endif
1c9241f5
KH
12375
12376 case 'z':
12377 /* coding-system (not including end-of-line format) */
12378 case 'Z':
12379 /* coding-system (including end-of-line type) */
12380 {
12381 int eol_flag = (c == 'Z');
539b4d41 12382 char *p = decode_mode_spec_buf;
1c9241f5 12383
d30e754b 12384 if (! FRAME_WINDOW_P (f))
1c9241f5 12385 {
11c52c4f
RS
12386 /* No need to mention EOL here--the terminal never needs
12387 to do EOL conversion. */
12388 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
12389 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 12390 }
f13c925f 12391 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 12392 p, eol_flag);
f13c925f 12393
11c52c4f 12394#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
12395#ifdef subprocesses
12396 obj = Fget_buffer_process (Fcurrent_buffer ());
12397 if (PROCESSP (obj))
12398 {
12399 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
12400 p, eol_flag);
12401 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
12402 p, eol_flag);
12403 }
12404#endif /* subprocesses */
11c52c4f 12405#endif /* 0 */
1c9241f5
KH
12406 *p = 0;
12407 return decode_mode_spec_buf;
12408 }
a2889657 12409 }
d39b6696 12410
e24c997d 12411 if (STRINGP (obj))
a2889657
JB
12412 return (char *) XSTRING (obj)->data;
12413 else
12414 return "";
12415}
5f5c8ee5
GM
12416
12417
12adba34
RS
12418/* Count up to COUNT lines starting from START / START_BYTE.
12419 But don't go beyond LIMIT_BYTE.
12420 Return the number of lines thus found (always nonnegative).
59b49f63 12421
12adba34 12422 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
12423
12424static int
12adba34
RS
12425display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
12426 int start, start_byte, limit_byte, count;
12427 int *byte_pos_ptr;
59b49f63 12428{
59b49f63
RS
12429 register unsigned char *cursor;
12430 unsigned char *base;
12431
12432 register int ceiling;
12433 register unsigned char *ceiling_addr;
12adba34 12434 int orig_count = count;
59b49f63
RS
12435
12436 /* If we are not in selective display mode,
12437 check only for newlines. */
12adba34
RS
12438 int selective_display = (!NILP (current_buffer->selective_display)
12439 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
12440
12441 if (count > 0)
12adba34
RS
12442 {
12443 while (start_byte < limit_byte)
12444 {
12445 ceiling = BUFFER_CEILING_OF (start_byte);
12446 ceiling = min (limit_byte - 1, ceiling);
12447 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
12448 base = (cursor = BYTE_POS_ADDR (start_byte));
12449 while (1)
12450 {
12451 if (selective_display)
12452 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
12453 ;
12454 else
12455 while (*cursor != '\n' && ++cursor != ceiling_addr)
12456 ;
12457
12458 if (cursor != ceiling_addr)
12459 {
12460 if (--count == 0)
12461 {
12462 start_byte += cursor - base + 1;
12463 *byte_pos_ptr = start_byte;
12464 return orig_count;
12465 }
12466 else
12467 if (++cursor == ceiling_addr)
12468 break;
12469 }
12470 else
12471 break;
12472 }
12473 start_byte += cursor - base;
12474 }
12475 }
59b49f63
RS
12476 else
12477 {
12adba34
RS
12478 while (start_byte > limit_byte)
12479 {
12480 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
12481 ceiling = max (limit_byte, ceiling);
12482 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
12483 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
12484 while (1)
12485 {
12adba34
RS
12486 if (selective_display)
12487 while (--cursor != ceiling_addr
12488 && *cursor != '\n' && *cursor != 015)
12489 ;
12490 else
12491 while (--cursor != ceiling_addr && *cursor != '\n')
12492 ;
12493
59b49f63
RS
12494 if (cursor != ceiling_addr)
12495 {
12496 if (++count == 0)
12497 {
12adba34
RS
12498 start_byte += cursor - base + 1;
12499 *byte_pos_ptr = start_byte;
12500 /* When scanning backwards, we should
12501 not count the newline posterior to which we stop. */
12502 return - orig_count - 1;
59b49f63
RS
12503 }
12504 }
12505 else
12506 break;
12507 }
12adba34
RS
12508 /* Here we add 1 to compensate for the last decrement
12509 of CURSOR, which took it past the valid range. */
12510 start_byte += cursor - base + 1;
59b49f63
RS
12511 }
12512 }
12513
12adba34 12514 *byte_pos_ptr = limit_byte;
aa6d10fa 12515
12adba34
RS
12516 if (count < 0)
12517 return - orig_count + count;
12518 return orig_count - count;
aa6d10fa 12519
12adba34 12520}
a2889657 12521
a2889657 12522
5f5c8ee5
GM
12523\f
12524/***********************************************************************
12525 Displaying strings
12526 ***********************************************************************/
278feba9 12527
5f5c8ee5 12528/* Display a NUL-terminated string, starting with index START.
a3788d53 12529
5f5c8ee5
GM
12530 If STRING is non-null, display that C string. Otherwise, the Lisp
12531 string LISP_STRING is displayed.
a2889657 12532
5f5c8ee5
GM
12533 If FACE_STRING is not nil, FACE_STRING_POS is a position in
12534 FACE_STRING. Display STRING or LISP_STRING with the face at
12535 FACE_STRING_POS in FACE_STRING:
a2889657 12536
5f5c8ee5
GM
12537 Display the string in the environment given by IT, but use the
12538 standard display table, temporarily.
a3788d53 12539
5f5c8ee5
GM
12540 FIELD_WIDTH is the minimum number of output glyphs to produce.
12541 If STRING has fewer characters than FIELD_WIDTH, pad to the right
12542 with spaces. If STRING has more characters, more than FIELD_WIDTH
12543 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
12544
12545 PRECISION is the maximum number of characters to output from
12546 STRING. PRECISION < 0 means don't truncate the string.
a2889657 12547
5f5c8ee5 12548 This is roughly equivalent to printf format specifiers:
a2889657 12549
5f5c8ee5
GM
12550 FIELD_WIDTH PRECISION PRINTF
12551 ----------------------------------------
12552 -1 -1 %s
12553 -1 10 %.10s
12554 10 -1 %10s
12555 20 10 %20.10s
a2889657 12556
5f5c8ee5
GM
12557 MULTIBYTE zero means do not display multibyte chars, > 0 means do
12558 display them, and < 0 means obey the current buffer's value of
12559 enable_multibyte_characters.
278feba9 12560
5f5c8ee5 12561 Value is the number of glyphs produced. */
b1d1124b 12562
5f5c8ee5
GM
12563static int
12564display_string (string, lisp_string, face_string, face_string_pos,
12565 start, it, field_width, precision, max_x, multibyte)
12566 unsigned char *string;
12567 Lisp_Object lisp_string;
68c45bf0
PE
12568 Lisp_Object face_string;
12569 int face_string_pos;
5f5c8ee5
GM
12570 int start;
12571 struct it *it;
12572 int field_width, precision, max_x;
12573 int multibyte;
12574{
12575 int hpos_at_start = it->hpos;
12576 int saved_face_id = it->face_id;
12577 struct glyph_row *row = it->glyph_row;
12578
12579 /* Initialize the iterator IT for iteration over STRING beginning
12580 with index START. We assume that IT may be modified here (which
12581 means that display_line has to do something when displaying a
12582 mini-buffer prompt, which it does). */
12583 reseat_to_string (it, string, lisp_string, start,
12584 precision, field_width, multibyte);
12585
12586 /* If displaying STRING, set up the face of the iterator
12587 from LISP_STRING, if that's given. */
12588 if (STRINGP (face_string))
12589 {
12590 int endptr;
12591 struct face *face;
12592
12593 it->face_id
12594 = face_at_string_position (it->w, face_string, face_string_pos,
12595 0, it->region_beg_charpos,
12596 it->region_end_charpos,
12597 &endptr, it->base_face_id);
12598 face = FACE_FROM_ID (it->f, it->face_id);
12599 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 12600 }
a2889657 12601
5f5c8ee5
GM
12602 /* Set max_x to the maximum allowed X position. Don't let it go
12603 beyond the right edge of the window. */
12604 if (max_x <= 0)
12605 max_x = it->last_visible_x;
12606 else
12607 max_x = min (max_x, it->last_visible_x);
efc63ef0 12608
5f5c8ee5
GM
12609 /* Skip over display elements that are not visible. because IT->w is
12610 hscrolled. */
12611 if (it->current_x < it->first_visible_x)
12612 move_it_in_display_line_to (it, 100000, it->first_visible_x,
12613 MOVE_TO_POS | MOVE_TO_X);
a2889657 12614
5f5c8ee5
GM
12615 row->ascent = it->max_ascent;
12616 row->height = it->max_ascent + it->max_descent;
312246d1
GM
12617 row->phys_ascent = it->max_phys_ascent;
12618 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 12619
5f5c8ee5
GM
12620 /* This condition is for the case that we are called with current_x
12621 past last_visible_x. */
12622 while (it->current_x < max_x)
a2889657 12623 {
5f5c8ee5 12624 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 12625
5f5c8ee5
GM
12626 /* Get the next display element. */
12627 if (!get_next_display_element (it))
90adcf20 12628 break;
1c9241f5 12629
5f5c8ee5
GM
12630 /* Produce glyphs. */
12631 x_before = it->current_x;
12632 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
12633 PRODUCE_GLYPHS (it);
90adcf20 12634
5f5c8ee5
GM
12635 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
12636 i = 0;
12637 x = x_before;
12638 while (i < nglyphs)
a2889657 12639 {
5f5c8ee5
GM
12640 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
12641
12642 if (!it->truncate_lines_p
12643 && x + glyph->pixel_width > max_x)
12644 {
12645 /* End of continued line or max_x reached. */
12646 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
12647 it->current_x = x;
12648 break;
12649 }
12650 else if (x + glyph->pixel_width > it->first_visible_x)
12651 {
12652 /* Glyph is at least partially visible. */
12653 ++it->hpos;
12654 if (x < it->first_visible_x)
12655 it->glyph_row->x = x - it->first_visible_x;
12656 }
12657 else
a2889657 12658 {
5f5c8ee5
GM
12659 /* Glyph is off the left margin of the display area.
12660 Should not happen. */
12661 abort ();
a2889657 12662 }
5f5c8ee5
GM
12663
12664 row->ascent = max (row->ascent, it->max_ascent);
12665 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
12666 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
12667 row->phys_height = max (row->phys_height,
12668 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
12669 x += glyph->pixel_width;
12670 ++i;
a2889657 12671 }
5f5c8ee5
GM
12672
12673 /* Stop if max_x reached. */
12674 if (i < nglyphs)
12675 break;
12676
12677 /* Stop at line ends. */
12678 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 12679 {
5f5c8ee5
GM
12680 it->continuation_lines_width = 0;
12681 break;
a2889657 12682 }
1c9241f5 12683
5f5c8ee5 12684 set_iterator_to_next (it);
a688bb24 12685
5f5c8ee5
GM
12686 /* Stop if truncating at the right edge. */
12687 if (it->truncate_lines_p
12688 && it->current_x >= it->last_visible_x)
12689 {
12690 /* Add truncation mark, but don't do it if the line is
12691 truncated at a padding space. */
12692 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 12693 {
5f5c8ee5
GM
12694 if (!FRAME_WINDOW_P (it->f))
12695 produce_special_glyphs (it, IT_TRUNCATION);
12696 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 12697 }
5f5c8ee5 12698 break;
1c9241f5 12699 }
a2889657
JB
12700 }
12701
5f5c8ee5
GM
12702 /* Maybe insert a truncation at the left. */
12703 if (it->first_visible_x
12704 && IT_CHARPOS (*it) > 0)
a2889657 12705 {
5f5c8ee5
GM
12706 if (!FRAME_WINDOW_P (it->f))
12707 insert_left_trunc_glyphs (it);
12708 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
12709 }
12710
5f5c8ee5
GM
12711 it->face_id = saved_face_id;
12712
12713 /* Value is number of columns displayed. */
12714 return it->hpos - hpos_at_start;
12715}
a2889657 12716
a2889657 12717
a2889657 12718\f
5f5c8ee5
GM
12719/* This is like a combination of memq and assq. Return 1 if PROPVAL
12720 appears as an element of LIST or as the car of an element of LIST.
12721 If PROPVAL is a list, compare each element against LIST in that
12722 way, and return 1 if any element of PROPVAL is found in LIST.
12723 Otherwise return 0. This function cannot quit. */
642eefc6
RS
12724
12725int
12726invisible_p (propval, list)
12727 register Lisp_Object propval;
12728 Lisp_Object list;
12729{
af460d46 12730 register Lisp_Object tail, proptail;
9472f927 12731 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
12732 {
12733 register Lisp_Object tem;
9472f927 12734 tem = XCAR (tail);
642eefc6
RS
12735 if (EQ (propval, tem))
12736 return 1;
9472f927 12737 if (CONSP (tem) && EQ (propval, XCAR (tem)))
642eefc6
RS
12738 return 1;
12739 }
af460d46
RS
12740 if (CONSP (propval))
12741 for (proptail = propval; CONSP (proptail);
9472f927 12742 proptail = XCDR (proptail))
af460d46
RS
12743 {
12744 Lisp_Object propelt;
9472f927
GM
12745 propelt = XCAR (proptail);
12746 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
12747 {
12748 register Lisp_Object tem;
9472f927 12749 tem = XCAR (tail);
af460d46
RS
12750 if (EQ (propelt, tem))
12751 return 1;
9472f927 12752 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
af460d46
RS
12753 return 1;
12754 }
12755 }
642eefc6
RS
12756 return 0;
12757}
12758
5f5c8ee5
GM
12759
12760/* Return 1 if PROPVAL appears as the car of an element of LIST and
12761 the cdr of that element is non-nil. If PROPVAL is a list, check
12762 each element of PROPVAL in that way, and the first time some
12763 element is found, return 1 if the cdr of that element is non-nil.
12764 Otherwise return 0. This function cannot quit. */
642eefc6
RS
12765
12766int
12767invisible_ellipsis_p (propval, list)
12768 register Lisp_Object propval;
12769 Lisp_Object list;
12770{
af460d46 12771 register Lisp_Object tail, proptail;
9472f927
GM
12772
12773 for (tail = list; CONSP (tail); tail = XCDR (tail))
642eefc6
RS
12774 {
12775 register Lisp_Object tem;
9472f927
GM
12776 tem = XCAR (tail);
12777 if (CONSP (tem) && EQ (propval, XCAR (tem)))
12778 return ! NILP (XCDR (tem));
642eefc6 12779 }
9472f927 12780
af460d46 12781 if (CONSP (propval))
9472f927 12782 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
af460d46
RS
12783 {
12784 Lisp_Object propelt;
9472f927
GM
12785 propelt = XCAR (proptail);
12786 for (tail = list; CONSP (tail); tail = XCDR (tail))
af460d46
RS
12787 {
12788 register Lisp_Object tem;
9472f927
GM
12789 tem = XCAR (tail);
12790 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
12791 return ! NILP (XCDR (tem));
af460d46
RS
12792 }
12793 }
9472f927 12794
642eefc6
RS
12795 return 0;
12796}
5f5c8ee5
GM
12797
12798
642eefc6 12799\f
5f5c8ee5
GM
12800/***********************************************************************
12801 Initialization
12802 ***********************************************************************/
12803
a2889657
JB
12804void
12805syms_of_xdisp ()
12806{
c6e89d6c
GM
12807 Vwith_echo_area_save_vector = Qnil;
12808 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 12809
c6e89d6c
GM
12810 Vmessage_stack = Qnil;
12811 staticpro (&Vmessage_stack);
12812
735c094c 12813 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 12814 staticpro (&Qinhibit_redisplay);
735c094c 12815
5f5c8ee5
GM
12816#if GLYPH_DEBUG
12817 defsubr (&Sdump_glyph_matrix);
12818 defsubr (&Sdump_glyph_row);
e037b9ec 12819 defsubr (&Sdump_tool_bar_row);
5f5c8ee5 12820 defsubr (&Strace_redisplay_toggle);
bf9249e3 12821 defsubr (&Strace_to_stderr);
5f5c8ee5
GM
12822#endif
12823
cf074754
RS
12824 staticpro (&Qmenu_bar_update_hook);
12825 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
12826
d46fb96a 12827 staticpro (&Qoverriding_terminal_local_map);
7079aefa 12828 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 12829
399164b4
KH
12830 staticpro (&Qoverriding_local_map);
12831 Qoverriding_local_map = intern ("overriding-local-map");
12832
75c43375
RS
12833 staticpro (&Qwindow_scroll_functions);
12834 Qwindow_scroll_functions = intern ("window-scroll-functions");
12835
e0bfbde6
RS
12836 staticpro (&Qredisplay_end_trigger_functions);
12837 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
5f5c8ee5 12838
2e54982e
RS
12839 staticpro (&Qinhibit_point_motion_hooks);
12840 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
12841
5f5c8ee5 12842 Qdisplay = intern ("display");
f3751a65 12843 staticpro (&Qdisplay);
5f5c8ee5
GM
12844 Qspace_width = intern ("space-width");
12845 staticpro (&Qspace_width);
5f5c8ee5
GM
12846 Qraise = intern ("raise");
12847 staticpro (&Qraise);
12848 Qspace = intern ("space");
12849 staticpro (&Qspace);
f3751a65
GM
12850 Qmargin = intern ("margin");
12851 staticpro (&Qmargin);
5f5c8ee5 12852 Qleft_margin = intern ("left-margin");
f3751a65 12853 staticpro (&Qleft_margin);
5f5c8ee5 12854 Qright_margin = intern ("right-margin");
f3751a65 12855 staticpro (&Qright_margin);
5f5c8ee5
GM
12856 Qalign_to = intern ("align-to");
12857 staticpro (&Qalign_to);
12858 QCalign_to = intern (":align-to");
12859 staticpro (&QCalign_to);
5f5c8ee5
GM
12860 Qrelative_width = intern ("relative-width");
12861 staticpro (&Qrelative_width);
12862 QCrelative_width = intern (":relative-width");
12863 staticpro (&QCrelative_width);
12864 QCrelative_height = intern (":relative-height");
12865 staticpro (&QCrelative_height);
12866 QCeval = intern (":eval");
12867 staticpro (&QCeval);
d3acf96b 12868 Qwhen = intern ("when");
f3751a65 12869 staticpro (&Qwhen);
886bd6f2
GM
12870 QCfile = intern (":file");
12871 staticpro (&QCfile);
5f5c8ee5
GM
12872 Qfontified = intern ("fontified");
12873 staticpro (&Qfontified);
12874 Qfontification_functions = intern ("fontification-functions");
12875 staticpro (&Qfontification_functions);
5f5c8ee5
GM
12876 Qtrailing_whitespace = intern ("trailing-whitespace");
12877 staticpro (&Qtrailing_whitespace);
12878 Qimage = intern ("image");
12879 staticpro (&Qimage);
12880
a2889657
JB
12881 last_arrow_position = Qnil;
12882 last_arrow_string = Qnil;
f3751a65
GM
12883 staticpro (&last_arrow_position);
12884 staticpro (&last_arrow_string);
c6e89d6c
GM
12885
12886 echo_buffer[0] = echo_buffer[1] = Qnil;
12887 staticpro (&echo_buffer[0]);
12888 staticpro (&echo_buffer[1]);
12889
12890 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
12891 staticpro (&echo_area_buffer[0]);
12892 staticpro (&echo_area_buffer[1]);
a2889657 12893
8f897821
GM
12894 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
12895 "Non-nil means highlight trailing whitespace.\n\
12896The face used for trailing whitespace is `trailing-whitespace'.");
12897 Vshow_trailing_whitespace = Qnil;
12898
735c094c
KH
12899 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
12900 "Non-nil means don't actually do any redisplay.\n\
12901This is used for internal purposes.");
12902 Vinhibit_redisplay = Qnil;
12903
a2889657 12904 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
8c45d522 12905 "String (or mode line construct) included (normally) in `mode-line-format'.");
a2889657
JB
12906 Vglobal_mode_string = Qnil;
12907
12908 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
12909 "Marker for where to display an arrow on top of the buffer text.\n\
12910This must be the beginning of a line in order to work.\n\
12911See also `overlay-arrow-string'.");
12912 Voverlay_arrow_position = Qnil;
12913
12914 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
12915 "String to display as an arrow. See also `overlay-arrow-position'.");
12916 Voverlay_arrow_string = Qnil;
12917
12918 DEFVAR_INT ("scroll-step", &scroll_step,
12919 "*The number of lines to try scrolling a window by when point moves out.\n\
44fa5b1e
JB
12920If that fails to bring point back on frame, point is centered instead.\n\
12921If this is zero, point is always centered after it moves off frame.");
a2889657 12922
0789adb2 12923 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
090f7baa
GM
12924 "*Scroll up to this many lines, to bring point back on screen.\n\
12925A value of zero means to scroll the text to center point vertically\n\
12926in the window.");
0789adb2
RS
12927 scroll_conservatively = 0;
12928
9afd2168
RS
12929 DEFVAR_INT ("scroll-margin", &scroll_margin,
12930 "*Number of lines of margin at the top and bottom of a window.\n\
12931Recenter the window whenever point gets within this many lines\n\
12932of the top or bottom of the window.");
12933 scroll_margin = 0;
12934
5f5c8ee5 12935#if GLYPH_DEBUG
a2889657 12936 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
5f5c8ee5 12937#endif
a2889657
JB
12938
12939 DEFVAR_BOOL ("truncate-partial-width-windows",
12940 &truncate_partial_width_windows,
44fa5b1e 12941 "*Non-nil means truncate lines in all windows less than full frame wide.");
a2889657
JB
12942 truncate_partial_width_windows = 1;
12943
12944 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
12945 "*Non-nil means use inverse video for the mode line.");
12946 mode_line_inverse_video = 1;
aa6d10fa
RS
12947
12948 DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
5f5c8ee5 12949 "*Maximum buffer size for which line number should be displayed.\n\
db4f2bfa 12950If the buffer is bigger than this, the line number does not appear\n\
9f027393 12951in the mode line.");
aa6d10fa 12952 line_number_display_limit = 1000000;
fba9ce76 12953
5d121aec
KH
12954 DEFVAR_INT ("line-number-display-limit-width", &line_number_display_limit_width,
12955 "*Maximum line width (in characters) for line number display.\n\
12956If the average length of the lines near point is bigger than this, then the\n\
12957line number may be omitted from the mode line.");
12958 line_number_display_limit_width = 200;
12959
fba9ce76
RS
12960 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
12961 "*Non-nil means highlight region even in nonselected windows.");
293a54ce 12962 highlight_nonselected_windows = 0;
d39b6696
KH
12963
12964 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
3450d04c
KH
12965 "Non-nil if more than one frame is visible on this display.\n\
12966Minibuffer-only frames don't count, but iconified frames do.\n\
4c2eb242
RS
12967This variable is not guaranteed to be accurate except while processing\n\
12968`frame-title-format' and `icon-title-format'.");
d39b6696
KH
12969
12970 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
5f5c8ee5 12971 "Template for displaying the title bar of visible frames.\n\
d39b6696
KH
12972\(Assuming the window manager supports this feature.)\n\
12973This variable has the same structure as `mode-line-format' (which see),\n\
12974and is used only on frames for which no explicit name has been set\n\
12975\(see `modify-frame-parameters').");
12976 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
5f5c8ee5 12977 "Template for displaying the title bar of an iconified frame.\n\
d39b6696
KH
12978\(Assuming the window manager supports this feature.)\n\
12979This variable has the same structure as `mode-line-format' (which see),\n\
12980and is used only on frames for which no explicit name has been set\n\
12981\(see `modify-frame-parameters').");
12982 Vicon_title_format
12983 = Vframe_title_format
12984 = Fcons (intern ("multiple-frames"),
12985 Fcons (build_string ("%b"),
12986 Fcons (Fcons (build_string (""),
12987 Fcons (intern ("invocation-name"),
12988 Fcons (build_string ("@"),
12989 Fcons (intern ("system-name"),
12990 Qnil)))),
12991 Qnil)));
5992c4f7
KH
12992
12993 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
12994 "Maximum number of lines to keep in the message log buffer.\n\
12995If nil, disable message logging. If t, log messages but don't truncate\n\
12996the buffer when it becomes large.");
12997 XSETFASTINT (Vmessage_log_max, 50);
08b610e4
RS
12998
12999 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
13000 "Functions called before redisplay, if window sizes have changed.\n\
13001The value should be a list of functions that take one argument.\n\
13002Just before redisplay, for each frame, if any of its windows have changed\n\
13003size since the last redisplay, or have been split or deleted,\n\
13004all the functions in the list are called, with the frame as argument.");
13005 Vwindow_size_change_functions = Qnil;
75c43375
RS
13006
13007 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
5f5c8ee5 13008 "List of Functions to call before redisplaying a window with scrolling.\n\
75c43375 13009Each function is called with two arguments, the window\n\
8d9583b0
RS
13010and its new display-start position. Note that the value of `window-end'\n\
13011is not valid when these functions are called.");
75c43375 13012 Vwindow_scroll_functions = Qnil;
5f5c8ee5 13013
e037b9ec
GM
13014 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
13015 "*Non-nil means automatically resize tool-bars.\n\
13016This increases a tool-bar's height if not all tool-bar items are visible.\n\
13017It decreases a tool-bar's height when it would display blank lines\n\
5f5c8ee5 13018otherwise.");
e037b9ec 13019 auto_resize_tool_bars_p = 1;
5f5c8ee5 13020
e037b9ec
GM
13021 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
13022 "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
13023 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 13024
e037b9ec
GM
13025 DEFVAR_INT ("tool-bar-button-margin", &tool_bar_button_margin,
13026 "*Margin around tool-bar buttons in pixels.");
13027 tool_bar_button_margin = 1;
5f5c8ee5 13028
e037b9ec
GM
13029 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
13030 "Relief thickness of tool-bar buttons.");
13031 tool_bar_button_relief = 3;
5f5c8ee5
GM
13032
13033 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
13034 "List of functions to call to fontify regions of text.\n\
13035Each function is called with one argument POS. Functions must\n\
13036fontify a region starting at POS in the current buffer, and give\n\
13037fontified regions the property `fontified'.\n\
13038This variable automatically becomes buffer-local when set.");
13039 Vfontification_functions = Qnil;
13040 Fmake_local_variable (Qfontification_functions);
7bbe686f
AI
13041
13042 DEFVAR_BOOL ("unibyte-display-via-language-environment",
5f5c8ee5
GM
13043 &unibyte_display_via_language_environment,
13044 "*Non-nil means display unibyte text according to language environment.\n\
7bbe686f
AI
13045Specifically this means that unibyte non-ASCII characters\n\
13046are displayed by converting them to the equivalent multibyte characters\n\
13047according to the current language environment. As a result, they are\n\
13048displayed according to the current fontset.");
13049 unibyte_display_via_language_environment = 0;
c6e89d6c
GM
13050
13051 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
13052 "*Maximum height for resizing mini-windows.\n\
13053If a float, it specifies a fraction of the mini-window frame's height.\n\
97cafc0f
GM
13054If an integer, it specifies a number of lines.\n\
13055If nil, don't resize.");
c6e89d6c 13056 Vmax_mini_window_height = make_float (0.25);
d6d26ed3
GM
13057
13058 DEFVAR_BOOL ("cursor-in-non-selected-windows",
13059 &cursor_in_non_selected_windows,
13060 "*Non-nil means display a hollow cursor in non-selected windows.\n\
13061Nil means don't display a cursor there.");
13062 cursor_in_non_selected_windows = 1;
a2889657
JB
13063}
13064
5f5c8ee5
GM
13065
13066/* Initialize this module when Emacs starts. */
13067
dfcf069d 13068void
a2889657
JB
13069init_xdisp ()
13070{
13071 Lisp_Object root_window;
5f5c8ee5 13072 struct window *mini_w;
a2889657 13073
5f5c8ee5 13074 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
13075
13076 mini_w = XWINDOW (minibuf_window);
11e82b76 13077 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 13078
a2889657
JB
13079 if (!noninteractive)
13080 {
5f5c8ee5
GM
13081 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
13082 int i;
13083
13084 XSETFASTINT (XWINDOW (root_window)->top, FRAME_TOP_MARGIN (f));
12c226c5 13085 set_window_height (root_window,
5f5c8ee5 13086 FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 13087 0);
c2213350 13088 XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
a2889657
JB
13089 set_window_height (minibuf_window, 1, 0);
13090
c2213350
KH
13091 XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
13092 XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
5f5c8ee5
GM
13093
13094 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
13095 scratch_glyph_row.glyphs[TEXT_AREA + 1]
13096 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
13097
13098 /* The default ellipsis glyphs `...'. */
13099 for (i = 0; i < 3; ++i)
13100 XSETFASTINT (default_invis_vector[i], '.');
a2889657 13101 }
5f5c8ee5
GM
13102
13103#ifdef HAVE_WINDOW_SYSTEM
13104 {
13105 /* Allocate the buffer for frame titles. */
13106 int size = 100;
13107 frame_title_buf = (char *) xmalloc (size);
13108 frame_title_buf_end = frame_title_buf + size;
13109 frame_title_ptr = NULL;
13110 }
13111#endif /* HAVE_WINDOW_SYSTEM */
a2889657 13112}
5f5c8ee5
GM
13113
13114