Add arch taglines
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
1a89be1e 2 Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03
5f5c8ee5 3 Free Software Foundation, Inc.
a2889657
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
b1d1124b 9the Free Software Foundation; either version 2, or (at your option)
a2889657
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
a2889657 21
5f5c8ee5
GM
22/* New redisplay written by Gerd Moellmann <gerd@gnu.org>.
23
24 Redisplay.
25
26 Emacs separates the task of updating the display from code
27 modifying global state, e.g. buffer text. This way functions
28 operating on buffers don't also have to be concerned with updating
29 the display.
30
31 Updating the display is triggered by the Lisp interpreter when it
32 decides it's time to do it. This is done either automatically for
33 you as part of the interpreter's command loop or as the result of
34 calling Lisp functions like `sit-for'. The C function `redisplay'
35 in xdisp.c is the only entry into the inner redisplay code. (Or,
48400103 36 let's say almost---see the description of direct update
4b41cebb 37 operations, below.)
5f5c8ee5
GM
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)
2311178e 50 direct_output_for_insert,
5f5c8ee5
GM
51 direct_forward_char (dispnew.c)
52 +---------------------------------+
53 | |
54 | V
82a7ab23 55 +--------------+ redisplay +----------------+
5f5c8ee5
GM
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
959bc044 67 What does redisplay do? Obviously, it has to figure out somehow what
5f5c8ee5
GM
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
48400103 91 You will find a lot of redisplay optimizations when you start
5f5c8ee5
GM
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
2311178e 109
5f5c8ee5
GM
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
959bc044 123 interface functions taking an iterator structure (struct it)
5f5c8ee5
GM
124 argument.
125
48400103 126 Iteration over things to be displayed is then simple. It is
1178ddde
GM
127 started by initializing an iterator with a call to init_iterator.
128 Calls to get_next_display_element fill the iterator structure with
129 relevant information about the next thing to display. Calls to
5f5c8ee5
GM
130 set_iterator_to_next move the iterator to the next thing.
131
132 Besides this, an iterator also contains information about the
133 display environment in which glyphs for display elements are to be
134 produced. It has fields for the width and height of the display,
135 the information whether long lines are truncated or continued, a
136 current X and Y position, and lots of other stuff you can better
137 see in dispextern.h.
138
139 Glyphs in a desired matrix are normally constructed in a loop
140 calling get_next_display_element and then produce_glyphs. The call
141 to produce_glyphs will fill the iterator structure with pixel
142 information about the element being displayed and at the same time
143 produce glyphs for it. If the display element fits on the line
144 being displayed, set_iterator_to_next is called next, otherwise the
145 glyphs produced are discarded.
146
147
148 Frame matrices.
149
150 That just couldn't be all, could it? What about terminal types not
151 supporting operations on sub-windows of the screen? To update the
152 display on such a terminal, window-based glyph matrices are not
153 well suited. To be able to reuse part of the display (scrolling
154 lines up and down), we must instead have a view of the whole
155 screen. This is what `frame matrices' are for. They are a trick.
156
157 Frames on terminals like above have a glyph pool. Windows on such
158 a frame sub-allocate their glyph memory from their frame's glyph
159 pool. The frame itself is given its own glyph matrices. By
160 coincidence---or maybe something else---rows in window glyph
161 matrices are slices of corresponding rows in frame matrices. Thus
162 writing to window matrices implicitly updates a frame matrix which
163 provides us with the view of the whole screen that we originally
164 wanted to have without having to move many bytes around. To be
165 honest, there is a little bit more done, but not much more. If you
166 plan to extend that code, take a look at dispnew.c. The function
167 build_frame_matrix is a good starting point. */
a2889657 168
18160b98 169#include <config.h>
a2889657 170#include <stdio.h>
7ee72033 171
a2889657 172#include "lisp.h"
546a4f00 173#include "keyboard.h"
44fa5b1e 174#include "frame.h"
a2889657
JB
175#include "window.h"
176#include "termchar.h"
177#include "dispextern.h"
178#include "buffer.h"
1c9241f5 179#include "charset.h"
a2889657
JB
180#include "indent.h"
181#include "commands.h"
fa3c6b4d 182#include "keymap.h"
a2889657
JB
183#include "macros.h"
184#include "disptab.h"
30c566e4 185#include "termhooks.h"
b0a0fbda 186#include "intervals.h"
1c9241f5
KH
187#include "coding.h"
188#include "process.h"
dfcf069d 189#include "region-cache.h"
0ef75e87 190#include "fontset.h"
f9b3d256 191#include "blockinput.h"
dfcf069d 192
6d55d620 193#ifdef HAVE_X_WINDOWS
dfcf069d
AS
194#include "xterm.h"
195#endif
a75dfea0
AI
196#ifdef WINDOWSNT
197#include "w32term.h"
198#endif
e0f712ba 199#ifdef MAC_OS
1a578e9b 200#include "macterm.h"
365fa1b3
AC
201
202Cursor No_Cursor;
1a578e9b 203#endif
a2889657 204
1dabd0cf
KS
205#ifndef FRAME_X_OUTPUT
206#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
207#endif
208
5f5c8ee5
GM
209#define INFINITY 10000000
210
488dd4c4
JD
211#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
212 || defined (USE_GTK)
2e621225 213extern void set_frame_menubar P_ ((struct frame *f, int, int));
cd6dfed6 214extern int pending_menu_activation;
76412d64
RS
215#endif
216
a2889657
JB
217extern int interrupt_input;
218extern int command_loop_level;
219
b6436d4e 220extern int minibuffer_auto_raise;
b2b5455d 221extern Lisp_Object Vminibuffer_list;
b6436d4e 222
c4628384 223extern Lisp_Object Qface;
fec8f23e 224extern Lisp_Object Qmode_line, Qmode_line_inactive, Qheader_line;
c4628384 225
399164b4
KH
226extern Lisp_Object Voverriding_local_map;
227extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 228extern Lisp_Object Qmenu_item;
0b063c27 229extern Lisp_Object Qwhen;
fa3c6b4d 230extern Lisp_Object Qhelp_echo;
399164b4 231
d46fb96a 232Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 233Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 234Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 235Lisp_Object Qinhibit_point_motion_hooks;
0b063c27 236Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
5f5c8ee5 237Lisp_Object Qfontified;
6422c1d7 238Lisp_Object Qgrow_only;
869fb12c 239Lisp_Object Qinhibit_eval_during_redisplay;
b384d6f8 240Lisp_Object Qbuffer_position, Qposition, Qobject;
5f5c8ee5 241
cfe03a41
KS
242/* Cursor shapes */
243Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
244
c53a1624
RS
245Lisp_Object Qrisky_local_variable;
246
7033d6df
RS
247/* Holds the list (error). */
248Lisp_Object list_of_error;
249
5f5c8ee5
GM
250/* Functions called to fontify regions of text. */
251
252Lisp_Object Vfontification_functions;
253Lisp_Object Qfontification_functions;
254
fa3c6b4d
KS
255/* Non-zero means automatically select any window when the mouse
256 cursor moves into it. */
257int mouse_autoselect_window;
258
e037b9ec 259/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
260 over them. */
261
e037b9ec 262int auto_raise_tool_bar_buttons_p;
5f5c8ee5 263
e037b9ec 264/* Margin around tool bar buttons in pixels. */
5f5c8ee5 265
35a41507 266Lisp_Object Vtool_bar_button_margin;
5f5c8ee5 267
e037b9ec 268/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 269
31ade731 270EMACS_INT tool_bar_button_relief;
5f5c8ee5 271
e037b9ec 272/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
273 items are visible, and no blank lines remain. */
274
e037b9ec 275int auto_resize_tool_bars_p;
399164b4 276
fa3c6b4d
KS
277/* Non-zero means draw block and hollow cursor as wide as the glyph
278 under it. For example, if a block cursor is over a tab, it will be
279 drawn as wide as that tab on the display. */
280
281int x_stretch_cursor_p;
282
735c094c
KH
283/* Non-nil means don't actually do any redisplay. */
284
285Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
286
30a3f61c
GM
287/* Non-zero means Lisp evaluation during redisplay is inhibited. */
288
869fb12c 289int inhibit_eval_during_redisplay;
30a3f61c 290
5f5c8ee5
GM
291/* Names of text properties relevant for redisplay. */
292
a7e27ef7 293Lisp_Object Qdisplay, Qrelative_width, Qalign_to;
4b41cebb 294extern Lisp_Object Qface, Qinvisible, Qwidth;
5f5c8ee5
GM
295
296/* Symbols used in text property values. */
297
298Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
a7e27ef7 299Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
f3751a65 300Lisp_Object Qmargin;
a7e27ef7 301extern Lisp_Object Qheight;
133c764e 302extern Lisp_Object QCwidth, QCheight, QCascent;
5f5c8ee5 303
8f897821 304/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 305
8f897821 306Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5
GM
307
308/* Name of the face used to highlight trailing whitespace. */
309
310Lisp_Object Qtrailing_whitespace;
311
312/* The symbol `image' which is the car of the lists used to represent
313 images in Lisp. */
314
315Lisp_Object Qimage;
316
317/* Non-zero means print newline to stdout before next mini-buffer
318 message. */
a2889657
JB
319
320int noninteractive_need_newline;
321
5f5c8ee5 322/* Non-zero means print newline to message log before next message. */
f88eb0b6 323
3c6595e0 324static int message_log_need_newline;
f88eb0b6 325
b14bc55e
RS
326/* Three markers that message_dolog uses.
327 It could allocate them itself, but that causes trouble
328 in handling memory-full errors. */
329static Lisp_Object message_dolog_marker1;
330static Lisp_Object message_dolog_marker2;
331static Lisp_Object message_dolog_marker3;
5f5c8ee5
GM
332\f
333/* The buffer position of the first character appearing entirely or
334 partially on the line of the selected window which contains the
335 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
336 redisplay optimization in redisplay_internal. */
a2889657 337
5f5c8ee5 338static struct text_pos this_line_start_pos;
a2889657 339
5f5c8ee5
GM
340/* Number of characters past the end of the line above, including the
341 terminating newline. */
342
343static struct text_pos this_line_end_pos;
344
345/* The vertical positions and the height of this line. */
a2889657 346
a2889657 347static int this_line_vpos;
5f5c8ee5
GM
348static int this_line_y;
349static int this_line_pixel_height;
350
351/* X position at which this display line starts. Usually zero;
352 negative if first character is partially visible. */
353
354static int this_line_start_x;
a2889657 355
5f5c8ee5 356/* Buffer that this_line_.* variables are referring to. */
a2889657 357
a2889657
JB
358static struct buffer *this_line_buffer;
359
5f5c8ee5
GM
360/* Nonzero means truncate lines in all windows less wide than the
361 frame. */
a2889657 362
a2889657
JB
363int truncate_partial_width_windows;
364
7bbe686f 365/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 366
7bbe686f 367int unibyte_display_via_language_environment;
2311178e 368
5f5c8ee5
GM
369/* Nonzero means we have more than one non-mini-buffer-only frame.
370 Not guaranteed to be accurate except while parsing
371 frame-title-format. */
7bbe686f 372
d39b6696
KH
373int multiple_frames;
374
a2889657
JB
375Lisp_Object Vglobal_mode_string;
376
377/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 378
a2889657
JB
379Lisp_Object Voverlay_arrow_position;
380
5f5c8ee5
GM
381/* String to display for the arrow. Only used on terminal frames. */
382
a2889657
JB
383Lisp_Object Voverlay_arrow_string;
384
5f5c8ee5
GM
385/* Values of those variables at last redisplay. However, if
386 Voverlay_arrow_position is a marker, last_arrow_position is its
387 numerical position. */
388
d45de95b
RS
389static Lisp_Object last_arrow_position, last_arrow_string;
390
5f5c8ee5
GM
391/* Like mode-line-format, but for the title bar on a visible frame. */
392
d39b6696
KH
393Lisp_Object Vframe_title_format;
394
5f5c8ee5
GM
395/* Like mode-line-format, but for the title bar on an iconified frame. */
396
d39b6696
KH
397Lisp_Object Vicon_title_format;
398
08b610e4
RS
399/* List of functions to call when a window's size changes. These
400 functions get one arg, a frame on which one or more windows' sizes
401 have changed. */
5f5c8ee5 402
08b610e4
RS
403static Lisp_Object Vwindow_size_change_functions;
404
0bca8940 405Lisp_Object Qmenu_bar_update_hook, Vmenu_bar_update_hook;
cf074754 406
a2889657 407/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 408
5f5c8ee5 409static int overlay_arrow_seen;
ca26e1c8 410
fba9ce76 411/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 412
5f5c8ee5
GM
413int highlight_nonselected_windows;
414
415/* If cursor motion alone moves point off frame, try scrolling this
416 many lines up or down if that will bring it back. */
417
31ade731 418static EMACS_INT scroll_step;
a2889657 419
4b41cebb 420/* Nonzero means scroll just far enough to bring point back on the
5f5c8ee5
GM
421 screen, when appropriate. */
422
31ade731 423static EMACS_INT scroll_conservatively;
0789adb2 424
5f5c8ee5
GM
425/* Recenter the window whenever point gets within this many lines of
426 the top or bottom of the window. This value is translated into a
da8b7f4f
KS
427 pixel value by multiplying it with FRAME_LINE_HEIGHT, which means
428 that there is really a fixed pixel height scroll margin. */
5f5c8ee5 429
31ade731 430EMACS_INT scroll_margin;
9afd2168 431
5f5c8ee5
GM
432/* Number of windows showing the buffer of the selected window (or
433 another buffer with the same base buffer). keyboard.c refers to
434 this. */
a2889657 435
a2889657
JB
436int buffer_shared;
437
5f5c8ee5 438/* Vector containing glyphs for an ellipsis `...'. */
a2889657 439
5f5c8ee5 440static Lisp_Object default_invis_vector[3];
a2889657 441
1862a24e
MB
442/* Zero means display the mode-line/header-line/menu-bar in the default face
443 (this slightly odd definition is for compatibility with previous versions
444 of emacs), non-zero means display them using their respective faces.
445
446 This variable is deprecated. */
a2889657 447
a2889657
JB
448int mode_line_inverse_video;
449
5f5c8ee5
GM
450/* Prompt to display in front of the mini-buffer contents. */
451
8c5b6a0a 452Lisp_Object minibuf_prompt;
a2889657 453
5f5c8ee5
GM
454/* Width of current mini-buffer prompt. Only set after display_line
455 of the line that contains the prompt. */
456
a2889657 457int minibuf_prompt_width;
5f5c8ee5 458
5f5c8ee5
GM
459/* This is the window where the echo area message was displayed. It
460 is always a mini-buffer window, but it may not be the same window
461 currently active as a mini-buffer. */
462
73af359d
RS
463Lisp_Object echo_area_window;
464
c6e89d6c
GM
465/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
466 pushes the current message and the value of
467 message_enable_multibyte on the stack, the function restore_message
468 pops the stack and displays MESSAGE again. */
469
470Lisp_Object Vmessage_stack;
471
a3788d53
RS
472/* Nonzero means multibyte characters were enabled when the echo area
473 message was specified. */
5f5c8ee5 474
a3788d53
RS
475int message_enable_multibyte;
476
4b41cebb 477/* Nonzero if we should redraw the mode lines on the next redisplay. */
5f5c8ee5 478
a2889657
JB
479int update_mode_lines;
480
5f5c8ee5 481/* Nonzero if window sizes or contents have changed since last
4b41cebb 482 redisplay that finished. */
5f5c8ee5 483
a2889657
JB
484int windows_or_buffers_changed;
485
5fb96e96
RS
486/* Nonzero means a frame's cursor type has been changed. */
487
488int cursor_type_changed;
489
5f5c8ee5
GM
490/* Nonzero after display_mode_line if %l was used and it displayed a
491 line number. */
492
aa6d10fa
RS
493int line_number_displayed;
494
495/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 496
090703f4 497Lisp_Object Vline_number_display_limit;
5992c4f7 498
4b41cebb 499/* Line width to consider when repositioning for line number display. */
5d121aec 500
31ade731 501static EMACS_INT line_number_display_limit_width;
5d121aec 502
5f5c8ee5
GM
503/* Number of lines to keep in the message log buffer. t means
504 infinite. nil means don't log at all. */
505
5992c4f7 506Lisp_Object Vmessage_log_max;
d45de95b 507
6a94510a
GM
508/* The name of the *Messages* buffer, a string. */
509
510static Lisp_Object Vmessages_buffer_name;
511
c6e89d6c
GM
512/* Current, index 0, and last displayed echo area message. Either
513 buffers from echo_buffers, or nil to indicate no message. */
514
515Lisp_Object echo_area_buffer[2];
516
517/* The buffers referenced from echo_area_buffer. */
518
519static Lisp_Object echo_buffer[2];
520
521/* A vector saved used in with_area_buffer to reduce consing. */
522
523static Lisp_Object Vwith_echo_area_save_vector;
524
525/* Non-zero means display_echo_area should display the last echo area
526 message again. Set by redisplay_preserve_echo_area. */
527
528static int display_last_displayed_message_p;
529
530/* Nonzero if echo area is being used by print; zero if being used by
531 message. */
532
533int message_buf_print;
534
e1477f43
GM
535/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
536
537Lisp_Object Qinhibit_menubar_update;
538int inhibit_menubar_update;
539
9142dd5b
GM
540/* Maximum height for resizing mini-windows. Either a float
541 specifying a fraction of the available height, or an integer
542 specifying a number of lines. */
c6e89d6c 543
ad4f174e
GM
544Lisp_Object Vmax_mini_window_height;
545
546/* Non-zero means messages should be displayed with truncated
547 lines instead of being continued. */
548
549int message_truncate_lines;
550Lisp_Object Qmessage_truncate_lines;
c6e89d6c 551
6e019995
GM
552/* Set to 1 in clear_message to make redisplay_internal aware
553 of an emptied echo area. */
554
555static int message_cleared_p;
556
d6d26ed3
GM
557/* Non-zero means we want a hollow cursor in windows that are not
558 selected. Zero means there's no cursor in such windows. */
559
cfe03a41 560Lisp_Object Vcursor_in_non_selected_windows;
af79bccb 561Lisp_Object Qcursor_in_non_selected_windows;
d6d26ed3 562
cfe03a41
KS
563/* How to blink the default frame cursor off. */
564Lisp_Object Vblink_cursor_alist;
565
5f5c8ee5
GM
566/* A scratch glyph row with contents used for generating truncation
567 glyphs. Also used in direct_output_for_insert. */
12adba34 568
5f5c8ee5
GM
569#define MAX_SCRATCH_GLYPHS 100
570struct glyph_row scratch_glyph_row;
571static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 572
5f5c8ee5
GM
573/* Ascent and height of the last line processed by move_it_to. */
574
575static int last_max_ascent, last_height;
576
21fdfb65
GM
577/* Non-zero if there's a help-echo in the echo area. */
578
579int help_echo_showing_p;
580
04612a64
GM
581/* If >= 0, computed, exact values of mode-line and header-line height
582 to use in the macros CURRENT_MODE_LINE_HEIGHT and
583 CURRENT_HEADER_LINE_HEIGHT. */
584
585int current_mode_line_height, current_header_line_height;
586
5f5c8ee5 587/* The maximum distance to look ahead for text properties. Values
2311178e 588 that are too small let us call compute_char_face and similar
5f5c8ee5
GM
589 functions too often which is expensive. Values that are too large
590 let us call compute_char_face and alike too often because we
591 might not be interested in text properties that far away. */
592
593#define TEXT_PROP_DISTANCE_LIMIT 100
594
47589c8c
GM
595#if GLYPH_DEBUG
596
76cb5e06
GM
597/* Variables to turn off display optimizations from Lisp. */
598
599int inhibit_try_window_id, inhibit_try_window_reusing;
600int inhibit_try_cursor_movement;
601
5f5c8ee5
GM
602/* Non-zero means print traces of redisplay if compiled with
603 GLYPH_DEBUG != 0. */
604
5f5c8ee5 605int trace_redisplay_p;
47589c8c 606
546a4f00 607#endif /* GLYPH_DEBUG */
47589c8c 608
546a4f00
AI
609#ifdef DEBUG_TRACE_MOVE
610/* Non-zero means trace with TRACE_MOVE to stderr. */
47589c8c
GM
611int trace_move;
612
47589c8c
GM
613#define TRACE_MOVE(x) if (trace_move) fprintf x; else (void) 0
614#else
91c3f500 615#define TRACE_MOVE(x) (void) 0
5f5c8ee5 616#endif
2311178e 617
d475bcb8
GM
618/* Non-zero means automatically scroll windows horizontally to make
619 point visible. */
620
621int automatic_hscrolling_p;
622
1df7e8f0
EZ
623/* How close to the margin can point get before the window is scrolled
624 horizontally. */
5d335845 625EMACS_INT hscroll_margin;
1df7e8f0
EZ
626
627/* How much to scroll horizontally when point is inside the above margin. */
e76d28d5 628Lisp_Object Vhscroll_step;
1df7e8f0 629
e00daaa0
GM
630/* A list of symbols, one for each supported image type. */
631
632Lisp_Object Vimage_types;
633
6422c1d7 634/* The variable `resize-mini-windows'. If nil, don't resize
67526daf 635 mini-windows. If t, always resize them to fit the text they
6422c1d7
GM
636 display. If `grow-only', let mini-windows grow only until they
637 become empty. */
638
639Lisp_Object Vresize_mini_windows;
640
82a7ab23
RS
641/* Buffer being redisplayed -- for redisplay_window_error. */
642
643struct buffer *displayed_buffer;
644
5f5c8ee5
GM
645/* Value returned from text property handlers (see below). */
646
647enum prop_handled
3c6595e0 648{
5f5c8ee5
GM
649 HANDLED_NORMALLY,
650 HANDLED_RECOMPUTE_PROPS,
651 HANDLED_OVERLAY_STRING_CONSUMED,
652 HANDLED_RETURN
653};
3c6595e0 654
5f5c8ee5
GM
655/* A description of text properties that redisplay is interested
656 in. */
3c6595e0 657
5f5c8ee5
GM
658struct props
659{
660 /* The name of the property. */
661 Lisp_Object *name;
90adcf20 662
5f5c8ee5
GM
663 /* A unique index for the property. */
664 enum prop_idx idx;
665
666 /* A handler function called to set up iterator IT from the property
667 at IT's current position. Value is used to steer handle_stop. */
668 enum prop_handled (*handler) P_ ((struct it *it));
669};
670
671static enum prop_handled handle_face_prop P_ ((struct it *));
672static enum prop_handled handle_invisible_prop P_ ((struct it *));
673static enum prop_handled handle_display_prop P_ ((struct it *));
260a86a0 674static enum prop_handled handle_composition_prop P_ ((struct it *));
5f5c8ee5
GM
675static enum prop_handled handle_overlay_change P_ ((struct it *));
676static enum prop_handled handle_fontified_prop P_ ((struct it *));
677
678/* Properties handled by iterators. */
679
680static struct props it_props[] =
5992c4f7 681{
5f5c8ee5
GM
682 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
683 /* Handle `face' before `display' because some sub-properties of
684 `display' need to know the face. */
685 {&Qface, FACE_PROP_IDX, handle_face_prop},
686 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
687 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
260a86a0 688 {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
5f5c8ee5
GM
689 {NULL, 0, NULL}
690};
5992c4f7 691
5f5c8ee5
GM
692/* Value is the position described by X. If X is a marker, value is
693 the marker_position of X. Otherwise, value is X. */
12adba34 694
5f5c8ee5 695#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 696
5f5c8ee5 697/* Enumeration returned by some move_it_.* functions internally. */
12adba34 698
5f5c8ee5
GM
699enum move_it_result
700{
701 /* Not used. Undefined value. */
702 MOVE_UNDEFINED,
bab29e15 703
5f5c8ee5
GM
704 /* Move ended at the requested buffer position or ZV. */
705 MOVE_POS_MATCH_OR_ZV,
bab29e15 706
5f5c8ee5
GM
707 /* Move ended at the requested X pixel position. */
708 MOVE_X_REACHED,
12adba34 709
5f5c8ee5
GM
710 /* Move within a line ended at the end of a line that must be
711 continued. */
712 MOVE_LINE_CONTINUED,
2311178e 713
5f5c8ee5
GM
714 /* Move within a line ended at the end of a line that would
715 be displayed truncated. */
716 MOVE_LINE_TRUNCATED,
ff6c30e5 717
5f5c8ee5
GM
718 /* Move within a line ended at a line end. */
719 MOVE_NEWLINE_OR_CR
720};
12adba34 721
1987b083
RS
722/* This counter is used to clear the face cache every once in a while
723 in redisplay_internal. It is incremented for each redisplay.
724 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
725 cleared. */
726
727#define CLEAR_FACE_CACHE_COUNT 500
728static int clear_face_cache_count;
729
730/* Record the previous terminal frame we displayed. */
731
732static struct frame *previous_terminal_frame;
733
734/* Non-zero while redisplay_internal is in progress. */
735
736int redisplaying_p;
737
26683087
RS
738/* Non-zero means don't free realized faces. Bound while freeing
739 realized faces is dangerous because glyph matrices might still
740 reference them. */
1987b083 741
26683087
RS
742int inhibit_free_realized_faces;
743Lisp_Object Qinhibit_free_realized_faces;
ff6c30e5 744
fa3c6b4d
KS
745/* If a string, XTread_socket generates an event to display that string.
746 (The display is done in read_char.) */
747
748Lisp_Object help_echo_string;
749Lisp_Object help_echo_window;
750Lisp_Object help_echo_object;
751int help_echo_pos;
752
753/* Temporary variable for XTread_socket. */
754
755Lisp_Object previous_help_echo_string;
756
757
5f5c8ee5
GM
758\f
759/* Function prototypes. */
760
5a08cbaf 761static void setup_for_ellipsis P_ ((struct it *));
43c09969 762static void mark_window_display_accurate_1 P_ ((struct window *, int));
74bd6d65
GM
763static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
764static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
cafafe0b 765static int cursor_row_p P_ ((struct window *, struct glyph_row *));
715e84c9 766static int redisplay_mode_lines P_ ((Lisp_Object, int));
2e621225 767static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
c0a53abb
PJ
768
769#if 0
2e621225 770static int invisible_text_between_p P_ ((struct it *, int, int));
c0a53abb
PJ
771#endif
772
2e621225
GM
773static int next_element_from_ellipsis P_ ((struct it *));
774static void pint2str P_ ((char *, int, int));
775static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
776 struct text_pos));
777static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
778static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
779static void store_frame_title_char P_ ((char));
50f80c2f 780static int store_frame_title P_ ((const unsigned char *, int, int));
2e621225
GM
781static void x_consider_frame_title P_ ((Lisp_Object));
782static void handle_stop P_ ((struct it *));
783static int tool_bar_lines_needed P_ ((struct frame *));
06568bbf 784static int single_display_prop_intangible_p P_ ((Lisp_Object));
5bcfeb49 785static void ensure_echo_area_buffers P_ ((void));
c6e89d6c
GM
786static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
787static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
23a96c77 788static int with_echo_area_buffer P_ ((struct window *, int,
23dd2d97
KR
789 int (*) (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT),
790 EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 791static void clear_garbaged_frames P_ ((void));
23dd2d97
KR
792static int current_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
793static int truncate_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
794static int set_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 795static int display_echo_area P_ ((struct window *));
23dd2d97
KR
796static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
797static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
28514cd9 798static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
50f80c2f 799static int string_char_and_length P_ ((const unsigned char *, int, int *));
5f5c8ee5
GM
800static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
801 struct text_pos));
802static int compute_window_start_on_continuation_line P_ ((struct window *));
116d6f5c 803static Lisp_Object safe_eval_handler P_ ((Lisp_Object));
5f5c8ee5
GM
804static void insert_left_trunc_glyphs P_ ((struct it *));
805static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
806static void extend_face_to_end_of_line P_ ((struct it *));
80c6cb1f 807static int append_space P_ ((struct it *, int));
cb617e7c 808static int make_cursor_line_fully_visible P_ ((struct window *));
03b0a4b4 809static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
47589c8c 810static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
5f5c8ee5
GM
811static int trailing_whitespace_p P_ ((int));
812static int message_log_check_duplicate P_ ((int, int, int, int));
5f5c8ee5
GM
813static void push_it P_ ((struct it *));
814static void pop_it P_ ((struct it *));
815static void sync_frame_with_window_matrix_rows P_ ((struct window *));
816static void redisplay_internal P_ ((int));
c6e89d6c 817static int echo_area_display P_ ((int));
5f5c8ee5
GM
818static void redisplay_windows P_ ((Lisp_Object));
819static void redisplay_window P_ ((Lisp_Object, int));
82a7ab23
RS
820static Lisp_Object redisplay_window_error ();
821static Lisp_Object redisplay_window_0 P_ ((Lisp_Object));
822static Lisp_Object redisplay_window_1 P_ ((Lisp_Object));
5f5c8ee5
GM
823static void update_menu_bar P_ ((struct frame *, int));
824static int try_window_reusing_current_matrix P_ ((struct window *));
825static int try_window_id P_ ((struct window *));
826static int display_line P_ ((struct it *));
715e84c9 827static int display_mode_lines P_ ((struct window *));
04612a64 828static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
c53a1624 829static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int));
fec8f23e 830static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object));
72f62cb5 831static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
5f5c8ee5
GM
832static void display_menu_bar P_ ((struct window *));
833static int display_count_lines P_ ((int, int, int, int, int *));
834static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
835 int, int, struct it *, int, int, int, int));
836static void compute_line_metrics P_ ((struct it *));
837static void run_redisplay_end_trigger_hook P_ ((struct it *));
5a08cbaf 838static int get_overlay_strings P_ ((struct it *, int));
5f5c8ee5 839static void next_overlay_string P_ ((struct it *));
5f5c8ee5
GM
840static void reseat P_ ((struct it *, struct text_pos, int));
841static void reseat_1 P_ ((struct it *, struct text_pos, int));
842static void back_to_previous_visible_line_start P_ ((struct it *));
843static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 844static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
845static int next_element_from_display_vector P_ ((struct it *));
846static int next_element_from_string P_ ((struct it *));
847static int next_element_from_c_string P_ ((struct it *));
848static int next_element_from_buffer P_ ((struct it *));
260a86a0 849static int next_element_from_composition P_ ((struct it *));
5f5c8ee5
GM
850static int next_element_from_image P_ ((struct it *));
851static int next_element_from_stretch P_ ((struct it *));
5a08cbaf 852static void load_overlay_strings P_ ((struct it *, int));
47d57b22
GM
853static int init_from_display_pos P_ ((struct it *, struct window *,
854 struct display_pos *));
5f5c8ee5
GM
855static void reseat_to_string P_ ((struct it *, unsigned char *,
856 Lisp_Object, int, int, int, int));
5f5c8ee5
GM
857static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
858 int, int, int));
859void move_it_vertically_backward P_ ((struct it *, int));
860static void init_to_row_start P_ ((struct it *, struct window *,
861 struct glyph_row *));
47d57b22
GM
862static int init_to_row_end P_ ((struct it *, struct window *,
863 struct glyph_row *));
5f5c8ee5 864static void back_to_previous_line_start P_ ((struct it *));
cafafe0b 865static int forward_to_next_line_start P_ ((struct it *, int *));
5f5c8ee5
GM
866static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
867 Lisp_Object, int));
868static struct text_pos string_pos P_ ((int, Lisp_Object));
869static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
870static int number_of_chars P_ ((unsigned char *, int));
871static void compute_stop_pos P_ ((struct it *));
872static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
873 Lisp_Object));
874static int face_before_or_after_it_pos P_ ((struct it *, int));
875static int next_overlay_change P_ ((int));
876static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
a61b7058
GM
877 Lisp_Object, struct text_pos *,
878 int));
06a12811 879static int underlying_face_id P_ ((struct it *));
4bde0ebb
GM
880static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
881 struct window *));
5f5c8ee5
GM
882
883#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
884#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 885
5f5c8ee5 886#ifdef HAVE_WINDOW_SYSTEM
12adba34 887
e037b9ec
GM
888static void update_tool_bar P_ ((struct frame *, int));
889static void build_desired_tool_bar_string P_ ((struct frame *f));
890static int redisplay_tool_bar P_ ((struct frame *));
891static void display_tool_bar_line P_ ((struct it *));
fa3c6b4d
KS
892static void notice_overwritten_cursor P_ ((struct window *,
893 enum glyph_row_area,
894 int, int, int, int));
895
896
12adba34 897
5f5c8ee5 898#endif /* HAVE_WINDOW_SYSTEM */
12adba34 899
5f5c8ee5
GM
900\f
901/***********************************************************************
902 Window display dimensions
903 ***********************************************************************/
12adba34 904
40a301b3
RS
905/* Return the bottom boundary y-position for text lines in window W.
906 This is the first y position at which a line cannot start.
907 It is relative to the top of the window.
908
909 This is the height of W minus the height of a mode line, if any. */
5f5c8ee5
GM
910
911INLINE int
912window_text_bottom_y (w)
913 struct window *w;
914{
da8b7f4f 915 int height = WINDOW_TOTAL_HEIGHT (w);
1a578e9b 916
5f5c8ee5
GM
917 if (WINDOW_WANTS_MODELINE_P (w))
918 height -= CURRENT_MODE_LINE_HEIGHT (w);
919 return height;
f88eb0b6
KH
920}
921
5f5c8ee5 922/* Return the pixel width of display area AREA of window W. AREA < 0
b46952ae 923 means return the total width of W, not including fringes to
5f5c8ee5 924 the left and right of the window. */
ff6c30e5 925
5f5c8ee5
GM
926INLINE int
927window_box_width (w, area)
928 struct window *w;
929 int area;
930{
da8b7f4f
KS
931 int cols = XFASTINT (w->total_cols);
932 int pixels = 0;
2311178e 933
5f5c8ee5 934 if (!w->pseudo_window_p)
ff6c30e5 935 {
da8b7f4f 936 cols -= WINDOW_SCROLL_BAR_COLS (w);
2311178e 937
5f5c8ee5
GM
938 if (area == TEXT_AREA)
939 {
da8b7f4f
KS
940 if (INTEGERP (w->left_margin_cols))
941 cols -= XFASTINT (w->left_margin_cols);
942 if (INTEGERP (w->right_margin_cols))
943 cols -= XFASTINT (w->right_margin_cols);
944 pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
5f5c8ee5
GM
945 }
946 else if (area == LEFT_MARGIN_AREA)
da8b7f4f
KS
947 {
948 cols = (INTEGERP (w->left_margin_cols)
949 ? XFASTINT (w->left_margin_cols) : 0);
950 pixels = 0;
951 }
5f5c8ee5 952 else if (area == RIGHT_MARGIN_AREA)
da8b7f4f
KS
953 {
954 cols = (INTEGERP (w->right_margin_cols)
955 ? XFASTINT (w->right_margin_cols) : 0);
956 pixels = 0;
957 }
ff6c30e5 958 }
5f5c8ee5 959
da8b7f4f 960 return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
ff6c30e5 961}
1adc55de 962
1adc55de 963
5f5c8ee5 964/* Return the pixel height of the display area of window W, not
4b41cebb 965 including mode lines of W, if any. */
f88eb0b6 966
5f5c8ee5
GM
967INLINE int
968window_box_height (w)
969 struct window *w;
f88eb0b6 970{
5f5c8ee5 971 struct frame *f = XFRAME (w->frame);
da8b7f4f 972 int height = WINDOW_TOTAL_HEIGHT (w);
7ecd4937
GM
973
974 xassert (height >= 0);
2311178e 975
d9c9e99c
MB
976 /* Note: the code below that determines the mode-line/header-line
977 height is essentially the same as that contained in the macro
978 CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
979 the appropriate glyph row has its `mode_line_p' flag set,
980 and if it doesn't, uses estimate_mode_line_height instead. */
981
5f5c8ee5 982 if (WINDOW_WANTS_MODELINE_P (w))
97dff879
MB
983 {
984 struct glyph_row *ml_row
985 = (w->current_matrix && w->current_matrix->rows
986 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
987 : 0);
988 if (ml_row && ml_row->mode_line_p)
989 height -= ml_row->height;
990 else
96d2320f 991 height -= estimate_mode_line_height (f, CURRENT_MODE_LINE_FACE_ID (w));
97dff879 992 }
5f5c8ee5 993
045dee35 994 if (WINDOW_WANTS_HEADER_LINE_P (w))
97dff879
MB
995 {
996 struct glyph_row *hl_row
997 = (w->current_matrix && w->current_matrix->rows
998 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
999 : 0);
1000 if (hl_row && hl_row->mode_line_p)
1001 height -= hl_row->height;
1002 else
1003 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1004 }
5f5c8ee5 1005
7c75be36
PJ
1006 /* With a very small font and a mode-line that's taller than
1007 default, we might end up with a negative height. */
1008 return max (0, height);
5992c4f7
KH
1009}
1010
da8b7f4f
KS
1011/* Return the window-relative coordinate of the left edge of display
1012 area AREA of window W. AREA < 0 means return the left edge of the
1013 whole window, to the right of the left fringe of W. */
1014
1015INLINE int
1016window_box_left_offset (w, area)
1017 struct window *w;
1018 int area;
1019{
1020 int x;
1021
1022 if (w->pseudo_window_p)
1023 return 0;
1024
1025 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1026
1027 if (area == TEXT_AREA)
1028 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1029 + window_box_width (w, LEFT_MARGIN_AREA));
1030 else if (area == RIGHT_MARGIN_AREA)
1031 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1032 + window_box_width (w, LEFT_MARGIN_AREA)
1033 + window_box_width (w, TEXT_AREA)
1034 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1035 ? 0
1036 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1037 else if (area == LEFT_MARGIN_AREA
1038 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1039 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1040
1041 return x;
1042}
1043
1044
1045/* Return the window-relative coordinate of the right edge of display
1046 area AREA of window W. AREA < 0 means return the left edge of the
1047 whole window, to the left of the right fringe of W. */
1048
1049INLINE int
1050window_box_right_offset (w, area)
1051 struct window *w;
1052 int area;
1053{
1054 return window_box_left_offset (w, area) + window_box_width (w, area);
1055}
5992c4f7 1056
5f5c8ee5
GM
1057/* Return the frame-relative coordinate of the left edge of display
1058 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 1059 whole window, to the right of the left fringe of W. */
5992c4f7 1060
5f5c8ee5
GM
1061INLINE int
1062window_box_left (w, area)
1063 struct window *w;
1064 int area;
90adcf20 1065{
5f5c8ee5 1066 struct frame *f = XFRAME (w->frame);
da8b7f4f 1067 int x;
a3788d53 1068
da8b7f4f
KS
1069 if (w->pseudo_window_p)
1070 return FRAME_INTERNAL_BORDER_WIDTH (f);
2311178e 1071
da8b7f4f
KS
1072 x = (WINDOW_LEFT_EDGE_X (w)
1073 + window_box_left_offset (w, area));
73af359d 1074
5f5c8ee5 1075 return x;
2311178e 1076}
90adcf20 1077
b6436d4e 1078
5f5c8ee5
GM
1079/* Return the frame-relative coordinate of the right edge of display
1080 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 1081 whole window, to the left of the right fringe of W. */
ded34426 1082
5f5c8ee5
GM
1083INLINE int
1084window_box_right (w, area)
1085 struct window *w;
1086 int area;
1087{
1088 return window_box_left (w, area) + window_box_width (w, area);
2311178e
TTN
1089}
1090
5f5c8ee5
GM
1091/* Get the bounding box of the display area AREA of window W, without
1092 mode lines, in frame-relative coordinates. AREA < 0 means the
b46952ae 1093 whole window, not including the left and right fringes of
5f5c8ee5
GM
1094 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
1095 coordinates of the upper-left corner of the box. Return in
1096 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
1097
1098INLINE void
1099window_box (w, area, box_x, box_y, box_width, box_height)
1100 struct window *w;
1101 int area;
1102 int *box_x, *box_y, *box_width, *box_height;
1103{
da8b7f4f
KS
1104 if (box_width)
1105 *box_width = window_box_width (w, area);
1106 if (box_height)
1107 *box_height = window_box_height (w);
1108 if (box_x)
1109 *box_x = window_box_left (w, area);
1110 if (box_y)
1111 {
1112 *box_y = WINDOW_TOP_EDGE_Y (w);
1113 if (WINDOW_WANTS_HEADER_LINE_P (w))
1114 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1115 }
ded34426 1116}
1adc55de 1117
1adc55de 1118
5f5c8ee5 1119/* Get the bounding box of the display area AREA of window W, without
b46952ae
KS
1120 mode lines. AREA < 0 means the whole window, not including the
1121 left and right fringe of the window. Return in *TOP_LEFT_X
5f5c8ee5
GM
1122 and TOP_LEFT_Y the frame-relative pixel coordinates of the
1123 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
1124 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
1125 box. */
ded34426 1126
5f5c8ee5
GM
1127INLINE void
1128window_box_edges (w, area, top_left_x, top_left_y,
1129 bottom_right_x, bottom_right_y)
1130 struct window *w;
1131 int area;
1132 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 1133{
5f5c8ee5
GM
1134 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
1135 bottom_right_y);
1136 *bottom_right_x += *top_left_x;
1137 *bottom_right_y += *top_left_y;
48ae5f0a
KH
1138}
1139
5f5c8ee5
GM
1140
1141\f
1142/***********************************************************************
1143 Utilities
1144 ***********************************************************************/
1145
8b6ea97f
GM
1146/* Return the bottom y-position of the line the iterator IT is in.
1147 This can modify IT's settings. */
1148
1149int
1150line_bottom_y (it)
1151 struct it *it;
1152{
1153 int line_height = it->max_ascent + it->max_descent;
1154 int line_top_y = it->current_y;
2311178e 1155
8b6ea97f
GM
1156 if (line_height == 0)
1157 {
1158 if (last_height)
1159 line_height = last_height;
1160 else if (IT_CHARPOS (*it) < ZV)
1161 {
1162 move_it_by_lines (it, 1, 1);
1163 line_height = (it->max_ascent || it->max_descent
1164 ? it->max_ascent + it->max_descent
1165 : last_height);
1166 }
1167 else
1168 {
1169 struct glyph_row *row = it->glyph_row;
2311178e 1170
8b6ea97f
GM
1171 /* Use the default character height. */
1172 it->glyph_row = NULL;
1173 it->what = IT_CHARACTER;
1174 it->c = ' ';
1175 it->len = 1;
1176 PRODUCE_GLYPHS (it);
1177 line_height = it->ascent + it->descent;
1178 it->glyph_row = row;
1179 }
1180 }
1181
1182 return line_top_y + line_height;
1183}
1184
1185
0db95684
GM
1186/* Return 1 if position CHARPOS is visible in window W. Set *FULLY to
1187 1 if POS is visible and the line containing POS is fully visible.
1188 EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
1189 and header-lines heights. */
3a641a69
GM
1190
1191int
04612a64 1192pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
3a641a69 1193 struct window *w;
04612a64 1194 int charpos, *fully, exact_mode_line_heights_p;
3a641a69
GM
1195{
1196 struct it it;
1197 struct text_pos top;
fcab1954
GM
1198 int visible_p;
1199 struct buffer *old_buffer = NULL;
1200
1201 if (XBUFFER (w->buffer) != current_buffer)
1202 {
1203 old_buffer = current_buffer;
1204 set_buffer_internal_1 (XBUFFER (w->buffer));
1205 }
3a641a69
GM
1206
1207 *fully = visible_p = 0;
1208 SET_TEXT_POS_FROM_MARKER (top, w->start);
2311178e 1209
04612a64
GM
1210 /* Compute exact mode line heights, if requested. */
1211 if (exact_mode_line_heights_p)
1212 {
1213 if (WINDOW_WANTS_MODELINE_P (w))
1214 current_mode_line_height
96d2320f 1215 = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
04612a64 1216 current_buffer->mode_line_format);
2311178e 1217
04612a64
GM
1218 if (WINDOW_WANTS_HEADER_LINE_P (w))
1219 current_header_line_height
1220 = display_mode_line (w, HEADER_LINE_FACE_ID,
1221 current_buffer->header_line_format);
1222 }
3a641a69 1223
04612a64 1224 start_display (&it, w, top);
3a641a69
GM
1225 move_it_to (&it, charpos, 0, it.last_visible_y, -1,
1226 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
a13be207
GM
1227
1228 /* Note that we may overshoot because of invisible text. */
1229 if (IT_CHARPOS (it) >= charpos)
3a641a69 1230 {
8b6ea97f
GM
1231 int top_y = it.current_y;
1232 int bottom_y = line_bottom_y (&it);
da8b7f4f 1233 int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
2311178e 1234
8b6ea97f
GM
1235 if (top_y < window_top_y)
1236 visible_p = bottom_y > window_top_y;
1237 else if (top_y < it.last_visible_y)
fcab1954
GM
1238 {
1239 visible_p = 1;
8b6ea97f 1240 *fully = bottom_y <= it.last_visible_y;
fcab1954 1241 }
3a641a69
GM
1242 }
1243 else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
1244 {
1245 move_it_by_lines (&it, 1, 0);
1246 if (charpos < IT_CHARPOS (it))
1247 {
1248 visible_p = 1;
1249 *fully = 0;
1250 }
1251 }
fcab1954
GM
1252
1253 if (old_buffer)
1254 set_buffer_internal_1 (old_buffer);
04612a64
GM
1255
1256 current_header_line_height = current_mode_line_height = -1;
3a641a69
GM
1257 return visible_p;
1258}
1259
1260
4fdb80f2
GM
1261/* Return the next character from STR which is MAXLEN bytes long.
1262 Return in *LEN the length of the character. This is like
1263 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
9ab8560d 1264 we find one, we return a `?', but with the length of the invalid
4fdb80f2
GM
1265 character. */
1266
1267static INLINE int
7a5b8a93 1268string_char_and_length (str, maxlen, len)
50f80c2f 1269 const unsigned char *str;
7a5b8a93 1270 int maxlen, *len;
4fdb80f2
GM
1271{
1272 int c;
1273
1274 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
1275 if (!CHAR_VALID_P (c, 1))
1276 /* We may not change the length here because other places in Emacs
9ab8560d 1277 don't use this function, i.e. they silently accept invalid
4fdb80f2
GM
1278 characters. */
1279 c = '?';
1280
1281 return c;
1282}
1283
1284
1285
5f5c8ee5
GM
1286/* Given a position POS containing a valid character and byte position
1287 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
1288
1289static struct text_pos
1290string_pos_nchars_ahead (pos, string, nchars)
1291 struct text_pos pos;
1292 Lisp_Object string;
1293 int nchars;
0b1005ef 1294{
5f5c8ee5
GM
1295 xassert (STRINGP (string) && nchars >= 0);
1296
1297 if (STRING_MULTIBYTE (string))
1298 {
2051c264 1299 int rest = SBYTES (string) - BYTEPOS (pos);
50f80c2f 1300 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
5f5c8ee5
GM
1301 int len;
1302
1303 while (nchars--)
1304 {
4fdb80f2 1305 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1306 p += len, rest -= len;
1307 xassert (rest >= 0);
1308 CHARPOS (pos) += 1;
1309 BYTEPOS (pos) += len;
1310 }
1311 }
1312 else
1313 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
1314
1315 return pos;
0a9dc68b
RS
1316}
1317
0a9dc68b 1318
5f5c8ee5
GM
1319/* Value is the text position, i.e. character and byte position,
1320 for character position CHARPOS in STRING. */
1321
1322static INLINE struct text_pos
1323string_pos (charpos, string)
1324 int charpos;
0a9dc68b 1325 Lisp_Object string;
0a9dc68b 1326{
5f5c8ee5
GM
1327 struct text_pos pos;
1328 xassert (STRINGP (string));
1329 xassert (charpos >= 0);
1330 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
1331 return pos;
1332}
1333
1334
1335/* Value is a text position, i.e. character and byte position, for
1336 character position CHARPOS in C string S. MULTIBYTE_P non-zero
1337 means recognize multibyte characters. */
1338
1339static struct text_pos
1340c_string_pos (charpos, s, multibyte_p)
1341 int charpos;
1342 unsigned char *s;
1343 int multibyte_p;
1344{
1345 struct text_pos pos;
1346
1347 xassert (s != NULL);
1348 xassert (charpos >= 0);
1349
1350 if (multibyte_p)
0a9dc68b 1351 {
5f5c8ee5
GM
1352 int rest = strlen (s), len;
1353
1354 SET_TEXT_POS (pos, 0, 0);
1355 while (charpos--)
0a9dc68b 1356 {
4fdb80f2 1357 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
1358 s += len, rest -= len;
1359 xassert (rest >= 0);
1360 CHARPOS (pos) += 1;
1361 BYTEPOS (pos) += len;
0a9dc68b
RS
1362 }
1363 }
5f5c8ee5
GM
1364 else
1365 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 1366
5f5c8ee5
GM
1367 return pos;
1368}
0a9dc68b 1369
0a9dc68b 1370
5f5c8ee5
GM
1371/* Value is the number of characters in C string S. MULTIBYTE_P
1372 non-zero means recognize multibyte characters. */
0a9dc68b 1373
5f5c8ee5
GM
1374static int
1375number_of_chars (s, multibyte_p)
1376 unsigned char *s;
1377 int multibyte_p;
1378{
1379 int nchars;
2311178e 1380
5f5c8ee5
GM
1381 if (multibyte_p)
1382 {
1383 int rest = strlen (s), len;
1384 unsigned char *p = (unsigned char *) s;
0a9dc68b 1385
5f5c8ee5
GM
1386 for (nchars = 0; rest > 0; ++nchars)
1387 {
4fdb80f2 1388 string_char_and_length (p, rest, &len);
5f5c8ee5 1389 rest -= len, p += len;
0a9dc68b
RS
1390 }
1391 }
5f5c8ee5
GM
1392 else
1393 nchars = strlen (s);
1394
1395 return nchars;
0b1005ef
KH
1396}
1397
2311178e 1398
5f5c8ee5
GM
1399/* Compute byte position NEWPOS->bytepos corresponding to
1400 NEWPOS->charpos. POS is a known position in string STRING.
1401 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1402
5f5c8ee5
GM
1403static void
1404compute_string_pos (newpos, pos, string)
1405 struct text_pos *newpos, pos;
1406 Lisp_Object string;
76412d64 1407{
5f5c8ee5
GM
1408 xassert (STRINGP (string));
1409 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
2311178e 1410
5f5c8ee5 1411 if (STRING_MULTIBYTE (string))
6fc556fd
KR
1412 *newpos = string_pos_nchars_ahead (pos, string,
1413 CHARPOS (*newpos) - CHARPOS (pos));
5f5c8ee5
GM
1414 else
1415 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1416}
1417
fa3c6b4d
KS
1418/* EXPORT:
1419 Return an estimation of the pixel height of mode or top lines on
1420 frame F. FACE_ID specifies what line's height to estimate. */
1421
1422int
1423estimate_mode_line_height (f, face_id)
1424 struct frame *f;
1425 enum face_id face_id;
1426{
1427#ifdef HAVE_WINDOW_SYSTEM
1428 if (FRAME_WINDOW_P (f))
1429 {
1430 int height = FONT_HEIGHT (FRAME_FONT (f));
1431
1432 /* This function is called so early when Emacs starts that the face
1433 cache and mode line face are not yet initialized. */
1434 if (FRAME_FACE_CACHE (f))
1435 {
1436 struct face *face = FACE_FROM_ID (f, face_id);
1437 if (face)
1438 {
1439 if (face->font)
1440 height = FONT_HEIGHT (face->font);
1441 if (face->box_line_width > 0)
1442 height += 2 * face->box_line_width;
1443 }
1444 }
1445
1446 return height;
1447 }
1448#endif
1449
1450 return 1;
1451}
1452
e080d3eb
KS
1453/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
1454 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
1455 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
1456 not force the value into range. */
1457
1458void
1459pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1460 FRAME_PTR f;
1461 register int pix_x, pix_y;
1462 int *x, *y;
1463 NativeRectangle *bounds;
1464 int noclip;
1465{
1466
1467#ifdef HAVE_WINDOW_SYSTEM
1468 if (FRAME_WINDOW_P (f))
1469 {
da8b7f4f 1470 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to round down
e080d3eb
KS
1471 even for negative values. */
1472 if (pix_x < 0)
da8b7f4f 1473 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
e080d3eb 1474 if (pix_y < 0)
da8b7f4f 1475 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
e080d3eb 1476
da8b7f4f
KS
1477 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
1478 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
e080d3eb
KS
1479
1480 if (bounds)
1481 STORE_NATIVE_RECT (*bounds,
da8b7f4f
KS
1482 FRAME_COL_TO_PIXEL_X (f, pix_x),
1483 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
1484 FRAME_COLUMN_WIDTH (f) - 1,
1485 FRAME_LINE_HEIGHT (f) - 1);
e080d3eb
KS
1486
1487 if (!noclip)
1488 {
1489 if (pix_x < 0)
1490 pix_x = 0;
da8b7f4f
KS
1491 else if (pix_x > FRAME_TOTAL_COLS (f))
1492 pix_x = FRAME_TOTAL_COLS (f);
e080d3eb
KS
1493
1494 if (pix_y < 0)
1495 pix_y = 0;
da8b7f4f
KS
1496 else if (pix_y > FRAME_LINES (f))
1497 pix_y = FRAME_LINES (f);
e080d3eb
KS
1498 }
1499 }
1500#endif
1501
1502 *x = pix_x;
1503 *y = pix_y;
1504}
1505
1506
1507/* Given HPOS/VPOS in the current matrix of W, return corresponding
1508 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
1509 can't tell the positions because W's display is not up to date,
1510 return 0. */
1511
1512int
1513glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
1514 struct window *w;
1515 int hpos, vpos;
1516 int *frame_x, *frame_y;
1517{
1518#ifdef HAVE_WINDOW_SYSTEM
1519 if (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))))
1520 {
1521 int success_p;
1522
1523 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
1524 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
1525
1526 if (display_completed)
1527 {
1528 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
1529 struct glyph *glyph = row->glyphs[TEXT_AREA];
1530 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
1531
1532 hpos = row->x;
1533 vpos = row->y;
1534 while (glyph < end)
1535 {
1536 hpos += glyph->pixel_width;
1537 ++glyph;
1538 }
1539
1540 success_p = 1;
1541 }
1542 else
1543 {
1544 hpos = vpos = 0;
1545 success_p = 0;
1546 }
1547
1548 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, hpos);
1549 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, vpos);
1550 return success_p;
1551 }
1552#endif
1553
1554 *frame_x = hpos;
1555 *frame_y = vpos;
1556 return 1;
1557}
1558
1559
fa3c6b4d
KS
1560#ifdef HAVE_WINDOW_SYSTEM
1561
1562/* Find the glyph under window-relative coordinates X/Y in window W.
1563 Consider only glyphs from buffer text, i.e. no glyphs from overlay
1564 strings. Return in *HPOS and *VPOS the row and column number of
1565 the glyph found. Return in *AREA the glyph area containing X.
1566 Value is a pointer to the glyph found or null if X/Y is not on
1567 text, or we can't tell because W's current matrix is not up to
1568 date. */
1569
1570static struct glyph *
1571x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
1572 struct window *w;
1573 int x, y;
1574 int *hpos, *vpos, *area;
1575 int buffer_only_p;
1576{
1577 struct glyph *glyph, *end;
1578 struct glyph_row *row = NULL;
da8b7f4f 1579 int x0, i;
fa3c6b4d
KS
1580
1581 /* Find row containing Y. Give up if some row is not enabled. */
1582 for (i = 0; i < w->current_matrix->nrows; ++i)
1583 {
1584 row = MATRIX_ROW (w->current_matrix, i);
1585 if (!row->enabled_p)
1586 return NULL;
1587 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
1588 break;
1589 }
1590
1591 *vpos = i;
1592 *hpos = 0;
1593
1594 /* Give up if Y is not in the window. */
1595 if (i == w->current_matrix->nrows)
1596 return NULL;
1597
1598 /* Get the glyph area containing X. */
1599 if (w->pseudo_window_p)
1600 {
1601 *area = TEXT_AREA;
1602 x0 = 0;
1603 }
1604 else
1605 {
da8b7f4f 1606 if (x < window_box_left_offset (w, TEXT_AREA))
fa3c6b4d
KS
1607 {
1608 *area = LEFT_MARGIN_AREA;
da8b7f4f 1609 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
fa3c6b4d 1610 }
da8b7f4f 1611 else if (x < window_box_right_offset (w, TEXT_AREA))
fa3c6b4d
KS
1612 {
1613 *area = TEXT_AREA;
da8b7f4f 1614 x0 = window_box_left_offset (w, TEXT_AREA);
fa3c6b4d
KS
1615 }
1616 else
1617 {
1618 *area = RIGHT_MARGIN_AREA;
da8b7f4f 1619 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
fa3c6b4d
KS
1620 }
1621 }
1622
1623 /* Find glyph containing X. */
1624 glyph = row->glyphs[*area];
1625 end = glyph + row->used[*area];
1626 while (glyph < end)
1627 {
1628 if (x < x0 + glyph->pixel_width)
1629 {
1630 if (w->pseudo_window_p)
1631 break;
1632 else if (!buffer_only_p || BUFFERP (glyph->object))
1633 break;
1634 }
1635
1636 x0 += glyph->pixel_width;
1637 ++glyph;
1638 }
1639
1640 if (glyph == end)
1641 return NULL;
1642
1643 *hpos = glyph - row->glyphs[*area];
1644 return glyph;
1645}
1646
1647
1648/* EXPORT:
1649 Convert frame-relative x/y to coordinates relative to window W.
1650 Takes pseudo-windows into account. */
1651
1652void
1653frame_to_window_pixel_xy (w, x, y)
1654 struct window *w;
1655 int *x, *y;
1656{
1657 if (w->pseudo_window_p)
1658 {
1659 /* A pseudo-window is always full-width, and starts at the
1660 left edge of the frame, plus a frame border. */
1661 struct frame *f = XFRAME (w->frame);
da8b7f4f 1662 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
fa3c6b4d
KS
1663 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1664 }
1665 else
1666 {
da8b7f4f 1667 *x -= WINDOW_LEFT_EDGE_X (w);
fa3c6b4d
KS
1668 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1669 }
1670}
1671
1672/* EXPORT:
1673 Return in *R the clipping rectangle for glyph string S. */
1674
1675void
1676get_glyph_string_clip_rect (s, nr)
1677 struct glyph_string *s;
1678 NativeRectangle *nr;
1679{
1680 XRectangle r;
1681
1682 if (s->row->full_width_p)
1683 {
da8b7f4f
KS
1684 /* Draw full-width. X coordinates are relative to S->w->left_col. */
1685 r.x = WINDOW_LEFT_EDGE_X (s->w);
1686 r.width = WINDOW_TOTAL_WIDTH (s->w);
fa3c6b4d
KS
1687
1688 /* Unless displaying a mode or menu bar line, which are always
1689 fully visible, clip to the visible part of the row. */
1690 if (s->w->pseudo_window_p)
1691 r.height = s->row->visible_height;
1692 else
1693 r.height = s->height;
1694 }
1695 else
1696 {
1697 /* This is a text line that may be partially visible. */
da8b7f4f 1698 r.x = window_box_left (s->w, s->area);
fa3c6b4d
KS
1699 r.width = window_box_width (s->w, s->area);
1700 r.height = s->row->visible_height;
1701 }
1702
1703 /* If S draws overlapping rows, it's sufficient to use the top and
1704 bottom of the window for clipping because this glyph string
1705 intentionally draws over other lines. */
1706 if (s->for_overlaps_p)
1707 {
da8b7f4f 1708 r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
fa3c6b4d
KS
1709 r.height = window_text_bottom_y (s->w) - r.y;
1710 }
1711 else
1712 {
1713 /* Don't use S->y for clipping because it doesn't take partially
1714 visible lines into account. For example, it can be negative for
1715 partially visible lines at the top of a window. */
1716 if (!s->row->full_width_p
1717 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
da8b7f4f 1718 r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
fa3c6b4d
KS
1719 else
1720 r.y = max (0, s->row->y);
1721
1722 /* If drawing a tool-bar window, draw it over the internal border
1723 at the top of the window. */
1724 if (s->w == XWINDOW (s->f->tool_bar_window))
b4ebbb12 1725 r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
fa3c6b4d
KS
1726 }
1727
1728 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
1729
1730#ifdef HAVE_NTGUI
1731 /* ++KFS: From W32 port, but it looks ok for all platforms to me. */
1732 /* If drawing the cursor, don't let glyph draw outside its
1733 advertised boundaries. Cleartype does this under some circumstances. */
1734 if (s->hl == DRAW_CURSOR)
1735 {
1736 if (s->x > r.x)
1737 {
1738 r.width -= s->x - r.x;
1739 r.x = s->x;
1740 }
1741 r.width = min (r.width, s->first_glyph->pixel_width);
1742 }
1743#endif
1744
1745#ifdef CONVERT_FROM_XRECT
1746 CONVERT_FROM_XRECT (r, *nr);
1747#else
1748 *nr = r;
fd4c9408 1749#endif
fa3c6b4d
KS
1750}
1751
1752#endif /* HAVE_WINDOW_SYSTEM */
9c74a0dd 1753
5f5c8ee5
GM
1754\f
1755/***********************************************************************
1756 Lisp form evaluation
1757 ***********************************************************************/
1758
116d6f5c 1759/* Error handler for safe_eval and safe_call. */
5f5c8ee5
GM
1760
1761static Lisp_Object
116d6f5c 1762safe_eval_handler (arg)
5f5c8ee5
GM
1763 Lisp_Object arg;
1764{
0dbf9fd2 1765 add_to_log ("Error during redisplay: %s", arg, Qnil);
5f5c8ee5
GM
1766 return Qnil;
1767}
1768
1769
1770/* Evaluate SEXPR and return the result, or nil if something went
2913a9c0 1771 wrong. Prevent redisplay during the evaluation. */
5f5c8ee5 1772
71e5b1b8 1773Lisp_Object
116d6f5c 1774safe_eval (sexpr)
5f5c8ee5
GM
1775 Lisp_Object sexpr;
1776{
5f5c8ee5 1777 Lisp_Object val;
2311178e 1778
30a3f61c
GM
1779 if (inhibit_eval_during_redisplay)
1780 val = Qnil;
1781 else
1782 {
331379bf 1783 int count = SPECPDL_INDEX ();
30a3f61c 1784 struct gcpro gcpro1;
0d8b31c0 1785
30a3f61c
GM
1786 GCPRO1 (sexpr);
1787 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1788 /* Use Qt to ensure debugger does not run,
1789 so there is no possibility of wanting to redisplay. */
1790 val = internal_condition_case_1 (Feval, sexpr, Qt,
30a3f61c
GM
1791 safe_eval_handler);
1792 UNGCPRO;
1793 val = unbind_to (count, val);
1794 }
2311178e 1795
30a3f61c 1796 return val;
0d8b31c0
GM
1797}
1798
1799
1800/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
2913a9c0
GM
1801 Return the result, or nil if something went wrong. Prevent
1802 redisplay during the evaluation. */
0d8b31c0
GM
1803
1804Lisp_Object
116d6f5c 1805safe_call (nargs, args)
0d8b31c0
GM
1806 int nargs;
1807 Lisp_Object *args;
1808{
0d8b31c0 1809 Lisp_Object val;
2311178e 1810
30a3f61c
GM
1811 if (inhibit_eval_during_redisplay)
1812 val = Qnil;
1813 else
1814 {
331379bf 1815 int count = SPECPDL_INDEX ();
30a3f61c 1816 struct gcpro gcpro1;
0d8b31c0 1817
30a3f61c
GM
1818 GCPRO1 (args[0]);
1819 gcpro1.nvars = nargs;
1820 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1821 /* Use Qt to ensure debugger does not run,
1822 so there is no possibility of wanting to redisplay. */
1823 val = internal_condition_case_2 (Ffuncall, nargs, args, Qt,
30a3f61c
GM
1824 safe_eval_handler);
1825 UNGCPRO;
1826 val = unbind_to (count, val);
1827 }
1828
1829 return val;
5f5c8ee5
GM
1830}
1831
1832
116d6f5c
GM
1833/* Call function FN with one argument ARG.
1834 Return the result, or nil if something went wrong. */
1835
1836Lisp_Object
1837safe_call1 (fn, arg)
1838 Lisp_Object fn, arg;
1839{
1840 Lisp_Object args[2];
1841 args[0] = fn;
1842 args[1] = arg;
1843 return safe_call (2, args);
1844}
1845
1846
5f5c8ee5
GM
1847\f
1848/***********************************************************************
1849 Debugging
1850 ***********************************************************************/
1851
1852#if 0
1853
1854/* Define CHECK_IT to perform sanity checks on iterators.
1855 This is for debugging. It is too slow to do unconditionally. */
1856
1857static void
1858check_it (it)
1859 struct it *it;
1860{
1861 if (it->method == next_element_from_string)
a2889657 1862 {
5f5c8ee5
GM
1863 xassert (STRINGP (it->string));
1864 xassert (IT_STRING_CHARPOS (*it) >= 0);
1865 }
1866 else if (it->method == next_element_from_buffer)
1867 {
1868 /* Check that character and byte positions agree. */
1869 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1870 }
73af359d 1871
5f5c8ee5
GM
1872 if (it->dpvec)
1873 xassert (it->current.dpvec_index >= 0);
1874 else
1875 xassert (it->current.dpvec_index < 0);
1876}
1f40cad2 1877
5f5c8ee5
GM
1878#define CHECK_IT(IT) check_it ((IT))
1879
1880#else /* not 0 */
1881
1882#define CHECK_IT(IT) (void) 0
1883
1884#endif /* not 0 */
1885
1886
1887#if GLYPH_DEBUG
1888
1889/* Check that the window end of window W is what we expect it
1890 to be---the last row in the current matrix displaying text. */
1891
1892static void
1893check_window_end (w)
1894 struct window *w;
1895{
1896 if (!MINI_WINDOW_P (w)
1897 && !NILP (w->window_end_valid))
1898 {
1899 struct glyph_row *row;
1900 xassert ((row = MATRIX_ROW (w->current_matrix,
1901 XFASTINT (w->window_end_vpos)),
1902 !row->enabled_p
1903 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1904 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1905 }
1906}
1907
1908#define CHECK_WINDOW_END(W) check_window_end ((W))
1909
1910#else /* not GLYPH_DEBUG */
1911
1912#define CHECK_WINDOW_END(W) (void) 0
1913
1914#endif /* not GLYPH_DEBUG */
1915
1916
1917\f
1918/***********************************************************************
1919 Iterator initialization
1920 ***********************************************************************/
1921
1922/* Initialize IT for displaying current_buffer in window W, starting
1923 at character position CHARPOS. CHARPOS < 0 means that no buffer
1924 position is specified which is useful when the iterator is assigned
1925 a position later. BYTEPOS is the byte position corresponding to
3ebf0ea9 1926 CHARPOS. BYTEPOS < 0 means compute it from CHARPOS.
5f5c8ee5
GM
1927
1928 If ROW is not null, calls to produce_glyphs with IT as parameter
1929 will produce glyphs in that row.
1930
1931 BASE_FACE_ID is the id of a base face to use. It must be one of
96d2320f
KS
1932 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID,
1933 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID for displaying
1934 mode lines, or TOOL_BAR_FACE_ID for displaying the tool-bar.
2311178e 1935
96d2320f
KS
1936 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID,
1937 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID, the iterator
1938 will be initialized to use the corresponding mode line glyph row of
1939 the desired matrix of W. */
5f5c8ee5
GM
1940
1941void
1942init_iterator (it, w, charpos, bytepos, row, base_face_id)
1943 struct it *it;
1944 struct window *w;
1945 int charpos, bytepos;
1946 struct glyph_row *row;
1947 enum face_id base_face_id;
1948{
1949 int highlight_region_p;
5f5c8ee5
GM
1950
1951 /* Some precondition checks. */
1952 xassert (w != NULL && it != NULL);
3b6b6db7
SM
1953 xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
1954 && charpos <= ZV));
5f5c8ee5
GM
1955
1956 /* If face attributes have been changed since the last redisplay,
1957 free realized faces now because they depend on face definitions
7d0393cf 1958 that might have changed. Don't free faces while there might be
1987b083 1959 desired matrices pending which reference these faces. */
26683087 1960 if (face_change_count && !inhibit_free_realized_faces)
5f5c8ee5
GM
1961 {
1962 face_change_count = 0;
1963 free_all_realized_faces (Qnil);
1964 }
1965
1966 /* Use one of the mode line rows of W's desired matrix if
1967 appropriate. */
1968 if (row == NULL)
1969 {
96d2320f
KS
1970 if (base_face_id == MODE_LINE_FACE_ID
1971 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
5f5c8ee5 1972 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
1973 else if (base_face_id == HEADER_LINE_FACE_ID)
1974 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5 1975 }
2311178e 1976
5f5c8ee5
GM
1977 /* Clear IT. */
1978 bzero (it, sizeof *it);
1979 it->current.overlay_string_index = -1;
1980 it->current.dpvec_index = -1;
5f5c8ee5
GM
1981 it->base_face_id = base_face_id;
1982
1983 /* The window in which we iterate over current_buffer: */
1984 XSETWINDOW (it->window, w);
1985 it->w = w;
1986 it->f = XFRAME (w->frame);
1987
d475bcb8
GM
1988 /* Extra space between lines (on window systems only). */
1989 if (base_face_id == DEFAULT_FACE_ID
1990 && FRAME_WINDOW_P (it->f))
1991 {
1992 if (NATNUMP (current_buffer->extra_line_spacing))
1993 it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
1994 else if (it->f->extra_line_spacing > 0)
1995 it->extra_line_spacing = it->f->extra_line_spacing;
1996 }
1997
5f5c8ee5 1998 /* If realized faces have been removed, e.g. because of face
62be9979
GM
1999 attribute changes of named faces, recompute them. When running
2000 in batch mode, the face cache of Vterminal_frame is null. If
2001 we happen to get called, make a dummy face cache. */
a24d4cb2 2002 if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
62be9979 2003 init_frame_faces (it->f);
5f5c8ee5
GM
2004 if (FRAME_FACE_CACHE (it->f)->used == 0)
2005 recompute_basic_faces (it->f);
2006
5f5c8ee5
GM
2007 /* Current value of the `space-width', and 'height' properties. */
2008 it->space_width = Qnil;
2009 it->font_height = Qnil;
2311178e 2010
5f5c8ee5
GM
2011 /* Are control characters displayed as `^C'? */
2012 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
2013
2014 /* -1 means everything between a CR and the following line end
2015 is invisible. >0 means lines indented more than this value are
2016 invisible. */
2017 it->selective = (INTEGERP (current_buffer->selective_display)
2018 ? XFASTINT (current_buffer->selective_display)
2311178e 2019 : (!NILP (current_buffer->selective_display)
5f5c8ee5
GM
2020 ? -1 : 0));
2021 it->selective_display_ellipsis_p
2022 = !NILP (current_buffer->selective_display_ellipses);
2023
2024 /* Display table to use. */
2025 it->dp = window_display_table (w);
2026
2027 /* Are multibyte characters enabled in current_buffer? */
2028 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
2029
2030 /* Non-zero if we should highlight the region. */
2031 highlight_region_p
3ebf0ea9 2032 = (!NILP (Vtransient_mark_mode)
5f5c8ee5
GM
2033 && !NILP (current_buffer->mark_active)
2034 && XMARKER (current_buffer->mark)->buffer != 0);
2035
2036 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
2037 start and end of a visible region in window IT->w. Set both to
2038 -1 to indicate no region. */
2039 if (highlight_region_p
2040 /* Maybe highlight only in selected window. */
2311178e 2041 && (/* Either show region everywhere. */
5f5c8ee5
GM
2042 highlight_nonselected_windows
2043 /* Or show region in the selected window. */
2044 || w == XWINDOW (selected_window)
2045 /* Or show the region if we are in the mini-buffer and W is
2046 the window the mini-buffer refers to. */
2047 || (MINI_WINDOW_P (XWINDOW (selected_window))
5705966b
KS
2048 && WINDOWP (minibuf_selected_window)
2049 && w == XWINDOW (minibuf_selected_window))))
5f5c8ee5
GM
2050 {
2051 int charpos = marker_position (current_buffer->mark);
2052 it->region_beg_charpos = min (PT, charpos);
2053 it->region_end_charpos = max (PT, charpos);
2054 }
2055 else
2056 it->region_beg_charpos = it->region_end_charpos = -1;
2057
2058 /* Get the position at which the redisplay_end_trigger hook should
2059 be run, if it is to be run at all. */
2060 if (MARKERP (w->redisplay_end_trigger)
2061 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
2062 it->redisplay_end_trigger_charpos
2063 = marker_position (w->redisplay_end_trigger);
2064 else if (INTEGERP (w->redisplay_end_trigger))
2065 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
2066
2067 /* Correct bogus values of tab_width. */
2068 it->tab_width = XINT (current_buffer->tab_width);
2069 if (it->tab_width <= 0 || it->tab_width > 1000)
2070 it->tab_width = 8;
2071
2072 /* Are lines in the display truncated? */
2073 it->truncate_lines_p
2074 = (base_face_id != DEFAULT_FACE_ID
2075 || XINT (it->w->hscroll)
2076 || (truncate_partial_width_windows
2077 && !WINDOW_FULL_WIDTH_P (it->w))
2078 || !NILP (current_buffer->truncate_lines));
2079
2080 /* Get dimensions of truncation and continuation glyphs. These are
b46952ae 2081 displayed as fringe bitmaps under X, so we don't need them for such
5f5c8ee5
GM
2082 frames. */
2083 if (!FRAME_WINDOW_P (it->f))
2084 {
2085 if (it->truncate_lines_p)
2086 {
2087 /* We will need the truncation glyph. */
2088 xassert (it->glyph_row == NULL);
2089 produce_special_glyphs (it, IT_TRUNCATION);
2090 it->truncation_pixel_width = it->pixel_width;
2091 }
2092 else
2093 {
2094 /* We will need the continuation glyph. */
2095 xassert (it->glyph_row == NULL);
2096 produce_special_glyphs (it, IT_CONTINUATION);
2097 it->continuation_pixel_width = it->pixel_width;
2098 }
2099
153c2160 2100 /* Reset these values to zero because the produce_special_glyphs
5f5c8ee5
GM
2101 above has changed them. */
2102 it->pixel_width = it->ascent = it->descent = 0;
312246d1 2103 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
2104 }
2105
2106 /* Set this after getting the dimensions of truncation and
2107 continuation glyphs, so that we don't produce glyphs when calling
2108 produce_special_glyphs, above. */
2109 it->glyph_row = row;
2110 it->area = TEXT_AREA;
2111
2112 /* Get the dimensions of the display area. The display area
2113 consists of the visible window area plus a horizontally scrolled
2114 part to the left of the window. All x-values are relative to the
2115 start of this total display area. */
2116 if (base_face_id != DEFAULT_FACE_ID)
2117 {
2118 /* Mode lines, menu bar in terminal frames. */
2119 it->first_visible_x = 0;
da8b7f4f 2120 it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
5f5c8ee5
GM
2121 }
2122 else
2123 {
2124 it->first_visible_x
da8b7f4f 2125 = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
5f5c8ee5
GM
2126 it->last_visible_x = (it->first_visible_x
2127 + window_box_width (w, TEXT_AREA));
2128
2129 /* If we truncate lines, leave room for the truncator glyph(s) at
2130 the right margin. Otherwise, leave room for the continuation
2131 glyph(s). Truncation and continuation glyphs are not inserted
2132 for window-based redisplay. */
2133 if (!FRAME_WINDOW_P (it->f))
2134 {
2135 if (it->truncate_lines_p)
2136 it->last_visible_x -= it->truncation_pixel_width;
2137 else
2138 it->last_visible_x -= it->continuation_pixel_width;
2139 }
2140
045dee35 2141 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
da8b7f4f 2142 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
2143 }
2144
2145 /* Leave room for a border glyph. */
2146 if (!FRAME_WINDOW_P (it->f)
2147 && !WINDOW_RIGHTMOST_P (it->w))
2148 it->last_visible_x -= 1;
2149
2150 it->last_visible_y = window_text_bottom_y (w);
2151
2152 /* For mode lines and alike, arrange for the first glyph having a
2153 left box line if the face specifies a box. */
2154 if (base_face_id != DEFAULT_FACE_ID)
2155 {
2156 struct face *face;
2311178e 2157
5f5c8ee5
GM
2158 it->face_id = base_face_id;
2159
2160 /* If we have a boxed mode line, make the first character appear
2161 with a left box line. */
2162 face = FACE_FROM_ID (it->f, base_face_id);
2163 if (face->box != FACE_NO_BOX)
2164 it->start_of_box_run_p = 1;
2165 }
2166
2167 /* If a buffer position was specified, set the iterator there,
2168 getting overlays and face properties from that position. */
3ebf0ea9 2169 if (charpos >= BUF_BEG (current_buffer))
5f5c8ee5
GM
2170 {
2171 it->end_charpos = ZV;
2172 it->face_id = -1;
2173 IT_CHARPOS (*it) = charpos;
2311178e 2174
5f5c8ee5 2175 /* Compute byte position if not specified. */
3ebf0ea9 2176 if (bytepos < charpos)
5f5c8ee5
GM
2177 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
2178 else
2179 IT_BYTEPOS (*it) = bytepos;
2180
2181 /* Compute faces etc. */
2182 reseat (it, it->current.pos, 1);
2183 }
2311178e 2184
5f5c8ee5
GM
2185 CHECK_IT (it);
2186}
2187
2188
2189/* Initialize IT for the display of window W with window start POS. */
2190
2191void
2192start_display (it, w, pos)
2193 struct it *it;
2194 struct window *w;
2195 struct text_pos pos;
2196{
5f5c8ee5 2197 struct glyph_row *row;
045dee35 2198 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
2199
2200 row = w->desired_matrix->rows + first_vpos;
2201 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
17fdcfc8
GM
2202
2203 if (!it->truncate_lines_p)
5f5c8ee5 2204 {
17fdcfc8
GM
2205 int start_at_line_beg_p;
2206 int first_y = it->current_y;
2311178e 2207
17fdcfc8
GM
2208 /* If window start is not at a line start, skip forward to POS to
2209 get the correct continuation lines width. */
2210 start_at_line_beg_p = (CHARPOS (pos) == BEGV
2211 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
2212 if (!start_at_line_beg_p)
5f5c8ee5 2213 {
0e47bbf7
RS
2214 int new_x;
2215
17fdcfc8
GM
2216 reseat_at_previous_visible_line_start (it);
2217 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
2218
0e47bbf7
RS
2219 new_x = it->current_x + it->pixel_width;
2220
17fdcfc8
GM
2221 /* If lines are continued, this line may end in the middle
2222 of a multi-glyph character (e.g. a control character
2223 displayed as \003, or in the middle of an overlay
2224 string). In this case move_it_to above will not have
2225 taken us to the start of the continuation line but to the
2226 end of the continued line. */
0e47bbf7
RS
2227 if (it->current_x > 0
2228 && !it->truncate_lines_p /* Lines are continued. */
2229 && (/* And glyph doesn't fit on the line. */
2230 new_x > it->last_visible_x
2231 /* Or it fits exactly and we're on a window
2232 system frame. */
2233 || (new_x == it->last_visible_x
2234 && FRAME_WINDOW_P (it->f))))
5f5c8ee5 2235 {
b28cb6ed
GM
2236 if (it->current.dpvec_index >= 0
2237 || it->current.overlay_string_index >= 0)
2238 {
cafafe0b 2239 set_iterator_to_next (it, 1);
b28cb6ed
GM
2240 move_it_in_display_line_to (it, -1, -1, 0);
2241 }
2311178e 2242
b28cb6ed 2243 it->continuation_lines_width += it->current_x;
5f5c8ee5 2244 }
b28cb6ed
GM
2245
2246 /* We're starting a new display line, not affected by the
2247 height of the continued line, so clear the appropriate
2248 fields in the iterator structure. */
2249 it->max_ascent = it->max_descent = 0;
2250 it->max_phys_ascent = it->max_phys_descent = 0;
2311178e 2251
17fdcfc8
GM
2252 it->current_y = first_y;
2253 it->vpos = 0;
2254 it->current_x = it->hpos = 0;
2255 }
5f5c8ee5
GM
2256 }
2257
2258#if 0 /* Don't assert the following because start_display is sometimes
2259 called intentionally with a window start that is not at a
2260 line start. Please leave this code in as a comment. */
2311178e 2261
5f5c8ee5
GM
2262 /* Window start should be on a line start, now. */
2263 xassert (it->continuation_lines_width
2264 || IT_CHARPOS (it) == BEGV
2265 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
2266#endif /* 0 */
2267}
2268
2269
4bde0ebb
GM
2270/* Return 1 if POS is a position in ellipses displayed for invisible
2271 text. W is the window we display, for text property lookup. */
5f5c8ee5 2272
4bde0ebb
GM
2273static int
2274in_ellipses_for_invisible_text_p (pos, w)
5f5c8ee5 2275 struct display_pos *pos;
4bde0ebb 2276 struct window *w;
5f5c8ee5 2277{
ac90c44f 2278 Lisp_Object prop, window;
4bde0ebb
GM
2279 int ellipses_p = 0;
2280 int charpos = CHARPOS (pos->pos);
2311178e 2281
ac90c44f
GM
2282 /* If POS specifies a position in a display vector, this might
2283 be for an ellipsis displayed for invisible text. We won't
2284 get the iterator set up for delivering that ellipsis unless
2285 we make sure that it gets aware of the invisible text. */
2286 if (pos->dpvec_index >= 0
2287 && pos->overlay_string_index < 0
2288 && CHARPOS (pos->string_pos) < 0
2289 && charpos > BEGV
2290 && (XSETWINDOW (window, w),
2291 prop = Fget_char_property (make_number (charpos),
2292 Qinvisible, window),
20fbd925 2293 !TEXT_PROP_MEANS_INVISIBLE (prop)))
ac90c44f
GM
2294 {
2295 prop = Fget_char_property (make_number (charpos - 1), Qinvisible,
2296 window);
8580a4e3 2297 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
4bde0ebb
GM
2298 }
2299
2300 return ellipses_p;
2301}
2302
2303
2304/* Initialize IT for stepping through current_buffer in window W,
2305 starting at position POS that includes overlay string and display
47d57b22
GM
2306 vector/ control character translation position information. Value
2307 is zero if there are overlay strings with newlines at POS. */
4bde0ebb 2308
47d57b22 2309static int
4bde0ebb
GM
2310init_from_display_pos (it, w, pos)
2311 struct it *it;
2312 struct window *w;
2313 struct display_pos *pos;
2314{
2315 int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
47d57b22 2316 int i, overlay_strings_with_newlines = 0;
2311178e 2317
4bde0ebb
GM
2318 /* If POS specifies a position in a display vector, this might
2319 be for an ellipsis displayed for invisible text. We won't
2320 get the iterator set up for delivering that ellipsis unless
2321 we make sure that it gets aware of the invisible text. */
2322 if (in_ellipses_for_invisible_text_p (pos, w))
2323 {
2324 --charpos;
2325 bytepos = 0;
ac90c44f 2326 }
2311178e 2327
5f5c8ee5
GM
2328 /* Keep in mind: the call to reseat in init_iterator skips invisible
2329 text, so we might end up at a position different from POS. This
2330 is only a problem when POS is a row start after a newline and an
2331 overlay starts there with an after-string, and the overlay has an
2332 invisible property. Since we don't skip invisible text in
2333 display_line and elsewhere immediately after consuming the
2334 newline before the row start, such a POS will not be in a string,
2335 but the call to init_iterator below will move us to the
2336 after-string. */
ac90c44f 2337 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
5f5c8ee5 2338
47d57b22 2339 for (i = 0; i < it->n_overlay_strings; ++i)
1e1e5daf 2340 {
50f80c2f
KR
2341 const char *s = SDATA (it->overlay_strings[i]);
2342 const char *e = s + SBYTES (it->overlay_strings[i]);
2311178e 2343
1e1e5daf
GM
2344 while (s < e && *s != '\n')
2345 ++s;
2346
2347 if (s < e)
2348 {
2349 overlay_strings_with_newlines = 1;
2350 break;
2351 }
2352 }
47d57b22 2353
75c5350a
GM
2354 /* If position is within an overlay string, set up IT to the right
2355 overlay string. */
5f5c8ee5
GM
2356 if (pos->overlay_string_index >= 0)
2357 {
2358 int relative_index;
75c5350a
GM
2359
2360 /* If the first overlay string happens to have a `display'
2361 property for an image, the iterator will be set up for that
2362 image, and we have to undo that setup first before we can
2363 correct the overlay string index. */
2364 if (it->method == next_element_from_image)
2365 pop_it (it);
2311178e 2366
5f5c8ee5
GM
2367 /* We already have the first chunk of overlay strings in
2368 IT->overlay_strings. Load more until the one for
2369 pos->overlay_string_index is in IT->overlay_strings. */
2370 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
2371 {
2372 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
2373 it->current.overlay_string_index = 0;
2374 while (n--)
2375 {
5a08cbaf 2376 load_overlay_strings (it, 0);
5f5c8ee5
GM
2377 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
2378 }
2379 }
2311178e 2380
5f5c8ee5
GM
2381 it->current.overlay_string_index = pos->overlay_string_index;
2382 relative_index = (it->current.overlay_string_index
2383 % OVERLAY_STRING_CHUNK_SIZE);
2384 it->string = it->overlay_strings[relative_index];
cafafe0b 2385 xassert (STRINGP (it->string));
5f5c8ee5
GM
2386 it->current.string_pos = pos->string_pos;
2387 it->method = next_element_from_string;
2388 }
2311178e 2389
1e1e5daf
GM
2390#if 0 /* This is bogus because POS not having an overlay string
2391 position does not mean it's after the string. Example: A
2392 line starting with a before-string and initialization of IT
2393 to the previous row's end position. */
2be8f184
GM
2394 else if (it->current.overlay_string_index >= 0)
2395 {
2396 /* If POS says we're already after an overlay string ending at
2397 POS, make sure to pop the iterator because it will be in
2398 front of that overlay string. When POS is ZV, we've thereby
2399 also ``processed'' overlay strings at ZV. */
aeb2b8fc
GM
2400 while (it->sp)
2401 pop_it (it);
2be8f184
GM
2402 it->current.overlay_string_index = -1;
2403 it->method = next_element_from_buffer;
2404 if (CHARPOS (pos->pos) == ZV)
2405 it->overlay_strings_at_end_processed_p = 1;
2406 }
1e1e5daf 2407#endif /* 0 */
2311178e 2408
2be8f184 2409 if (CHARPOS (pos->string_pos) >= 0)
5f5c8ee5
GM
2410 {
2411 /* Recorded position is not in an overlay string, but in another
2412 string. This can only be a string from a `display' property.
2413 IT should already be filled with that string. */
2414 it->current.string_pos = pos->string_pos;
2415 xassert (STRINGP (it->string));
2416 }
2417
ac90c44f
GM
2418 /* Restore position in display vector translations, control
2419 character translations or ellipses. */
5f5c8ee5
GM
2420 if (pos->dpvec_index >= 0)
2421 {
ac90c44f
GM
2422 if (it->dpvec == NULL)
2423 get_next_display_element (it);
5f5c8ee5
GM
2424 xassert (it->dpvec && it->current.dpvec_index == 0);
2425 it->current.dpvec_index = pos->dpvec_index;
2426 }
2311178e 2427
5f5c8ee5 2428 CHECK_IT (it);
47d57b22 2429 return !overlay_strings_with_newlines;
5f5c8ee5
GM
2430}
2431
2432
2433/* Initialize IT for stepping through current_buffer in window W
2434 starting at ROW->start. */
2435
2436static void
2437init_to_row_start (it, w, row)
2438 struct it *it;
2439 struct window *w;
2440 struct glyph_row *row;
2441{
2442 init_from_display_pos (it, w, &row->start);
2443 it->continuation_lines_width = row->continuation_lines_width;
2444 CHECK_IT (it);
2445}
2446
2311178e 2447
5f5c8ee5 2448/* Initialize IT for stepping through current_buffer in window W
47d57b22
GM
2449 starting in the line following ROW, i.e. starting at ROW->end.
2450 Value is zero if there are overlay strings with newlines at ROW's
2451 end position. */
5f5c8ee5 2452
47d57b22 2453static int
5f5c8ee5
GM
2454init_to_row_end (it, w, row)
2455 struct it *it;
2456 struct window *w;
2457 struct glyph_row *row;
2458{
47d57b22 2459 int success = 0;
2311178e 2460
47d57b22
GM
2461 if (init_from_display_pos (it, w, &row->end))
2462 {
2463 if (row->continued_p)
2464 it->continuation_lines_width
2465 = row->continuation_lines_width + row->pixel_width;
2466 CHECK_IT (it);
2467 success = 1;
2468 }
2311178e 2469
47d57b22 2470 return success;
5f5c8ee5
GM
2471}
2472
2473
2474
2475\f
2476/***********************************************************************
2477 Text properties
2478 ***********************************************************************/
2479
2480/* Called when IT reaches IT->stop_charpos. Handle text property and
2481 overlay changes. Set IT->stop_charpos to the next position where
2482 to stop. */
2483
2484static void
2485handle_stop (it)
2486 struct it *it;
2487{
2488 enum prop_handled handled;
2489 int handle_overlay_change_p = 1;
2490 struct props *p;
2491
2492 it->dpvec = NULL;
2493 it->current.dpvec_index = -1;
2494
2495 do
2496 {
2497 handled = HANDLED_NORMALLY;
2311178e 2498
5f5c8ee5
GM
2499 /* Call text property handlers. */
2500 for (p = it_props; p->handler; ++p)
2501 {
2502 handled = p->handler (it);
2970b9be 2503
5f5c8ee5
GM
2504 if (handled == HANDLED_RECOMPUTE_PROPS)
2505 break;
2506 else if (handled == HANDLED_RETURN)
2507 return;
2508 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
2509 handle_overlay_change_p = 0;
2510 }
2511
2512 if (handled != HANDLED_RECOMPUTE_PROPS)
2513 {
2514 /* Don't check for overlay strings below when set to deliver
2515 characters from a display vector. */
2516 if (it->method == next_element_from_display_vector)
2517 handle_overlay_change_p = 0;
2518
2519 /* Handle overlay changes. */
2520 if (handle_overlay_change_p)
2521 handled = handle_overlay_change (it);
2311178e 2522
5f5c8ee5
GM
2523 /* Determine where to stop next. */
2524 if (handled == HANDLED_NORMALLY)
2525 compute_stop_pos (it);
2526 }
2527 }
2528 while (handled == HANDLED_RECOMPUTE_PROPS);
2529}
2530
2531
2532/* Compute IT->stop_charpos from text property and overlay change
2533 information for IT's current position. */
2534
2535static void
2536compute_stop_pos (it)
2537 struct it *it;
2538{
2539 register INTERVAL iv, next_iv;
2540 Lisp_Object object, limit, position;
2541
2542 /* If nowhere else, stop at the end. */
2543 it->stop_charpos = it->end_charpos;
2311178e 2544
5f5c8ee5
GM
2545 if (STRINGP (it->string))
2546 {
2547 /* Strings are usually short, so don't limit the search for
2548 properties. */
2549 object = it->string;
2550 limit = Qnil;
ac90c44f 2551 position = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
2552 }
2553 else
2554 {
2555 int charpos;
2556
2557 /* If next overlay change is in front of the current stop pos
2558 (which is IT->end_charpos), stop there. Note: value of
2559 next_overlay_change is point-max if no overlay change
2560 follows. */
2561 charpos = next_overlay_change (IT_CHARPOS (*it));
2562 if (charpos < it->stop_charpos)
2563 it->stop_charpos = charpos;
2564
2565 /* If showing the region, we have to stop at the region
2566 start or end because the face might change there. */
2567 if (it->region_beg_charpos > 0)
2568 {
2569 if (IT_CHARPOS (*it) < it->region_beg_charpos)
2570 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
2571 else if (IT_CHARPOS (*it) < it->region_end_charpos)
2572 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
2573 }
2311178e 2574
5f5c8ee5
GM
2575 /* Set up variables for computing the stop position from text
2576 property changes. */
2577 XSETBUFFER (object, current_buffer);
ac90c44f
GM
2578 limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
2579 position = make_number (IT_CHARPOS (*it));
5f5c8ee5
GM
2580
2581 }
2582
2583 /* Get the interval containing IT's position. Value is a null
2584 interval if there isn't such an interval. */
2585 iv = validate_interval_range (object, &position, &position, 0);
2586 if (!NULL_INTERVAL_P (iv))
2587 {
2588 Lisp_Object values_here[LAST_PROP_IDX];
2589 struct props *p;
2590
2591 /* Get properties here. */
2592 for (p = it_props; p->handler; ++p)
2593 values_here[p->idx] = textget (iv->plist, *p->name);
2594
2595 /* Look for an interval following iv that has different
2596 properties. */
2597 for (next_iv = next_interval (iv);
2598 (!NULL_INTERVAL_P (next_iv)
2599 && (NILP (limit)
2600 || XFASTINT (limit) > next_iv->position));
2601 next_iv = next_interval (next_iv))
2602 {
2603 for (p = it_props; p->handler; ++p)
2604 {
2605 Lisp_Object new_value;
2606
2607 new_value = textget (next_iv->plist, *p->name);
2608 if (!EQ (values_here[p->idx], new_value))
2609 break;
2610 }
2311178e 2611
5f5c8ee5
GM
2612 if (p->handler)
2613 break;
2614 }
2615
2616 if (!NULL_INTERVAL_P (next_iv))
2617 {
2618 if (INTEGERP (limit)
2619 && next_iv->position >= XFASTINT (limit))
2620 /* No text property change up to limit. */
2621 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
2622 else
2623 /* Text properties change in next_iv. */
2624 it->stop_charpos = min (it->stop_charpos, next_iv->position);
2625 }
2626 }
2627
2628 xassert (STRINGP (it->string)
2629 || (it->stop_charpos >= BEGV
2630 && it->stop_charpos >= IT_CHARPOS (*it)));
2631}
2632
2633
2634/* Return the position of the next overlay change after POS in
2635 current_buffer. Value is point-max if no overlay change
2636 follows. This is like `next-overlay-change' but doesn't use
2637 xmalloc. */
2638
2639static int
2640next_overlay_change (pos)
2641 int pos;
2642{
2643 int noverlays;
2644 int endpos;
2645 Lisp_Object *overlays;
2646 int len;
2647 int i;
2648
2649 /* Get all overlays at the given position. */
2650 len = 10;
2651 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2652 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2653 if (noverlays > len)
2654 {
2655 len = noverlays;
2656 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2657 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2658 }
2659
2660 /* If any of these overlays ends before endpos,
2661 use its ending point instead. */
2662 for (i = 0; i < noverlays; ++i)
2663 {
2664 Lisp_Object oend;
2665 int oendpos;
2666
2667 oend = OVERLAY_END (overlays[i]);
2668 oendpos = OVERLAY_POSITION (oend);
2669 endpos = min (endpos, oendpos);
2670 }
2671
2672 return endpos;
2673}
2674
2675
2676\f
2677/***********************************************************************
2678 Fontification
2679 ***********************************************************************/
2680
2681/* Handle changes in the `fontified' property of the current buffer by
2682 calling hook functions from Qfontification_functions to fontify
2683 regions of text. */
2684
2685static enum prop_handled
2686handle_fontified_prop (it)
2687 struct it *it;
2688{
2689 Lisp_Object prop, pos;
2690 enum prop_handled handled = HANDLED_NORMALLY;
2691
2692 /* Get the value of the `fontified' property at IT's current buffer
2693 position. (The `fontified' property doesn't have a special
2694 meaning in strings.) If the value is nil, call functions from
2695 Qfontification_functions. */
2696 if (!STRINGP (it->string)
2697 && it->s == NULL
2698 && !NILP (Vfontification_functions)
085536c2 2699 && !NILP (Vrun_hooks)
5f5c8ee5
GM
2700 && (pos = make_number (IT_CHARPOS (*it)),
2701 prop = Fget_char_property (pos, Qfontified, Qnil),
2702 NILP (prop)))
2703 {
331379bf 2704 int count = SPECPDL_INDEX ();
085536c2
GM
2705 Lisp_Object val;
2706
2707 val = Vfontification_functions;
2708 specbind (Qfontification_functions, Qnil);
2311178e 2709
085536c2 2710 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
116d6f5c 2711 safe_call1 (val, pos);
085536c2
GM
2712 else
2713 {
2714 Lisp_Object globals, fn;
2715 struct gcpro gcpro1, gcpro2;
5f5c8ee5 2716
085536c2
GM
2717 globals = Qnil;
2718 GCPRO2 (val, globals);
2311178e 2719
085536c2
GM
2720 for (; CONSP (val); val = XCDR (val))
2721 {
2722 fn = XCAR (val);
2311178e 2723
085536c2
GM
2724 if (EQ (fn, Qt))
2725 {
2726 /* A value of t indicates this hook has a local
2727 binding; it means to run the global binding too.
2728 In a global value, t should not occur. If it
2729 does, we must ignore it to avoid an endless
2730 loop. */
2731 for (globals = Fdefault_value (Qfontification_functions);
2732 CONSP (globals);
2733 globals = XCDR (globals))
2734 {
2735 fn = XCAR (globals);
2736 if (!EQ (fn, Qt))
116d6f5c 2737 safe_call1 (fn, pos);
085536c2
GM
2738 }
2739 }
2740 else
116d6f5c 2741 safe_call1 (fn, pos);
085536c2
GM
2742 }
2743
2744 UNGCPRO;
2745 }
2746
2747 unbind_to (count, Qnil);
5f5c8ee5
GM
2748
2749 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
2750 something. This avoids an endless loop if they failed to
2751 fontify the text for which reason ever. */
2752 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
2753 handled = HANDLED_RECOMPUTE_PROPS;
2754 }
2755
2756 return handled;
2757}
2758
2759
2760\f
2761/***********************************************************************
2762 Faces
2763 ***********************************************************************/
2764
2765/* Set up iterator IT from face properties at its current position.
2766 Called from handle_stop. */
2767
2768static enum prop_handled
2769handle_face_prop (it)
2770 struct it *it;
2771{
2772 int new_face_id, next_stop;
2311178e 2773
5f5c8ee5
GM
2774 if (!STRINGP (it->string))
2775 {
2776 new_face_id
2777 = face_at_buffer_position (it->w,
2778 IT_CHARPOS (*it),
2779 it->region_beg_charpos,
2780 it->region_end_charpos,
2781 &next_stop,
2782 (IT_CHARPOS (*it)
2783 + TEXT_PROP_DISTANCE_LIMIT),
2784 0);
2311178e 2785
5f5c8ee5
GM
2786 /* Is this a start of a run of characters with box face?
2787 Caveat: this can be called for a freshly initialized
4b41cebb 2788 iterator; face_id is -1 in this case. We know that the new
5f5c8ee5
GM
2789 face will not change until limit, i.e. if the new face has a
2790 box, all characters up to limit will have one. But, as
2791 usual, we don't know whether limit is really the end. */
2792 if (new_face_id != it->face_id)
2793 {
2794 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2311178e 2795
5f5c8ee5
GM
2796 /* If new face has a box but old face has not, this is
2797 the start of a run of characters with box, i.e. it has
2798 a shadow on the left side. The value of face_id of the
2799 iterator will be -1 if this is the initial call that gets
2800 the face. In this case, we have to look in front of IT's
2801 position and see whether there is a face != new_face_id. */
2802 it->start_of_box_run_p
2803 = (new_face->box != FACE_NO_BOX
2804 && (it->face_id >= 0
2805 || IT_CHARPOS (*it) == BEG
2806 || new_face_id != face_before_it_pos (it)));
2807 it->face_box_p = new_face->box != FACE_NO_BOX;
2808 }
2809 }
2810 else
2811 {
06a12811
GM
2812 int base_face_id, bufpos;
2813
2814 if (it->current.overlay_string_index >= 0)
2815 bufpos = IT_CHARPOS (*it);
2816 else
2817 bufpos = 0;
2311178e 2818
06a12811
GM
2819 /* For strings from a buffer, i.e. overlay strings or strings
2820 from a `display' property, use the face at IT's current
2821 buffer position as the base face to merge with, so that
2822 overlay strings appear in the same face as surrounding
2823 text, unless they specify their own faces. */
2824 base_face_id = underlying_face_id (it);
2311178e 2825
06a12811
GM
2826 new_face_id = face_at_string_position (it->w,
2827 it->string,
2828 IT_STRING_CHARPOS (*it),
2829 bufpos,
2830 it->region_beg_charpos,
2831 it->region_end_charpos,
2832 &next_stop,
5de7c6f2 2833 base_face_id, 0);
2311178e 2834
5f5c8ee5
GM
2835#if 0 /* This shouldn't be neccessary. Let's check it. */
2836 /* If IT is used to display a mode line we would really like to
2837 use the mode line face instead of the frame's default face. */
2838 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
2839 && new_face_id == DEFAULT_FACE_ID)
96d2320f 2840 new_face_id = CURRENT_MODE_LINE_FACE_ID (it->w);
5f5c8ee5 2841#endif
2311178e 2842
5f5c8ee5
GM
2843 /* Is this a start of a run of characters with box? Caveat:
2844 this can be called for a freshly allocated iterator; face_id
2845 is -1 is this case. We know that the new face will not
2846 change until the next check pos, i.e. if the new face has a
2847 box, all characters up to that position will have a
2848 box. But, as usual, we don't know whether that position
2849 is really the end. */
2850 if (new_face_id != it->face_id)
2851 {
2852 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2853 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
2311178e 2854
5f5c8ee5
GM
2855 /* If new face has a box but old face hasn't, this is the
2856 start of a run of characters with box, i.e. it has a
2857 shadow on the left side. */
2858 it->start_of_box_run_p
2859 = new_face->box && (old_face == NULL || !old_face->box);
2860 it->face_box_p = new_face->box != FACE_NO_BOX;
2861 }
2862 }
2311178e 2863
5f5c8ee5 2864 it->face_id = new_face_id;
5f5c8ee5
GM
2865 return HANDLED_NORMALLY;
2866}
2867
2868
06a12811
GM
2869/* Return the ID of the face ``underlying'' IT's current position,
2870 which is in a string. If the iterator is associated with a
2871 buffer, return the face at IT's current buffer position.
2872 Otherwise, use the iterator's base_face_id. */
2873
2874static int
2875underlying_face_id (it)
2876 struct it *it;
2877{
2878 int face_id = it->base_face_id, i;
2879
2880 xassert (STRINGP (it->string));
2881
2882 for (i = it->sp - 1; i >= 0; --i)
2883 if (NILP (it->stack[i].string))
2884 face_id = it->stack[i].face_id;
2885
2886 return face_id;
2887}
2888
2889
5f5c8ee5
GM
2890/* Compute the face one character before or after the current position
2891 of IT. BEFORE_P non-zero means get the face in front of IT's
2892 position. Value is the id of the face. */
2893
2894static int
2895face_before_or_after_it_pos (it, before_p)
2896 struct it *it;
2897 int before_p;
2898{
2899 int face_id, limit;
2900 int next_check_charpos;
2901 struct text_pos pos;
2902
2903 xassert (it->s == NULL);
2311178e 2904
5f5c8ee5
GM
2905 if (STRINGP (it->string))
2906 {
06a12811 2907 int bufpos, base_face_id;
2311178e 2908
5f5c8ee5
GM
2909 /* No face change past the end of the string (for the case
2910 we are padding with spaces). No face change before the
2911 string start. */
2051c264 2912 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
5f5c8ee5
GM
2913 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
2914 return it->face_id;
2915
2916 /* Set pos to the position before or after IT's current position. */
2917 if (before_p)
2918 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
2919 else
260a86a0
KH
2920 /* For composition, we must check the character after the
2921 composition. */
2922 pos = (it->what == IT_COMPOSITION
2923 ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
2924 : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
5f5c8ee5 2925
06a12811
GM
2926 if (it->current.overlay_string_index >= 0)
2927 bufpos = IT_CHARPOS (*it);
2928 else
2929 bufpos = 0;
2930
2931 base_face_id = underlying_face_id (it);
2932
5f5c8ee5 2933 /* Get the face for ASCII, or unibyte. */
06a12811
GM
2934 face_id = face_at_string_position (it->w,
2935 it->string,
2936 CHARPOS (pos),
2937 bufpos,
2938 it->region_beg_charpos,
2939 it->region_end_charpos,
2940 &next_check_charpos,
5de7c6f2 2941 base_face_id, 0);
5f5c8ee5
GM
2942
2943 /* Correct the face for charsets different from ASCII. Do it
2944 for the multibyte case only. The face returned above is
2945 suitable for unibyte text if IT->string is unibyte. */
2946 if (STRING_MULTIBYTE (it->string))
2947 {
50f80c2f 2948 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos);
2051c264 2949 int rest = SBYTES (it->string) - BYTEPOS (pos);
980806b6
KH
2950 int c, len;
2951 struct face *face = FACE_FROM_ID (it->f, face_id);
2311178e 2952
4fdb80f2 2953 c = string_char_and_length (p, rest, &len);
980806b6 2954 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2955 }
2956 }
2957 else
2958 {
70851746
GM
2959 if ((IT_CHARPOS (*it) >= ZV && !before_p)
2960 || (IT_CHARPOS (*it) <= BEGV && before_p))
2961 return it->face_id;
2311178e 2962
5f5c8ee5
GM
2963 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
2964 pos = it->current.pos;
2311178e 2965
5f5c8ee5 2966 if (before_p)
c1005d06 2967 DEC_TEXT_POS (pos, it->multibyte_p);
5f5c8ee5 2968 else
260a86a0
KH
2969 {
2970 if (it->what == IT_COMPOSITION)
2971 /* For composition, we must check the position after the
2972 composition. */
2973 pos.charpos += it->cmp_len, pos.bytepos += it->len;
2974 else
c1005d06 2975 INC_TEXT_POS (pos, it->multibyte_p);
260a86a0 2976 }
2311178e 2977
5f5c8ee5
GM
2978 /* Determine face for CHARSET_ASCII, or unibyte. */
2979 face_id = face_at_buffer_position (it->w,
2980 CHARPOS (pos),
2981 it->region_beg_charpos,
2982 it->region_end_charpos,
2983 &next_check_charpos,
2984 limit, 0);
2985
2986 /* Correct the face for charsets different from ASCII. Do it
2987 for the multibyte case only. The face returned above is
2988 suitable for unibyte text if current_buffer is unibyte. */
2989 if (it->multibyte_p)
2990 {
1d1b6e6a 2991 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
980806b6
KH
2992 struct face *face = FACE_FROM_ID (it->f, face_id);
2993 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
2994 }
2995 }
2311178e 2996
5f5c8ee5
GM
2997 return face_id;
2998}
2999
3000
3001\f
3002/***********************************************************************
3003 Invisible text
3004 ***********************************************************************/
3005
3006/* Set up iterator IT from invisible properties at its current
3007 position. Called from handle_stop. */
3008
3009static enum prop_handled
3010handle_invisible_prop (it)
3011 struct it *it;
3012{
3013 enum prop_handled handled = HANDLED_NORMALLY;
3014
3015 if (STRINGP (it->string))
3016 {
3017 extern Lisp_Object Qinvisible;
3018 Lisp_Object prop, end_charpos, limit, charpos;
3019
3020 /* Get the value of the invisible text property at the
3021 current position. Value will be nil if there is no such
3022 property. */
ac90c44f 3023 charpos = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
3024 prop = Fget_text_property (charpos, Qinvisible, it->string);
3025
eadc0bf8
GM
3026 if (!NILP (prop)
3027 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
3028 {
3029 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 3030
5f5c8ee5
GM
3031 /* Get the position at which the next change of the
3032 invisible text property can be found in IT->string.
3033 Value will be nil if the property value is the same for
3034 all the rest of IT->string. */
2051c264 3035 XSETINT (limit, SCHARS (it->string));
5f5c8ee5 3036 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2051c264 3037 it->string, limit);
2311178e 3038
5f5c8ee5
GM
3039 /* Text at current position is invisible. The next
3040 change in the property is at position end_charpos.
3041 Move IT's current position to that position. */
3042 if (INTEGERP (end_charpos)
3043 && XFASTINT (end_charpos) < XFASTINT (limit))
3044 {
3045 struct text_pos old;
3046 old = it->current.string_pos;
3047 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
3048 compute_string_pos (&it->current.string_pos, old, it->string);
3049 }
3050 else
3051 {
3052 /* The rest of the string is invisible. If this is an
3053 overlay string, proceed with the next overlay string
3054 or whatever comes and return a character from there. */
3055 if (it->current.overlay_string_index >= 0)
3056 {
3057 next_overlay_string (it);
3058 /* Don't check for overlay strings when we just
3059 finished processing them. */
3060 handled = HANDLED_OVERLAY_STRING_CONSUMED;
3061 }
3062 else
3063 {
2051c264
GM
3064 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
3065 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5f5c8ee5
GM
3066 }
3067 }
3068 }
3069 }
3070 else
3071 {
8580a4e3 3072 int invis_p, newpos, next_stop, start_charpos;
5a08cbaf 3073 Lisp_Object pos, prop, overlay;
5f5c8ee5
GM
3074
3075 /* First of all, is there invisible text at this position? */
5a08cbaf 3076 start_charpos = IT_CHARPOS (*it);
ac90c44f 3077 pos = make_number (IT_CHARPOS (*it));
5a08cbaf
GM
3078 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
3079 &overlay);
8580a4e3
SM
3080 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
3081
5f5c8ee5 3082 /* If we are on invisible text, skip over it. */
8580a4e3 3083 if (invis_p && IT_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
3084 {
3085 /* Record whether we have to display an ellipsis for the
3086 invisible text. */
8580a4e3 3087 int display_ellipsis_p = invis_p == 2;
5f5c8ee5
GM
3088
3089 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 3090
5f5c8ee5
GM
3091 /* Loop skipping over invisible text. The loop is left at
3092 ZV or with IT on the first char being visible again. */
3093 do
3094 {
3095 /* Try to skip some invisible text. Return value is the
3096 position reached which can be equal to IT's position
3097 if there is nothing invisible here. This skips both
3098 over invisible text properties and overlays with
3099 invisible property. */
3100 newpos = skip_invisible (IT_CHARPOS (*it),
3101 &next_stop, ZV, it->window);
3102
3103 /* If we skipped nothing at all we weren't at invisible
3104 text in the first place. If everything to the end of
3105 the buffer was skipped, end the loop. */
3106 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
8580a4e3 3107 invis_p = 0;
5f5c8ee5
GM
3108 else
3109 {
3110 /* We skipped some characters but not necessarily
3111 all there are. Check if we ended up on visible
3112 text. Fget_char_property returns the property of
3113 the char before the given position, i.e. if we
8580a4e3 3114 get invis_p = 0, this means that the char at
5f5c8ee5 3115 newpos is visible. */
ac90c44f 3116 pos = make_number (newpos);
5f5c8ee5 3117 prop = Fget_char_property (pos, Qinvisible, it->window);
8580a4e3 3118 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
5f5c8ee5 3119 }
2311178e 3120
5f5c8ee5
GM
3121 /* If we ended up on invisible text, proceed to
3122 skip starting with next_stop. */
8580a4e3 3123 if (invis_p)
5f5c8ee5
GM
3124 IT_CHARPOS (*it) = next_stop;
3125 }
8580a4e3 3126 while (invis_p);
5a08cbaf 3127
5f5c8ee5
GM
3128 /* The position newpos is now either ZV or on visible text. */
3129 IT_CHARPOS (*it) = newpos;
3130 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2311178e 3131
5a08cbaf
GM
3132 /* If there are before-strings at the start of invisible
3133 text, and the text is invisible because of a text
3134 property, arrange to show before-strings because 20.x did
3135 it that way. (If the text is invisible because of an
3136 overlay property instead of a text property, this is
3137 already handled in the overlay code.) */
3138 if (NILP (overlay)
3139 && get_overlay_strings (it, start_charpos))
5f5c8ee5 3140 {
5a08cbaf
GM
3141 handled = HANDLED_RECOMPUTE_PROPS;
3142 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5f5c8ee5 3143 }
5a08cbaf
GM
3144 else if (display_ellipsis_p)
3145 setup_for_ellipsis (it);
5f5c8ee5
GM
3146 }
3147 }
3148
3149 return handled;
3150}
3151
3152
5a08cbaf
GM
3153/* Make iterator IT return `...' next. */
3154
3155static void
3156setup_for_ellipsis (it)
3157 struct it *it;
3158{
2311178e 3159 if (it->dp
5a08cbaf
GM
3160 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
3161 {
3162 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
3163 it->dpvec = v->contents;
3164 it->dpend = v->contents + v->size;
3165 }
2311178e 3166 else
5a08cbaf
GM
3167 {
3168 /* Default `...'. */
3169 it->dpvec = default_invis_vector;
3170 it->dpend = default_invis_vector + 3;
3171 }
2311178e 3172
5a08cbaf
GM
3173 /* The ellipsis display does not replace the display of the
3174 character at the new position. Indicate this by setting
3175 IT->dpvec_char_len to zero. */
3176 it->dpvec_char_len = 0;
2311178e 3177
5a08cbaf
GM
3178 it->current.dpvec_index = 0;
3179 it->method = next_element_from_display_vector;
3180}
3181
3182
5f5c8ee5
GM
3183\f
3184/***********************************************************************
3185 'display' property
3186 ***********************************************************************/
3187
3188/* Set up iterator IT from `display' property at its current position.
3189 Called from handle_stop. */
3190
3191static enum prop_handled
3192handle_display_prop (it)
3193 struct it *it;
3194{
3195 Lisp_Object prop, object;
3196 struct text_pos *position;
a61b7058 3197 int display_replaced_p = 0;
5f5c8ee5
GM
3198
3199 if (STRINGP (it->string))
3200 {
3201 object = it->string;
3202 position = &it->current.string_pos;
3203 }
3204 else
3205 {
221dd3e7 3206 object = it->w->buffer;
5f5c8ee5
GM
3207 position = &it->current.pos;
3208 }
3209
3210 /* Reset those iterator values set from display property values. */
3211 it->font_height = Qnil;
3212 it->space_width = Qnil;
3213 it->voffset = 0;
3214
3215 /* We don't support recursive `display' properties, i.e. string
3216 values that have a string `display' property, that have a string
3217 `display' property etc. */
3218 if (!it->string_from_display_prop_p)
3219 it->area = TEXT_AREA;
3220
3221 prop = Fget_char_property (make_number (position->charpos),
3222 Qdisplay, object);
3223 if (NILP (prop))
3224 return HANDLED_NORMALLY;
3225
f3751a65 3226 if (CONSP (prop)
12700f40
GM
3227 /* Simple properties. */
3228 && !EQ (XCAR (prop), Qimage)
3229 && !EQ (XCAR (prop), Qspace)
3230 && !EQ (XCAR (prop), Qwhen)
3231 && !EQ (XCAR (prop), Qspace_width)
3232 && !EQ (XCAR (prop), Qheight)
3233 && !EQ (XCAR (prop), Qraise)
3234 /* Marginal area specifications. */
3235 && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin))
3236 && !NILP (XCAR (prop)))
5f5c8ee5 3237 {
a61b7058 3238 for (; CONSP (prop); prop = XCDR (prop))
5f5c8ee5 3239 {
a61b7058
GM
3240 if (handle_single_display_prop (it, XCAR (prop), object,
3241 position, display_replaced_p))
3242 display_replaced_p = 1;
5f5c8ee5
GM
3243 }
3244 }
3245 else if (VECTORP (prop))
3246 {
3247 int i;
a61b7058
GM
3248 for (i = 0; i < ASIZE (prop); ++i)
3249 if (handle_single_display_prop (it, AREF (prop, i), object,
3250 position, display_replaced_p))
3251 display_replaced_p = 1;
5f5c8ee5
GM
3252 }
3253 else
3254 {
a61b7058
GM
3255 if (handle_single_display_prop (it, prop, object, position, 0))
3256 display_replaced_p = 1;
5f5c8ee5
GM
3257 }
3258
a61b7058 3259 return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
5f5c8ee5
GM
3260}
3261
3262
6c577098 3263/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
3264 at START_POS in OBJECT. */
3265
3266static struct text_pos
3267display_prop_end (it, object, start_pos)
3268 struct it *it;
3269 Lisp_Object object;
3270 struct text_pos start_pos;
3271{
3272 Lisp_Object end;
3273 struct text_pos end_pos;
5f5c8ee5 3274
016b5642
MB
3275 end = Fnext_single_char_property_change (make_number (CHARPOS (start_pos)),
3276 Qdisplay, object, Qnil);
6c577098
GM
3277 CHARPOS (end_pos) = XFASTINT (end);
3278 if (STRINGP (object))
5f5c8ee5
GM
3279 compute_string_pos (&end_pos, start_pos, it->string);
3280 else
6c577098 3281 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
3282
3283 return end_pos;
3284}
3285
3286
3287/* Set up IT from a single `display' sub-property value PROP. OBJECT
3288 is the object in which the `display' property was found. *POSITION
a61b7058
GM
3289 is the position at which it was found. DISPLAY_REPLACED_P non-zero
3290 means that we previously saw a display sub-property which already
3291 replaced text display with something else, for example an image;
3292 ignore such properties after the first one has been processed.
5f5c8ee5
GM
3293
3294 If PROP is a `space' or `image' sub-property, set *POSITION to the
3295 end position of the `display' property.
3296
4b41cebb 3297 Value is non-zero if something was found which replaces the display
a61b7058 3298 of buffer or string text. */
5f5c8ee5
GM
3299
3300static int
a61b7058
GM
3301handle_single_display_prop (it, prop, object, position,
3302 display_replaced_before_p)
5f5c8ee5
GM
3303 struct it *it;
3304 Lisp_Object prop;
3305 Lisp_Object object;
3306 struct text_pos *position;
a61b7058 3307 int display_replaced_before_p;
5f5c8ee5
GM
3308{
3309 Lisp_Object value;
a61b7058 3310 int replaces_text_display_p = 0;
5f5c8ee5
GM
3311 Lisp_Object form;
3312
d3acf96b 3313 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
4b41cebb 3314 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 3315 form = Qt;
d3acf96b 3316 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
3317 {
3318 prop = XCDR (prop);
3319 if (!CONSP (prop))
3320 return 0;
3321 form = XCAR (prop);
3322 prop = XCDR (prop);
5f5c8ee5
GM
3323 }
3324
3325 if (!NILP (form) && !EQ (form, Qt))
3326 {
331379bf 3327 int count = SPECPDL_INDEX ();
5f5c8ee5 3328 struct gcpro gcpro1;
5f5c8ee5 3329
b384d6f8
GM
3330 /* Bind `object' to the object having the `display' property, a
3331 buffer or string. Bind `position' to the position in the
3332 object where the property was found, and `buffer-position'
3333 to the current position in the buffer. */
3334 specbind (Qobject, object);
31ac723b
SM
3335 specbind (Qposition, make_number (CHARPOS (*position)));
3336 specbind (Qbuffer_position,
3337 make_number (STRINGP (object)
3338 ? IT_CHARPOS (*it) : CHARPOS (*position)));
b384d6f8 3339 GCPRO1 (form);
116d6f5c 3340 form = safe_eval (form);
b384d6f8
GM
3341 UNGCPRO;
3342 unbind_to (count, Qnil);
5f5c8ee5 3343 }
2311178e 3344
5f5c8ee5
GM
3345 if (NILP (form))
3346 return 0;
3347
3348 if (CONSP (prop)
3349 && EQ (XCAR (prop), Qheight)
3350 && CONSP (XCDR (prop)))
3351 {
e4093f38 3352 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
5f5c8ee5 3353 return 0;
2311178e 3354
5f5c8ee5
GM
3355 /* `(height HEIGHT)'. */
3356 it->font_height = XCAR (XCDR (prop));
3357 if (!NILP (it->font_height))
3358 {
3359 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3360 int new_height = -1;
3361
3362 if (CONSP (it->font_height)
3363 && (EQ (XCAR (it->font_height), Qplus)
3364 || EQ (XCAR (it->font_height), Qminus))
3365 && CONSP (XCDR (it->font_height))
3366 && INTEGERP (XCAR (XCDR (it->font_height))))
3367 {
3368 /* `(+ N)' or `(- N)' where N is an integer. */
3369 int steps = XINT (XCAR (XCDR (it->font_height)));
3370 if (EQ (XCAR (it->font_height), Qplus))
3371 steps = - steps;
3372 it->face_id = smaller_face (it->f, it->face_id, steps);
3373 }
0d8b31c0 3374 else if (FUNCTIONP (it->font_height))
5f5c8ee5
GM
3375 {
3376 /* Call function with current height as argument.
3377 Value is the new height. */
116d6f5c
GM
3378 Lisp_Object height;
3379 height = safe_call1 (it->font_height,
3380 face->lface[LFACE_HEIGHT_INDEX]);
5f5c8ee5
GM
3381 if (NUMBERP (height))
3382 new_height = XFLOATINT (height);
5f5c8ee5
GM
3383 }
3384 else if (NUMBERP (it->font_height))
3385 {
3386 /* Value is a multiple of the canonical char height. */
3387 struct face *face;
2311178e 3388
5f5c8ee5
GM
3389 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
3390 new_height = (XFLOATINT (it->font_height)
3391 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
3392 }
3393 else
3394 {
3395 /* Evaluate IT->font_height with `height' bound to the
3396 current specified height to get the new height. */
3397 Lisp_Object value;
331379bf 3398 int count = SPECPDL_INDEX ();
2311178e 3399
5f5c8ee5 3400 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
116d6f5c 3401 value = safe_eval (it->font_height);
5f5c8ee5 3402 unbind_to (count, Qnil);
2311178e 3403
5f5c8ee5
GM
3404 if (NUMBERP (value))
3405 new_height = XFLOATINT (value);
3406 }
2311178e 3407
5f5c8ee5
GM
3408 if (new_height > 0)
3409 it->face_id = face_with_height (it->f, it->face_id, new_height);
3410 }
3411 }
3412 else if (CONSP (prop)
3413 && EQ (XCAR (prop), Qspace_width)
3414 && CONSP (XCDR (prop)))
3415 {
3416 /* `(space_width WIDTH)'. */
e4093f38 3417 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 3418 return 0;
2311178e 3419
5f5c8ee5
GM
3420 value = XCAR (XCDR (prop));
3421 if (NUMBERP (value) && XFLOATINT (value) > 0)
3422 it->space_width = value;
3423 }
3424 else if (CONSP (prop)
3425 && EQ (XCAR (prop), Qraise)
3426 && CONSP (XCDR (prop)))
3427 {
5f5c8ee5 3428 /* `(raise FACTOR)'. */
e4093f38 3429 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 3430 return 0;
2311178e 3431
fb3842a8 3432#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
3433 value = XCAR (XCDR (prop));
3434 if (NUMBERP (value))
3435 {
3436 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3437 it->voffset = - (XFLOATINT (value)
1ab3e082 3438 * (FONT_HEIGHT (face->font)));
5f5c8ee5
GM
3439 }
3440#endif /* HAVE_WINDOW_SYSTEM */
3441 }
3442 else if (!it->string_from_display_prop_p)
3443 {
f3751a65 3444 /* `((margin left-margin) VALUE)' or `((margin right-margin)
4b41cebb 3445 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
3446 Lisp_Object location, value;
3447 struct text_pos start_pos;
3448 int valid_p;
3449
3450 /* Characters having this form of property are not displayed, so
3451 we have to find the end of the property. */
5f5c8ee5
GM
3452 start_pos = *position;
3453 *position = display_prop_end (it, object, start_pos);
15e26c76 3454 value = Qnil;
5f5c8ee5
GM
3455
3456 /* Let's stop at the new position and assume that all
3457 text properties change there. */
3458 it->stop_charpos = position->charpos;
3459
f3751a65
GM
3460 location = Qunbound;
3461 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 3462 {
f3751a65 3463 Lisp_Object tem;
2311178e 3464
5f5c8ee5 3465 value = XCDR (prop);
f3751a65
GM
3466 if (CONSP (value))
3467 value = XCAR (value);
3468
3469 tem = XCAR (prop);
3470 if (EQ (XCAR (tem), Qmargin)
3471 && (tem = XCDR (tem),
3472 tem = CONSP (tem) ? XCAR (tem) : Qnil,
3473 (NILP (tem)
3474 || EQ (tem, Qleft_margin)
3475 || EQ (tem, Qright_margin))))
3476 location = tem;
5f5c8ee5 3477 }
f3751a65
GM
3478
3479 if (EQ (location, Qunbound))
5f5c8ee5
GM
3480 {
3481 location = Qnil;
3482 value = prop;
3483 }
3484
3485#ifdef HAVE_WINDOW_SYSTEM
fb3842a8 3486 if (FRAME_TERMCAP_P (it->f))
5f5c8ee5
GM
3487 valid_p = STRINGP (value);
3488 else
3489 valid_p = (STRINGP (value)
3490 || (CONSP (value) && EQ (XCAR (value), Qspace))
3491 || valid_image_p (value));
3492#else /* not HAVE_WINDOW_SYSTEM */
3493 valid_p = STRINGP (value);
3494#endif /* not HAVE_WINDOW_SYSTEM */
2311178e 3495
5f5c8ee5
GM
3496 if ((EQ (location, Qleft_margin)
3497 || EQ (location, Qright_margin)
3498 || NILP (location))
a61b7058
GM
3499 && valid_p
3500 && !display_replaced_before_p)
5f5c8ee5 3501 {
a61b7058 3502 replaces_text_display_p = 1;
2311178e 3503
5f5c8ee5
GM
3504 /* Save current settings of IT so that we can restore them
3505 when we are finished with the glyph property value. */
3506 push_it (it);
2311178e 3507
5f5c8ee5
GM
3508 if (NILP (location))
3509 it->area = TEXT_AREA;
3510 else if (EQ (location, Qleft_margin))
3511 it->area = LEFT_MARGIN_AREA;
3512 else
3513 it->area = RIGHT_MARGIN_AREA;
2311178e 3514
5f5c8ee5
GM
3515 if (STRINGP (value))
3516 {
3517 it->string = value;
3518 it->multibyte_p = STRING_MULTIBYTE (it->string);
3519 it->current.overlay_string_index = -1;
3520 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2051c264 3521 it->end_charpos = it->string_nchars = SCHARS (it->string);
5f5c8ee5
GM
3522 it->method = next_element_from_string;
3523 it->stop_charpos = 0;
3524 it->string_from_display_prop_p = 1;
e187cf71
GM
3525 /* Say that we haven't consumed the characters with
3526 `display' property yet. The call to pop_it in
3527 set_iterator_to_next will clean this up. */
3528 *position = start_pos;
5f5c8ee5
GM
3529 }
3530 else if (CONSP (value) && EQ (XCAR (value), Qspace))
3531 {
3532 it->method = next_element_from_stretch;
3533 it->object = value;
3534 it->current.pos = it->position = start_pos;
3535 }
3536#ifdef HAVE_WINDOW_SYSTEM
3537 else
3538 {
3539 it->what = IT_IMAGE;
3540 it->image_id = lookup_image (it->f, value);
3541 it->position = start_pos;
3542 it->object = NILP (object) ? it->w->buffer : object;
3543 it->method = next_element_from_image;
2311178e 3544
02513cdd 3545 /* Say that we haven't consumed the characters with
5f5c8ee5
GM
3546 `display' property yet. The call to pop_it in
3547 set_iterator_to_next will clean this up. */
3548 *position = start_pos;
3549 }
3550#endif /* HAVE_WINDOW_SYSTEM */
3551 }
a21a3943
GM
3552 else
3553 /* Invalid property or property not supported. Restore
3554 the position to what it was before. */
3555 *position = start_pos;
5f5c8ee5
GM
3556 }
3557
a61b7058 3558 return replaces_text_display_p;
5f5c8ee5
GM
3559}
3560
3561
06568bbf
GM
3562/* Check if PROP is a display sub-property value whose text should be
3563 treated as intangible. */
3564
3565static int
3566single_display_prop_intangible_p (prop)
3567 Lisp_Object prop;
3568{
3569 /* Skip over `when FORM'. */
3570 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3571 {
3572 prop = XCDR (prop);
3573 if (!CONSP (prop))
3574 return 0;
3575 prop = XCDR (prop);
3576 }
3577
959bc044
SM
3578 if (STRINGP (prop))
3579 return 1;
3580
06568bbf
GM
3581 if (!CONSP (prop))
3582 return 0;
3583
3584 /* Skip over `margin LOCATION'. If LOCATION is in the margins,
3585 we don't need to treat text as intangible. */
3586 if (EQ (XCAR (prop), Qmargin))
3587 {
3588 prop = XCDR (prop);
3589 if (!CONSP (prop))
3590 return 0;
3591
3592 prop = XCDR (prop);
3593 if (!CONSP (prop)
3594 || EQ (XCAR (prop), Qleft_margin)
3595 || EQ (XCAR (prop), Qright_margin))
3596 return 0;
3597 }
2311178e 3598
6cd83a9a
SM
3599 return (CONSP (prop)
3600 && (EQ (XCAR (prop), Qimage)
3601 || EQ (XCAR (prop), Qspace)));
06568bbf
GM
3602}
3603
3604
3605/* Check if PROP is a display property value whose text should be
3606 treated as intangible. */
3607
3608int
3609display_prop_intangible_p (prop)
3610 Lisp_Object prop;
3611{
3612 if (CONSP (prop)
3613 && CONSP (XCAR (prop))
3614 && !EQ (Qmargin, XCAR (XCAR (prop))))
3615 {
3616 /* A list of sub-properties. */
3617 while (CONSP (prop))
3618 {
3619 if (single_display_prop_intangible_p (XCAR (prop)))
3620 return 1;
3621 prop = XCDR (prop);
3622 }
3623 }
3624 else if (VECTORP (prop))
3625 {
3626 /* A vector of sub-properties. */
3627 int i;
a61b7058
GM
3628 for (i = 0; i < ASIZE (prop); ++i)
3629 if (single_display_prop_intangible_p (AREF (prop, i)))
06568bbf
GM
3630 return 1;
3631 }
3632 else
3633 return single_display_prop_intangible_p (prop);
3634
3635 return 0;
3636}
3637
74bd6d65
GM
3638
3639/* Return 1 if PROP is a display sub-property value containing STRING. */
3640
3641static int
3642single_display_prop_string_p (prop, string)
3643 Lisp_Object prop, string;
3644{
74bd6d65
GM
3645 if (EQ (string, prop))
3646 return 1;
2311178e 3647
74bd6d65
GM
3648 /* Skip over `when FORM'. */
3649 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3650 {
3651 prop = XCDR (prop);
3652 if (!CONSP (prop))
3653 return 0;
3654 prop = XCDR (prop);
3655 }
3656
3657 if (CONSP (prop))
3658 /* Skip over `margin LOCATION'. */
3659 if (EQ (XCAR (prop), Qmargin))
3660 {
3661 prop = XCDR (prop);
3662 if (!CONSP (prop))
3663 return 0;
3664
3665 prop = XCDR (prop);
3666 if (!CONSP (prop))
3667 return 0;
3668 }
2311178e 3669
74bd6d65
GM
3670 return CONSP (prop) && EQ (XCAR (prop), string);
3671}
3672
3673
3674/* Return 1 if STRING appears in the `display' property PROP. */
3675
3676static int
3677display_prop_string_p (prop, string)
3678 Lisp_Object prop, string;
3679{
74bd6d65
GM
3680 if (CONSP (prop)
3681 && CONSP (XCAR (prop))
3682 && !EQ (Qmargin, XCAR (XCAR (prop))))
3683 {
3684 /* A list of sub-properties. */
3685 while (CONSP (prop))
3686 {
3687 if (single_display_prop_string_p (XCAR (prop), string))
3688 return 1;
3689 prop = XCDR (prop);
3690 }
3691 }
3692 else if (VECTORP (prop))
3693 {
3694 /* A vector of sub-properties. */
3695 int i;
3696 for (i = 0; i < ASIZE (prop); ++i)
3697 if (single_display_prop_string_p (AREF (prop, i), string))
3698 return 1;
3699 }
3700 else
3701 return single_display_prop_string_p (prop, string);
3702
3703 return 0;
3704}
3705
3706
3707/* Determine from which buffer position in W's buffer STRING comes
3708 from. AROUND_CHARPOS is an approximate position where it could
3709 be from. Value is the buffer position or 0 if it couldn't be
3710 determined.
3711
3712 W's buffer must be current.
3713
3714 This function is necessary because we don't record buffer positions
3715 in glyphs generated from strings (to keep struct glyph small).
3716 This function may only use code that doesn't eval because it is
3717 called asynchronously from note_mouse_highlight. */
3718
3719int
3720string_buffer_position (w, string, around_charpos)
3721 struct window *w;
3722 Lisp_Object string;
3723 int around_charpos;
3724{
74bd6d65
GM
3725 Lisp_Object limit, prop, pos;
3726 const int MAX_DISTANCE = 1000;
3727 int found = 0;
3728
d8731202 3729 pos = make_number (around_charpos);
74bd6d65
GM
3730 limit = make_number (min (XINT (pos) + MAX_DISTANCE, ZV));
3731 while (!found && !EQ (pos, limit))
3732 {
3733 prop = Fget_char_property (pos, Qdisplay, Qnil);
3734 if (!NILP (prop) && display_prop_string_p (prop, string))
3735 found = 1;
3736 else
134d9283 3737 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil, limit);
74bd6d65
GM
3738 }
3739
3740 if (!found)
3741 {
d8731202 3742 pos = make_number (around_charpos);
74bd6d65
GM
3743 limit = make_number (max (XINT (pos) - MAX_DISTANCE, BEGV));
3744 while (!found && !EQ (pos, limit))
3745 {
3746 prop = Fget_char_property (pos, Qdisplay, Qnil);
3747 if (!NILP (prop) && display_prop_string_p (prop, string))
3748 found = 1;
3749 else
134d9283
GM
3750 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
3751 limit);
74bd6d65
GM
3752 }
3753 }
3754
3755 return found ? XINT (pos) : 0;
3756}
3757
3758
5f5c8ee5 3759\f
260a86a0
KH
3760/***********************************************************************
3761 `composition' property
3762 ***********************************************************************/
3763
3764/* Set up iterator IT from `composition' property at its current
3765 position. Called from handle_stop. */
3766
3767static enum prop_handled
3768handle_composition_prop (it)
3769 struct it *it;
3770{
3771 Lisp_Object prop, string;
3772 int pos, pos_byte, end;
3773 enum prop_handled handled = HANDLED_NORMALLY;
3774
3775 if (STRINGP (it->string))
3776 {
3777 pos = IT_STRING_CHARPOS (*it);
3778 pos_byte = IT_STRING_BYTEPOS (*it);
3779 string = it->string;
3780 }
3781 else
3782 {
3783 pos = IT_CHARPOS (*it);
3784 pos_byte = IT_BYTEPOS (*it);
3785 string = Qnil;
3786 }
3787
3788 /* If there's a valid composition and point is not inside of the
3789 composition (in the case that the composition is from the current
3790 buffer), draw a glyph composed from the composition components. */
3791 if (find_composition (pos, -1, &pos, &end, &prop, string)
3792 && COMPOSITION_VALID_P (pos, end, prop)
3793 && (STRINGP (it->string) || (PT <= pos || PT >= end)))
3794 {
3795 int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
3796
3797 if (id >= 0)
3798 {
3799 it->method = next_element_from_composition;
3800 it->cmp_id = id;
3801 it->cmp_len = COMPOSITION_LENGTH (prop);
3802 /* For a terminal, draw only the first character of the
3803 components. */
3804 it->c = COMPOSITION_GLYPH (composition_table[id], 0);
3805 it->len = (STRINGP (it->string)
3806 ? string_char_to_byte (it->string, end)
3807 : CHAR_TO_BYTE (end)) - pos_byte;
3808 it->stop_charpos = end;
3809 handled = HANDLED_RETURN;
3810 }
3811 }
3812
3813 return handled;
3814}
3815
3816
3817\f
5f5c8ee5
GM
3818/***********************************************************************
3819 Overlay strings
3820 ***********************************************************************/
3821
3822/* The following structure is used to record overlay strings for
3823 later sorting in load_overlay_strings. */
3824
3825struct overlay_entry
3826{
2970b9be 3827 Lisp_Object overlay;
5f5c8ee5
GM
3828 Lisp_Object string;
3829 int priority;
3830 int after_string_p;
3831};
3832
3833
3834/* Set up iterator IT from overlay strings at its current position.
3835 Called from handle_stop. */
3836
3837static enum prop_handled
3838handle_overlay_change (it)
3839 struct it *it;
3840{
5a08cbaf 3841 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
2970b9be 3842 return HANDLED_RECOMPUTE_PROPS;
5f5c8ee5 3843 else
2970b9be 3844 return HANDLED_NORMALLY;
5f5c8ee5
GM
3845}
3846
3847
3848/* Set up the next overlay string for delivery by IT, if there is an
3849 overlay string to deliver. Called by set_iterator_to_next when the
3850 end of the current overlay string is reached. If there are more
3851 overlay strings to display, IT->string and
3852 IT->current.overlay_string_index are set appropriately here.
3853 Otherwise IT->string is set to nil. */
2311178e 3854
5f5c8ee5
GM
3855static void
3856next_overlay_string (it)
3857 struct it *it;
3858{
3859 ++it->current.overlay_string_index;
3860 if (it->current.overlay_string_index == it->n_overlay_strings)
3861 {
3862 /* No more overlay strings. Restore IT's settings to what
3863 they were before overlay strings were processed, and
3864 continue to deliver from current_buffer. */
5a08cbaf 3865 int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
2311178e 3866
5f5c8ee5
GM
3867 pop_it (it);
3868 xassert (it->stop_charpos >= BEGV
3869 && it->stop_charpos <= it->end_charpos);
3870 it->string = Qnil;
3871 it->current.overlay_string_index = -1;
3872 SET_TEXT_POS (it->current.string_pos, -1, -1);
3873 it->n_overlay_strings = 0;
3874 it->method = next_element_from_buffer;
2970b9be
GM
3875
3876 /* If we're at the end of the buffer, record that we have
3877 processed the overlay strings there already, so that
3878 next_element_from_buffer doesn't try it again. */
3879 if (IT_CHARPOS (*it) >= it->end_charpos)
3880 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf
GM
3881
3882 /* If we have to display `...' for invisible text, set
3883 the iterator up for that. */
3884 if (display_ellipsis_p)
3885 setup_for_ellipsis (it);
5f5c8ee5
GM
3886 }
3887 else
3888 {
3889 /* There are more overlay strings to process. If
3890 IT->current.overlay_string_index has advanced to a position
3891 where we must load IT->overlay_strings with more strings, do
3892 it. */
3893 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2311178e 3894
5f5c8ee5 3895 if (it->current.overlay_string_index && i == 0)
5a08cbaf 3896 load_overlay_strings (it, 0);
5f5c8ee5
GM
3897
3898 /* Initialize IT to deliver display elements from the overlay
3899 string. */
3900 it->string = it->overlay_strings[i];
3901 it->multibyte_p = STRING_MULTIBYTE (it->string);
3902 SET_TEXT_POS (it->current.string_pos, 0, 0);
3903 it->method = next_element_from_string;
3904 it->stop_charpos = 0;
3905 }
2311178e 3906
5f5c8ee5
GM
3907 CHECK_IT (it);
3908}
3909
3910
3911/* Compare two overlay_entry structures E1 and E2. Used as a
3912 comparison function for qsort in load_overlay_strings. Overlay
3913 strings for the same position are sorted so that
3914
2970b9be
GM
3915 1. All after-strings come in front of before-strings, except
3916 when they come from the same overlay.
2311178e 3917
5f5c8ee5
GM
3918 2. Within after-strings, strings are sorted so that overlay strings
3919 from overlays with higher priorities come first.
3920
3921 2. Within before-strings, strings are sorted so that overlay
3922 strings from overlays with higher priorities come last.
3923
3924 Value is analogous to strcmp. */
3925
2311178e 3926
5f5c8ee5
GM
3927static int
3928compare_overlay_entries (e1, e2)
3929 void *e1, *e2;
3930{
3931 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
3932 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
3933 int result;
3934
3935 if (entry1->after_string_p != entry2->after_string_p)
2970b9be
GM
3936 {
3937 /* Let after-strings appear in front of before-strings if
3938 they come from different overlays. */
3939 if (EQ (entry1->overlay, entry2->overlay))
3940 result = entry1->after_string_p ? 1 : -1;
3941 else
3942 result = entry1->after_string_p ? -1 : 1;
3943 }
5f5c8ee5
GM
3944 else if (entry1->after_string_p)
3945 /* After-strings sorted in order of decreasing priority. */
3946 result = entry2->priority - entry1->priority;
3947 else
3948 /* Before-strings sorted in order of increasing priority. */
3949 result = entry1->priority - entry2->priority;
3950
3951 return result;
3952}
3953
3954
3955/* Load the vector IT->overlay_strings with overlay strings from IT's
5a08cbaf
GM
3956 current buffer position, or from CHARPOS if that is > 0. Set
3957 IT->n_overlays to the total number of overlay strings found.
5f5c8ee5
GM
3958
3959 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
3960 a time. On entry into load_overlay_strings,
3961 IT->current.overlay_string_index gives the number of overlay
3962 strings that have already been loaded by previous calls to this
3963 function.
3964
2970b9be
GM
3965 IT->add_overlay_start contains an additional overlay start
3966 position to consider for taking overlay strings from, if non-zero.
3967 This position comes into play when the overlay has an `invisible'
3968 property, and both before and after-strings. When we've skipped to
3969 the end of the overlay, because of its `invisible' property, we
3970 nevertheless want its before-string to appear.
3971 IT->add_overlay_start will contain the overlay start position
3972 in this case.
3973
5f5c8ee5
GM
3974 Overlay strings are sorted so that after-string strings come in
3975 front of before-string strings. Within before and after-strings,
3976 strings are sorted by overlay priority. See also function
3977 compare_overlay_entries. */
2311178e 3978
5f5c8ee5 3979static void
5a08cbaf 3980load_overlay_strings (it, charpos)
5f5c8ee5 3981 struct it *it;
5a08cbaf 3982 int charpos;
5f5c8ee5
GM
3983{
3984 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
b7253a3e
SM
3985 Lisp_Object overlay, window, str, invisible;
3986 struct Lisp_Overlay *ov;
5f5c8ee5
GM
3987 int start, end;
3988 int size = 20;
cafafe0b 3989 int n = 0, i, j, invis_p;
5f5c8ee5
GM
3990 struct overlay_entry *entries
3991 = (struct overlay_entry *) alloca (size * sizeof *entries);
5a08cbaf
GM
3992
3993 if (charpos <= 0)
3994 charpos = IT_CHARPOS (*it);
5f5c8ee5
GM
3995
3996 /* Append the overlay string STRING of overlay OVERLAY to vector
3997 `entries' which has size `size' and currently contains `n'
3998 elements. AFTER_P non-zero means STRING is an after-string of
3999 OVERLAY. */
4000#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
4001 do \
4002 { \
4003 Lisp_Object priority; \
4004 \
4005 if (n == size) \
4006 { \
4007 int new_size = 2 * size; \
4008 struct overlay_entry *old = entries; \
4009 entries = \
4010 (struct overlay_entry *) alloca (new_size \
4011 * sizeof *entries); \
4012 bcopy (old, entries, size * sizeof *entries); \
4013 size = new_size; \
4014 } \
4015 \
4016 entries[n].string = (STRING); \
2970b9be 4017 entries[n].overlay = (OVERLAY); \
5f5c8ee5 4018 priority = Foverlay_get ((OVERLAY), Qpriority); \
2970b9be 4019 entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0; \
5f5c8ee5
GM
4020 entries[n].after_string_p = (AFTER_P); \
4021 ++n; \
4022 } \
4023 while (0)
4024
4025 /* Process overlay before the overlay center. */
b7253a3e 4026 for (ov = current_buffer->overlays_before; ov; ov = ov->next)
5f5c8ee5 4027 {
b7253a3e 4028 XSETMISC (overlay, ov);
5f5c8ee5
GM
4029 xassert (OVERLAYP (overlay));
4030 start = OVERLAY_POSITION (OVERLAY_START (overlay));
4031 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2311178e 4032
cafafe0b 4033 if (end < charpos)
5f5c8ee5
GM
4034 break;
4035
4036 /* Skip this overlay if it doesn't start or end at IT's current
4037 position. */
cafafe0b 4038 if (end != charpos && start != charpos)
5f5c8ee5 4039 continue;
2311178e 4040
5f5c8ee5
GM
4041 /* Skip this overlay if it doesn't apply to IT->w. */
4042 window = Foverlay_get (overlay, Qwindow);
4043 if (WINDOWP (window) && XWINDOW (window) != it->w)
4044 continue;
4045
cafafe0b
GM
4046 /* If the text ``under'' the overlay is invisible, both before-
4047 and after-strings from this overlay are visible; start and
4048 end position are indistinguishable. */
4049 invisible = Foverlay_get (overlay, Qinvisible);
4050 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
4051
5f5c8ee5 4052 /* If overlay has a non-empty before-string, record it. */
cafafe0b 4053 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 4054 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 4055 && SCHARS (str))
5f5c8ee5 4056 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 4057
5f5c8ee5 4058 /* If overlay has a non-empty after-string, record it. */
cafafe0b 4059 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 4060 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 4061 && SCHARS (str))
5f5c8ee5
GM
4062 RECORD_OVERLAY_STRING (overlay, str, 1);
4063 }
2311178e 4064
5f5c8ee5 4065 /* Process overlays after the overlay center. */
b7253a3e 4066 for (ov = current_buffer->overlays_after; ov; ov = ov->next)
5f5c8ee5 4067 {
b7253a3e 4068 XSETMISC (overlay, ov);
5f5c8ee5
GM
4069 xassert (OVERLAYP (overlay));
4070 start = OVERLAY_POSITION (OVERLAY_START (overlay));
4071 end = OVERLAY_POSITION (OVERLAY_END (overlay));
4072
cafafe0b 4073 if (start > charpos)
5f5c8ee5 4074 break;
2311178e 4075
5f5c8ee5
GM
4076 /* Skip this overlay if it doesn't start or end at IT's current
4077 position. */
cafafe0b 4078 if (end != charpos && start != charpos)
5f5c8ee5
GM
4079 continue;
4080
4081 /* Skip this overlay if it doesn't apply to IT->w. */
4082 window = Foverlay_get (overlay, Qwindow);
4083 if (WINDOWP (window) && XWINDOW (window) != it->w)
4084 continue;
2311178e 4085
cafafe0b
GM
4086 /* If the text ``under'' the overlay is invisible, it has a zero
4087 dimension, and both before- and after-strings apply. */
4088 invisible = Foverlay_get (overlay, Qinvisible);
4089 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
4090
5f5c8ee5 4091 /* If overlay has a non-empty before-string, record it. */
cafafe0b 4092 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 4093 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 4094 && SCHARS (str))
5f5c8ee5 4095 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 4096
5f5c8ee5 4097 /* If overlay has a non-empty after-string, record it. */
cafafe0b 4098 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 4099 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 4100 && SCHARS (str))
5f5c8ee5
GM
4101 RECORD_OVERLAY_STRING (overlay, str, 1);
4102 }
4103
4104#undef RECORD_OVERLAY_STRING
2311178e 4105
5f5c8ee5 4106 /* Sort entries. */
cafafe0b 4107 if (n > 1)
2970b9be 4108 qsort (entries, n, sizeof *entries, compare_overlay_entries);
5f5c8ee5
GM
4109
4110 /* Record the total number of strings to process. */
4111 it->n_overlay_strings = n;
4112
4113 /* IT->current.overlay_string_index is the number of overlay strings
4114 that have already been consumed by IT. Copy some of the
4115 remaining overlay strings to IT->overlay_strings. */
4116 i = 0;
4117 j = it->current.overlay_string_index;
4118 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
4119 it->overlay_strings[i++] = entries[j++].string;
2970b9be 4120
5f5c8ee5
GM
4121 CHECK_IT (it);
4122}
4123
4124
4125/* Get the first chunk of overlay strings at IT's current buffer
5a08cbaf
GM
4126 position, or at CHARPOS if that is > 0. Value is non-zero if at
4127 least one overlay string was found. */
5f5c8ee5
GM
4128
4129static int
5a08cbaf 4130get_overlay_strings (it, charpos)
5f5c8ee5 4131 struct it *it;
5a08cbaf 4132 int charpos;
5f5c8ee5
GM
4133{
4134 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
4135 process. This fills IT->overlay_strings with strings, and sets
4136 IT->n_overlay_strings to the total number of strings to process.
4137 IT->pos.overlay_string_index has to be set temporarily to zero
4138 because load_overlay_strings needs this; it must be set to -1
4139 when no overlay strings are found because a zero value would
4140 indicate a position in the first overlay string. */
4141 it->current.overlay_string_index = 0;
5a08cbaf 4142 load_overlay_strings (it, charpos);
5f5c8ee5
GM
4143
4144 /* If we found overlay strings, set up IT to deliver display
4145 elements from the first one. Otherwise set up IT to deliver
4146 from current_buffer. */
4147 if (it->n_overlay_strings)
4148 {
4149 /* Make sure we know settings in current_buffer, so that we can
4150 restore meaningful values when we're done with the overlay
4151 strings. */
4152 compute_stop_pos (it);
4153 xassert (it->face_id >= 0);
2311178e 4154
5f5c8ee5
GM
4155 /* Save IT's settings. They are restored after all overlay
4156 strings have been processed. */
4157 xassert (it->sp == 0);
4158 push_it (it);
4159
4160 /* Set up IT to deliver display elements from the first overlay
4161 string. */
4162 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
5f5c8ee5 4163 it->string = it->overlay_strings[0];
b2046df8 4164 it->stop_charpos = 0;
5f5c8ee5 4165 xassert (STRINGP (it->string));
2051c264 4166 it->end_charpos = SCHARS (it->string);
d5db4077 4167 it->multibyte_p = STRING_MULTIBYTE (it->string);
5f5c8ee5
GM
4168 it->method = next_element_from_string;
4169 }
4170 else
4171 {
4172 it->string = Qnil;
4173 it->current.overlay_string_index = -1;
4174 it->method = next_element_from_buffer;
4175 }
4176
4177 CHECK_IT (it);
4178
4179 /* Value is non-zero if we found at least one overlay string. */
4180 return STRINGP (it->string);
4181}
4182
4183
4184\f
4185/***********************************************************************
4186 Saving and restoring state
4187 ***********************************************************************/
4188
4189/* Save current settings of IT on IT->stack. Called, for example,
4190 before setting up IT for an overlay string, to be able to restore
4191 IT's settings to what they were after the overlay string has been
4192 processed. */
4193
4194static void
4195push_it (it)
4196 struct it *it;
4197{
4198 struct iterator_stack_entry *p;
2311178e 4199
5f5c8ee5
GM
4200 xassert (it->sp < 2);
4201 p = it->stack + it->sp;
4202
4203 p->stop_charpos = it->stop_charpos;
4204 xassert (it->face_id >= 0);
4205 p->face_id = it->face_id;
4206 p->string = it->string;
4207 p->pos = it->current;
4208 p->end_charpos = it->end_charpos;
4209 p->string_nchars = it->string_nchars;
4210 p->area = it->area;
4211 p->multibyte_p = it->multibyte_p;
4212 p->space_width = it->space_width;
4213 p->font_height = it->font_height;
4214 p->voffset = it->voffset;
4215 p->string_from_display_prop_p = it->string_from_display_prop_p;
5a08cbaf 4216 p->display_ellipsis_p = 0;
5f5c8ee5
GM
4217 ++it->sp;
4218}
4219
4220
4221/* Restore IT's settings from IT->stack. Called, for example, when no
4222 more overlay strings must be processed, and we return to delivering
4223 display elements from a buffer, or when the end of a string from a
4224 `display' property is reached and we return to delivering display
4225 elements from an overlay string, or from a buffer. */
4226
4227static void
4228pop_it (it)
4229 struct it *it;
4230{
4231 struct iterator_stack_entry *p;
2311178e 4232
5f5c8ee5
GM
4233 xassert (it->sp > 0);
4234 --it->sp;
4235 p = it->stack + it->sp;
4236 it->stop_charpos = p->stop_charpos;
4237 it->face_id = p->face_id;
4238 it->string = p->string;
4239 it->current = p->pos;
4240 it->end_charpos = p->end_charpos;
4241 it->string_nchars = p->string_nchars;
4242 it->area = p->area;
4243 it->multibyte_p = p->multibyte_p;
4244 it->space_width = p->space_width;
4245 it->font_height = p->font_height;
4246 it->voffset = p->voffset;
4247 it->string_from_display_prop_p = p->string_from_display_prop_p;
4248}
4249
4250
4251\f
4252/***********************************************************************
4253 Moving over lines
4254 ***********************************************************************/
4255
4256/* Set IT's current position to the previous line start. */
4257
4258static void
4259back_to_previous_line_start (it)
4260 struct it *it;
4261{
4262 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
4263 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
4264}
4265
4266
cafafe0b 4267/* Move IT to the next line start.
2311178e 4268
cafafe0b
GM
4269 Value is non-zero if a newline was found. Set *SKIPPED_P to 1 if
4270 we skipped over part of the text (as opposed to moving the iterator
4271 continuously over the text). Otherwise, don't change the value
4272 of *SKIPPED_P.
2311178e 4273
cafafe0b
GM
4274 Newlines may come from buffer text, overlay strings, or strings
4275 displayed via the `display' property. That's the reason we can't
0fd37545
GM
4276 simply use find_next_newline_no_quit.
4277
4278 Note that this function may not skip over invisible text that is so
4279 because of text properties and immediately follows a newline. If
4280 it would, function reseat_at_next_visible_line_start, when called
4281 from set_iterator_to_next, would effectively make invisible
4282 characters following a newline part of the wrong glyph row, which
4283 leads to wrong cursor motion. */
5f5c8ee5 4284
cafafe0b
GM
4285static int
4286forward_to_next_line_start (it, skipped_p)
5f5c8ee5 4287 struct it *it;
cafafe0b 4288 int *skipped_p;
5f5c8ee5 4289{
54918e2b 4290 int old_selective, newline_found_p, n;
cafafe0b
GM
4291 const int MAX_NEWLINE_DISTANCE = 500;
4292
0fd37545
GM
4293 /* If already on a newline, just consume it to avoid unintended
4294 skipping over invisible text below. */
51695746
GM
4295 if (it->what == IT_CHARACTER
4296 && it->c == '\n'
4297 && CHARPOS (it->position) == IT_CHARPOS (*it))
0fd37545
GM
4298 {
4299 set_iterator_to_next (it, 0);
a77dc1ec 4300 it->c = 0;
0fd37545
GM
4301 return 1;
4302 }
4303
54918e2b 4304 /* Don't handle selective display in the following. It's (a)
0fd37545
GM
4305 unnecessary because it's done by the caller, and (b) leads to an
4306 infinite recursion because next_element_from_ellipsis indirectly
4307 calls this function. */
54918e2b
GM
4308 old_selective = it->selective;
4309 it->selective = 0;
4310
cafafe0b
GM
4311 /* Scan for a newline within MAX_NEWLINE_DISTANCE display elements
4312 from buffer text. */
3aec8722
GM
4313 for (n = newline_found_p = 0;
4314 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
4315 n += STRINGP (it->string) ? 0 : 1)
cafafe0b 4316 {
8692ca92 4317 if (!get_next_display_element (it))
d43be70c 4318 return 0;
d02f1cb8 4319 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
cafafe0b 4320 set_iterator_to_next (it, 0);
cafafe0b
GM
4321 }
4322
4323 /* If we didn't find a newline near enough, see if we can use a
4324 short-cut. */
db0bb807 4325 if (!newline_found_p)
cafafe0b
GM
4326 {
4327 int start = IT_CHARPOS (*it);
4328 int limit = find_next_newline_no_quit (start, 1);
4329 Lisp_Object pos;
4330
4331 xassert (!STRINGP (it->string));
4332
4333 /* If there isn't any `display' property in sight, and no
4334 overlays, we can just use the position of the newline in
4335 buffer text. */
4336 if (it->stop_charpos >= limit
4337 || ((pos = Fnext_single_property_change (make_number (start),
4338 Qdisplay,
4339 Qnil, make_number (limit)),
4340 NILP (pos))
4341 && next_overlay_change (start) == ZV))
4342 {
4343 IT_CHARPOS (*it) = limit;
4344 IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
4345 *skipped_p = newline_found_p = 1;
4346 }
4347 else
4348 {
4349 while (get_next_display_element (it)
4350 && !newline_found_p)
4351 {
4352 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
4353 set_iterator_to_next (it, 0);
4354 }
4355 }
4356 }
4357
54918e2b 4358 it->selective = old_selective;
cafafe0b 4359 return newline_found_p;
5f5c8ee5
GM
4360}
4361
4362
4363/* Set IT's current position to the previous visible line start. Skip
4364 invisible text that is so either due to text properties or due to
4365 selective display. Caution: this does not change IT->current_x and
4366 IT->hpos. */
4367
4368static void
4369back_to_previous_visible_line_start (it)
4370 struct it *it;
4371{
4372 int visible_p = 0;
4373
4374 /* Go back one newline if not on BEGV already. */
4375 if (IT_CHARPOS (*it) > BEGV)
4376 back_to_previous_line_start (it);
4377
4378 /* Move over lines that are invisible because of selective display
4379 or text properties. */
4380 while (IT_CHARPOS (*it) > BEGV
4381 && !visible_p)
4382 {
4383 visible_p = 1;
4384
4385 /* If selective > 0, then lines indented more than that values
4386 are invisible. */
4387 if (it->selective > 0
4388 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 4389 (double) it->selective)) /* iftc */
5f5c8ee5 4390 visible_p = 0;
2311178e 4391 else
5f5c8ee5
GM
4392 {
4393 Lisp_Object prop;
4394
6fc556fd
KR
4395 prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
4396 Qinvisible, it->window);
5f5c8ee5
GM
4397 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4398 visible_p = 0;
4399 }
5f5c8ee5
GM
4400
4401 /* Back one more newline if the current one is invisible. */
4402 if (!visible_p)
4403 back_to_previous_line_start (it);
4404 }
4405
4406 xassert (IT_CHARPOS (*it) >= BEGV);
4407 xassert (IT_CHARPOS (*it) == BEGV
4408 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
4409 CHECK_IT (it);
4410}
4411
4412
4413/* Reseat iterator IT at the previous visible line start. Skip
4414 invisible text that is so either due to text properties or due to
4415 selective display. At the end, update IT's overlay information,
4416 face information etc. */
4417
4418static void
4419reseat_at_previous_visible_line_start (it)
4420 struct it *it;
4421{
4422 back_to_previous_visible_line_start (it);
4423 reseat (it, it->current.pos, 1);
4424 CHECK_IT (it);
4425}
4426
4427
4428/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
4429 buffer. ON_NEWLINE_P non-zero means position IT on the newline
4430 preceding the line start. Skip over invisible text that is so
4431 because of selective display. Compute faces, overlays etc at the
4432 new position. Note that this function does not skip over text that
4433 is invisible because of text properties. */
5f5c8ee5
GM
4434
4435static void
312246d1 4436reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 4437 struct it *it;
312246d1 4438 int on_newline_p;
5f5c8ee5 4439{
cafafe0b
GM
4440 int newline_found_p, skipped_p = 0;
4441
4442 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4443
4444 /* Skip over lines that are invisible because they are indented
4445 more than the value of IT->selective. */
4446 if (it->selective > 0)
4447 while (IT_CHARPOS (*it) < ZV
a77dc1ec 4448 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 4449 (double) it->selective)) /* iftc */
a77dc1ec
GM
4450 {
4451 xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
4452 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4453 }
cafafe0b
GM
4454
4455 /* Position on the newline if that's what's requested. */
4456 if (on_newline_p && newline_found_p)
5f5c8ee5 4457 {
cafafe0b 4458 if (STRINGP (it->string))
5f5c8ee5 4459 {
cafafe0b
GM
4460 if (IT_STRING_CHARPOS (*it) > 0)
4461 {
4462 --IT_STRING_CHARPOS (*it);
4463 --IT_STRING_BYTEPOS (*it);
4464 }
5f5c8ee5 4465 }
cafafe0b 4466 else if (IT_CHARPOS (*it) > BEGV)
312246d1
GM
4467 {
4468 --IT_CHARPOS (*it);
cafafe0b
GM
4469 --IT_BYTEPOS (*it);
4470 reseat (it, it->current.pos, 0);
312246d1 4471 }
5f5c8ee5 4472 }
cafafe0b
GM
4473 else if (skipped_p)
4474 reseat (it, it->current.pos, 0);
2311178e 4475
5f5c8ee5
GM
4476 CHECK_IT (it);
4477}
4478
4479
4480\f
4481/***********************************************************************
4482 Changing an iterator's position
4483***********************************************************************/
4484
4485/* Change IT's current position to POS in current_buffer. If FORCE_P
4486 is non-zero, always check for text properties at the new position.
4487 Otherwise, text properties are only looked up if POS >=
4488 IT->check_charpos of a property. */
4489
4490static void
4491reseat (it, pos, force_p)
4492 struct it *it;
4493 struct text_pos pos;
4494 int force_p;
4495{
4496 int original_pos = IT_CHARPOS (*it);
4497
4498 reseat_1 (it, pos, 0);
4499
4500 /* Determine where to check text properties. Avoid doing it
4501 where possible because text property lookup is very expensive. */
4502 if (force_p
4503 || CHARPOS (pos) > it->stop_charpos
4504 || CHARPOS (pos) < original_pos)
4505 handle_stop (it);
4506
4507 CHECK_IT (it);
4508}
4509
4510
4511/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
4512 IT->stop_pos to POS, also. */
4513
4514static void
4515reseat_1 (it, pos, set_stop_p)
4516 struct it *it;
4517 struct text_pos pos;
4518 int set_stop_p;
4519{
4520 /* Don't call this function when scanning a C string. */
4521 xassert (it->s == NULL);
4522
4523 /* POS must be a reasonable value. */
4524 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
4525
4526 it->current.pos = it->position = pos;
4527 XSETBUFFER (it->object, current_buffer);
78c663d8 4528 it->end_charpos = ZV;
5f5c8ee5
GM
4529 it->dpvec = NULL;
4530 it->current.dpvec_index = -1;
4531 it->current.overlay_string_index = -1;
4532 IT_STRING_CHARPOS (*it) = -1;
4533 IT_STRING_BYTEPOS (*it) = -1;
4534 it->string = Qnil;
4535 it->method = next_element_from_buffer;
5905025c
RS
4536 /* RMS: I added this to fix a bug in move_it_vertically_backward
4537 where it->area continued to relate to the starting point
4538 for the backward motion. Bug report from
4539 Nick Roberts <nick@nick.uklinux.net> on 19 May 2003.
4540 However, I am not sure whether reseat still does the right thing
4541 in general after this change. */
4542 it->area = TEXT_AREA;
06fd3792 4543 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
5f5c8ee5 4544 it->sp = 0;
4aad61f8 4545 it->face_before_selective_p = 0;
5f5c8ee5
GM
4546
4547 if (set_stop_p)
4548 it->stop_charpos = CHARPOS (pos);
4549}
4550
4551
4552/* Set up IT for displaying a string, starting at CHARPOS in window W.
4553 If S is non-null, it is a C string to iterate over. Otherwise,
4554 STRING gives a Lisp string to iterate over.
2311178e 4555
5f5c8ee5
GM
4556 If PRECISION > 0, don't return more then PRECISION number of
4557 characters from the string.
4558
4559 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
4560 characters have been returned. FIELD_WIDTH < 0 means an infinite
4561 field width.
4562
4563 MULTIBYTE = 0 means disable processing of multibyte characters,
4564 MULTIBYTE > 0 means enable it,
4565 MULTIBYTE < 0 means use IT->multibyte_p.
4566
4567 IT must be initialized via a prior call to init_iterator before
4568 calling this function. */
4569
4570static void
4571reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
4572 struct it *it;
4573 unsigned char *s;
4574 Lisp_Object string;
4575 int charpos;
4576 int precision, field_width, multibyte;
4577{
4578 /* No region in strings. */
4579 it->region_beg_charpos = it->region_end_charpos = -1;
4580
4581 /* No text property checks performed by default, but see below. */
4582 it->stop_charpos = -1;
4583
4584 /* Set iterator position and end position. */
4585 bzero (&it->current, sizeof it->current);
4586 it->current.overlay_string_index = -1;
4587 it->current.dpvec_index = -1;
5f5c8ee5 4588 xassert (charpos >= 0);
2311178e 4589
e719f5ae
GM
4590 /* If STRING is specified, use its multibyteness, otherwise use the
4591 setting of MULTIBYTE, if specified. */
cabf45da 4592 if (multibyte >= 0)
5f5c8ee5 4593 it->multibyte_p = multibyte > 0;
2311178e 4594
5f5c8ee5
GM
4595 if (s == NULL)
4596 {
4597 xassert (STRINGP (string));
4598 it->string = string;
4599 it->s = NULL;
2051c264 4600 it->end_charpos = it->string_nchars = SCHARS (string);
5f5c8ee5
GM
4601 it->method = next_element_from_string;
4602 it->current.string_pos = string_pos (charpos, string);
4603 }
4604 else
4605 {
4606 it->s = s;
4607 it->string = Qnil;
4608
4609 /* Note that we use IT->current.pos, not it->current.string_pos,
4610 for displaying C strings. */
4611 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
4612 if (it->multibyte_p)
4613 {
4614 it->current.pos = c_string_pos (charpos, s, 1);
4615 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
4616 }
4617 else
4618 {
4619 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
4620 it->end_charpos = it->string_nchars = strlen (s);
4621 }
2311178e 4622
5f5c8ee5
GM
4623 it->method = next_element_from_c_string;
4624 }
4625
4626 /* PRECISION > 0 means don't return more than PRECISION characters
4627 from the string. */
4628 if (precision > 0 && it->end_charpos - charpos > precision)
4629 it->end_charpos = it->string_nchars = charpos + precision;
4630
4631 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
4632 characters have been returned. FIELD_WIDTH == 0 means don't pad,
4633 FIELD_WIDTH < 0 means infinite field width. This is useful for
4634 padding with `-' at the end of a mode line. */
4635 if (field_width < 0)
4636 field_width = INFINITY;
4637 if (field_width > it->end_charpos - charpos)
4638 it->end_charpos = charpos + field_width;
4639
4640 /* Use the standard display table for displaying strings. */
4641 if (DISP_TABLE_P (Vstandard_display_table))
4642 it->dp = XCHAR_TABLE (Vstandard_display_table);
4643
4644 it->stop_charpos = charpos;
4645 CHECK_IT (it);
4646}
4647
4648
4649\f
4650/***********************************************************************
4651 Iteration
4652 ***********************************************************************/
4653
4654/* Load IT's display element fields with information about the next
4655 display element from the current position of IT. Value is zero if
4656 end of buffer (or C string) is reached. */
4657
4658int
4659get_next_display_element (it)
4660 struct it *it;
4661{
7d0393cf 4662 /* Non-zero means that we found a display element. Zero means that
5f5c8ee5
GM
4663 we hit the end of what we iterate over. Performance note: the
4664 function pointer `method' used here turns out to be faster than
4665 using a sequence of if-statements. */
4666 int success_p = (*it->method) (it);
5f5c8ee5
GM
4667
4668 if (it->what == IT_CHARACTER)
4669 {
4670 /* Map via display table or translate control characters.
4671 IT->c, IT->len etc. have been set to the next character by
4672 the function call above. If we have a display table, and it
4673 contains an entry for IT->c, translate it. Don't do this if
4674 IT->c itself comes from a display table, otherwise we could
4675 end up in an infinite recursion. (An alternative could be to
4676 count the recursion depth of this function and signal an
4677 error when a certain maximum depth is reached.) Is it worth
4678 it? */
4679 if (success_p && it->dpvec == NULL)
4680 {
4681 Lisp_Object dv;
4682
4683 if (it->dp
4684 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
4685 VECTORP (dv)))
4686 {
4687 struct Lisp_Vector *v = XVECTOR (dv);
4688
4689 /* Return the first character from the display table
4690 entry, if not empty. If empty, don't display the
4691 current character. */
4692 if (v->size)
4693 {
4694 it->dpvec_char_len = it->len;
4695 it->dpvec = v->contents;
4696 it->dpend = v->contents + v->size;
4697 it->current.dpvec_index = 0;
4698 it->method = next_element_from_display_vector;
7eee47cc
GM
4699 success_p = get_next_display_element (it);
4700 }
4701 else
4702 {
4703 set_iterator_to_next (it, 0);
4704 success_p = get_next_display_element (it);
5f5c8ee5 4705 }
5f5c8ee5
GM
4706 }
4707
4708 /* Translate control characters into `\003' or `^C' form.
4709 Control characters coming from a display table entry are
4710 currently not translated because we use IT->dpvec to hold
4711 the translation. This could easily be changed but I
197516c2
KH
4712 don't believe that it is worth doing.
4713
fa831cf8
KH
4714 If it->multibyte_p is nonzero, eight-bit characters and
4715 non-printable multibyte characters are also translated to
4716 octal form.
4717
4718 If it->multibyte_p is zero, eight-bit characters that
4719 don't have corresponding multibyte char code are also
4720 translated to octal form. */
ba197fe6 4721 else if ((it->c < ' '
5f5c8ee5 4722 && (it->area != TEXT_AREA
c6e89d6c 4723 || (it->c != '\n' && it->c != '\t')))
fa831cf8
KH
4724 || (it->multibyte_p
4725 ? ((it->c >= 127
4726 && it->len == 1)
4727 || !CHAR_PRINTABLE_P (it->c))
ba197fe6 4728 : (it->c >= 127
fa831cf8 4729 && it->c == unibyte_char_to_multibyte (it->c))))
5f5c8ee5
GM
4730 {
4731 /* IT->c is a control character which must be displayed
4732 either as '\003' or as `^C' where the '\\' and '^'
4733 can be defined in the display table. Fill
4734 IT->ctl_chars with glyphs for what we have to
4735 display. Then, set IT->dpvec to these glyphs. */
4736 GLYPH g;
4737
54c85a23 4738 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
4739 {
4740 /* Set IT->ctl_chars[0] to the glyph for `^'. */
4741 if (it->dp
4742 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
4743 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
4744 g = XINT (DISP_CTRL_GLYPH (it->dp));
4745 else
4746 g = FAST_MAKE_GLYPH ('^', 0);
4747 XSETINT (it->ctl_chars[0], g);
4748
4749 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
4750 XSETINT (it->ctl_chars[1], g);
4751
4752 /* Set up IT->dpvec and return first character from it. */
4753 it->dpvec_char_len = it->len;
4754 it->dpvec = it->ctl_chars;
4755 it->dpend = it->dpvec + 2;
4756 it->current.dpvec_index = 0;
4757 it->method = next_element_from_display_vector;
4758 get_next_display_element (it);
4759 }
4760 else
4761 {
260a86a0 4762 unsigned char str[MAX_MULTIBYTE_LENGTH];
c5924f47 4763 int len;
197516c2
KH
4764 int i;
4765 GLYPH escape_glyph;
4766
5f5c8ee5
GM
4767 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
4768 if (it->dp
4769 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
4770 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 4771 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 4772 else
197516c2
KH
4773 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
4774
c5924f47
KH
4775 if (SINGLE_BYTE_CHAR_P (it->c))
4776 str[0] = it->c, len = 1;
4777 else
ea9dd091
GM
4778 {
4779 len = CHAR_STRING_NO_SIGNAL (it->c, str);
4780 if (len < 0)
4781 {
4782 /* It's an invalid character, which
4783 shouldn't happen actually, but due to
4784 bugs it may happen. Let's print the char
4785 as is, there's not much meaningful we can
4786 do with it. */
4787 str[0] = it->c;
4788 str[1] = it->c >> 8;
4789 str[2] = it->c >> 16;
4790 str[3] = it->c >> 24;
4791 len = 4;
4792 }
4793 }
c5924f47 4794
197516c2
KH
4795 for (i = 0; i < len; i++)
4796 {
4797 XSETINT (it->ctl_chars[i * 4], escape_glyph);
4798 /* Insert three more glyphs into IT->ctl_chars for
4799 the octal display of the character. */
2311178e 4800 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
197516c2 4801 XSETINT (it->ctl_chars[i * 4 + 1], g);
2311178e 4802 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
197516c2 4803 XSETINT (it->ctl_chars[i * 4 + 2], g);
2311178e 4804 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
197516c2
KH
4805 XSETINT (it->ctl_chars[i * 4 + 3], g);
4806 }
5f5c8ee5
GM
4807
4808 /* Set up IT->dpvec and return the first character
4809 from it. */
4810 it->dpvec_char_len = it->len;
4811 it->dpvec = it->ctl_chars;
197516c2 4812 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
4813 it->current.dpvec_index = 0;
4814 it->method = next_element_from_display_vector;
4815 get_next_display_element (it);
4816 }
4817 }
4818 }
4819
980806b6
KH
4820 /* Adjust face id for a multibyte character. There are no
4821 multibyte character in unibyte text. */
5f5c8ee5
GM
4822 if (it->multibyte_p
4823 && success_p
980806b6 4824 && FRAME_WINDOW_P (it->f))
5f5c8ee5 4825 {
980806b6
KH
4826 struct face *face = FACE_FROM_ID (it->f, it->face_id);
4827 it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
5f5c8ee5
GM
4828 }
4829 }
4830
4831 /* Is this character the last one of a run of characters with
4832 box? If yes, set IT->end_of_box_run_p to 1. */
4833 if (it->face_box_p
4834 && it->s == NULL)
4835 {
4836 int face_id;
4837 struct face *face;
4838
4839 it->end_of_box_run_p
4840 = ((face_id = face_after_it_pos (it),
4841 face_id != it->face_id)
4842 && (face = FACE_FROM_ID (it->f, face_id),
4843 face->box == FACE_NO_BOX));
4844 }
4845
4846 /* Value is 0 if end of buffer or string reached. */
4847 return success_p;
4848}
4849
4850
4851/* Move IT to the next display element.
4852
cafafe0b
GM
4853 RESEAT_P non-zero means if called on a newline in buffer text,
4854 skip to the next visible line start.
4855
5f5c8ee5
GM
4856 Functions get_next_display_element and set_iterator_to_next are
4857 separate because I find this arrangement easier to handle than a
4858 get_next_display_element function that also increments IT's
4859 position. The way it is we can first look at an iterator's current
4860 display element, decide whether it fits on a line, and if it does,
4861 increment the iterator position. The other way around we probably
4862 would either need a flag indicating whether the iterator has to be
4863 incremented the next time, or we would have to implement a
4864 decrement position function which would not be easy to write. */
4865
4866void
cafafe0b 4867set_iterator_to_next (it, reseat_p)
5f5c8ee5 4868 struct it *it;
cafafe0b 4869 int reseat_p;
5f5c8ee5 4870{
483de32b
GM
4871 /* Reset flags indicating start and end of a sequence of characters
4872 with box. Reset them at the start of this function because
4873 moving the iterator to a new position might set them. */
4874 it->start_of_box_run_p = it->end_of_box_run_p = 0;
2311178e 4875
5f5c8ee5
GM
4876 if (it->method == next_element_from_buffer)
4877 {
4878 /* The current display element of IT is a character from
4879 current_buffer. Advance in the buffer, and maybe skip over
4880 invisible lines that are so because of selective display. */
cafafe0b 4881 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
312246d1 4882 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4883 else
4884 {
4885 xassert (it->len != 0);
4886 IT_BYTEPOS (*it) += it->len;
4887 IT_CHARPOS (*it) += 1;
4888 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
4889 }
4890 }
260a86a0
KH
4891 else if (it->method == next_element_from_composition)
4892 {
4893 xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
4894 if (STRINGP (it->string))
4895 {
4896 IT_STRING_BYTEPOS (*it) += it->len;
4897 IT_STRING_CHARPOS (*it) += it->cmp_len;
4898 it->method = next_element_from_string;
4899 goto consider_string_end;
4900 }
4901 else
4902 {
4903 IT_BYTEPOS (*it) += it->len;
4904 IT_CHARPOS (*it) += it->cmp_len;
4905 it->method = next_element_from_buffer;
4906 }
4907 }
5f5c8ee5
GM
4908 else if (it->method == next_element_from_c_string)
4909 {
4910 /* Current display element of IT is from a C string. */
4911 IT_BYTEPOS (*it) += it->len;
4912 IT_CHARPOS (*it) += 1;
4913 }
4914 else if (it->method == next_element_from_display_vector)
4915 {
4916 /* Current display element of IT is from a display table entry.
4917 Advance in the display table definition. Reset it to null if
4918 end reached, and continue with characters from buffers/
4919 strings. */
4920 ++it->current.dpvec_index;
286bcbc9 4921
980806b6
KH
4922 /* Restore face of the iterator to what they were before the
4923 display vector entry (these entries may contain faces). */
5f5c8ee5 4924 it->face_id = it->saved_face_id;
2311178e 4925
5f5c8ee5
GM
4926 if (it->dpvec + it->current.dpvec_index == it->dpend)
4927 {
4928 if (it->s)
4929 it->method = next_element_from_c_string;
4930 else if (STRINGP (it->string))
4931 it->method = next_element_from_string;
4932 else
4933 it->method = next_element_from_buffer;
4934
4935 it->dpvec = NULL;
4936 it->current.dpvec_index = -1;
4937
312246d1
GM
4938 /* Skip over characters which were displayed via IT->dpvec. */
4939 if (it->dpvec_char_len < 0)
4940 reseat_at_next_visible_line_start (it, 1);
4941 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
4942 {
4943 it->len = it->dpvec_char_len;
cafafe0b 4944 set_iterator_to_next (it, reseat_p);
5f5c8ee5
GM
4945 }
4946 }
4947 }
4948 else if (it->method == next_element_from_string)
4949 {
4950 /* Current display element is a character from a Lisp string. */
4951 xassert (it->s == NULL && STRINGP (it->string));
4952 IT_STRING_BYTEPOS (*it) += it->len;
4953 IT_STRING_CHARPOS (*it) += 1;
2311178e 4954
5f5c8ee5
GM
4955 consider_string_end:
4956
4957 if (it->current.overlay_string_index >= 0)
4958 {
4959 /* IT->string is an overlay string. Advance to the
4960 next, if there is one. */
2051c264 4961 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
4962 next_overlay_string (it);
4963 }
4964 else
4965 {
4966 /* IT->string is not an overlay string. If we reached
4967 its end, and there is something on IT->stack, proceed
4968 with what is on the stack. This can be either another
4969 string, this time an overlay string, or a buffer. */
2051c264 4970 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
5f5c8ee5
GM
4971 && it->sp > 0)
4972 {
4973 pop_it (it);
4974 if (!STRINGP (it->string))
4975 it->method = next_element_from_buffer;
b2046df8
GM
4976 else
4977 goto consider_string_end;
5f5c8ee5
GM
4978 }
4979 }
4980 }
4981 else if (it->method == next_element_from_image
4982 || it->method == next_element_from_stretch)
4983 {
4984 /* The position etc with which we have to proceed are on
4985 the stack. The position may be at the end of a string,
4986 if the `display' property takes up the whole string. */
4987 pop_it (it);
4988 it->image_id = 0;
4989 if (STRINGP (it->string))
4990 {
4991 it->method = next_element_from_string;
4992 goto consider_string_end;
4993 }
4994 else
4995 it->method = next_element_from_buffer;
4996 }
4997 else
4998 /* There are no other methods defined, so this should be a bug. */
4999 abort ();
5000
5f5c8ee5
GM
5001 xassert (it->method != next_element_from_string
5002 || (STRINGP (it->string)
5003 && IT_STRING_CHARPOS (*it) >= 0));
5004}
5005
5006
5007/* Load IT's display element fields with information about the next
5008 display element which comes from a display table entry or from the
5009 result of translating a control character to one of the forms `^C'
5010 or `\003'. IT->dpvec holds the glyphs to return as characters. */
5011
5012static int
5013next_element_from_display_vector (it)
5014 struct it *it;
5015{
5016 /* Precondition. */
5017 xassert (it->dpvec && it->current.dpvec_index >= 0);
5018
5019 /* Remember the current face id in case glyphs specify faces.
5020 IT's face is restored in set_iterator_to_next. */
5021 it->saved_face_id = it->face_id;
2311178e 5022
5f5c8ee5
GM
5023 if (INTEGERP (*it->dpvec)
5024 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
5025 {
5026 int lface_id;
5027 GLYPH g;
5028
5029 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
5030 it->c = FAST_GLYPH_CHAR (g);
c5924f47 5031 it->len = CHAR_BYTES (it->c);
5f5c8ee5
GM
5032
5033 /* The entry may contain a face id to use. Such a face id is
5034 the id of a Lisp face, not a realized face. A face id of
969065c3 5035 zero means no face is specified. */
5f5c8ee5
GM
5036 lface_id = FAST_GLYPH_FACE (g);
5037 if (lface_id)
5038 {
969065c3 5039 /* The function returns -1 if lface_id is invalid. */
5f5c8ee5
GM
5040 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
5041 if (face_id >= 0)
969065c3 5042 it->face_id = face_id;
5f5c8ee5
GM
5043 }
5044 }
5045 else
5046 /* Display table entry is invalid. Return a space. */
5047 it->c = ' ', it->len = 1;
5048
5049 /* Don't change position and object of the iterator here. They are
5050 still the values of the character that had this display table
5051 entry or was translated, and that's what we want. */
5052 it->what = IT_CHARACTER;
5053 return 1;
5054}
5055
5056
5057/* Load IT with the next display element from Lisp string IT->string.
5058 IT->current.string_pos is the current position within the string.
5059 If IT->current.overlay_string_index >= 0, the Lisp string is an
5060 overlay string. */
5061
5062static int
5063next_element_from_string (it)
5064 struct it *it;
5065{
5066 struct text_pos position;
5067
5068 xassert (STRINGP (it->string));
5069 xassert (IT_STRING_CHARPOS (*it) >= 0);
5070 position = it->current.string_pos;
5071
5072 /* Time to check for invisible text? */
5073 if (IT_STRING_CHARPOS (*it) < it->end_charpos
5074 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
5075 {
5076 handle_stop (it);
5077
5078 /* Since a handler may have changed IT->method, we must
5079 recurse here. */
5080 return get_next_display_element (it);
5081 }
5082
5083 if (it->current.overlay_string_index >= 0)
5084 {
5085 /* Get the next character from an overlay string. In overlay
5086 strings, There is no field width or padding with spaces to
5087 do. */
2051c264 5088 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
5089 {
5090 it->what = IT_EOB;
5091 return 0;
5092 }
5093 else if (STRING_MULTIBYTE (it->string))
5094 {
2051c264 5095 int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
5096 const unsigned char *s = (SDATA (it->string)
5097 + IT_STRING_BYTEPOS (*it));
4fdb80f2 5098 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
5099 }
5100 else
5101 {
2051c264 5102 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
5103 it->len = 1;
5104 }
5105 }
5106 else
5107 {
5108 /* Get the next character from a Lisp string that is not an
5109 overlay string. Such strings come from the mode line, for
5110 example. We may have to pad with spaces, or truncate the
5111 string. See also next_element_from_c_string. */
5112 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
5113 {
5114 it->what = IT_EOB;
5115 return 0;
5116 }
5117 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
5118 {
5119 /* Pad with spaces. */
5120 it->c = ' ', it->len = 1;
5121 CHARPOS (position) = BYTEPOS (position) = -1;
5122 }
5123 else if (STRING_MULTIBYTE (it->string))
5124 {
2051c264 5125 int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
5126 const unsigned char *s = (SDATA (it->string)
5127 + IT_STRING_BYTEPOS (*it));
4fdb80f2 5128 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
5129 }
5130 else
5131 {
2051c264 5132 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
5133 it->len = 1;
5134 }
5135 }
5136
5137 /* Record what we have and where it came from. Note that we store a
5138 buffer position in IT->position although it could arguably be a
5139 string position. */
5140 it->what = IT_CHARACTER;
5141 it->object = it->string;
5142 it->position = position;
5143 return 1;
5144}
5145
5146
5147/* Load IT with next display element from C string IT->s.
5148 IT->string_nchars is the maximum number of characters to return
5149 from the string. IT->end_charpos may be greater than
5150 IT->string_nchars when this function is called, in which case we
5151 may have to return padding spaces. Value is zero if end of string
5152 reached, including padding spaces. */
5153
5154static int
5155next_element_from_c_string (it)
5156 struct it *it;
5157{
5158 int success_p = 1;
2311178e 5159
5f5c8ee5
GM
5160 xassert (it->s);
5161 it->what = IT_CHARACTER;
5162 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
5163 it->object = Qnil;
2311178e 5164
5f5c8ee5
GM
5165 /* IT's position can be greater IT->string_nchars in case a field
5166 width or precision has been specified when the iterator was
5167 initialized. */
5168 if (IT_CHARPOS (*it) >= it->end_charpos)
5169 {
5170 /* End of the game. */
5171 it->what = IT_EOB;
5172 success_p = 0;
5173 }
5174 else if (IT_CHARPOS (*it) >= it->string_nchars)
5175 {
5176 /* Pad with spaces. */
5177 it->c = ' ', it->len = 1;
5178 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
5179 }
5180 else if (it->multibyte_p)
5181 {
5182 /* Implementation note: The calls to strlen apparently aren't a
5183 performance problem because there is no noticeable performance
5184 difference between Emacs running in unibyte or multibyte mode. */
5185 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
5186 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
5187 maxlen, &it->len);
5f5c8ee5
GM
5188 }
5189 else
5190 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
2311178e 5191
5f5c8ee5
GM
5192 return success_p;
5193}
5194
5195
5196/* Set up IT to return characters from an ellipsis, if appropriate.
5197 The definition of the ellipsis glyphs may come from a display table
5198 entry. This function Fills IT with the first glyph from the
5199 ellipsis if an ellipsis is to be displayed. */
5200
13f19968 5201static int
5f5c8ee5
GM
5202next_element_from_ellipsis (it)
5203 struct it *it;
5204{
13f19968 5205 if (it->selective_display_ellipsis_p)
5f5c8ee5 5206 {
13f19968
GM
5207 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5208 {
5209 /* Use the display table definition for `...'. Invalid glyphs
5210 will be handled by the method returning elements from dpvec. */
5211 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5212 it->dpvec_char_len = it->len;
5213 it->dpvec = v->contents;
5214 it->dpend = v->contents + v->size;
5215 it->current.dpvec_index = 0;
5216 it->method = next_element_from_display_vector;
5217 }
5218 else
5219 {
5220 /* Use default `...' which is stored in default_invis_vector. */
5221 it->dpvec_char_len = it->len;
5222 it->dpvec = default_invis_vector;
5223 it->dpend = default_invis_vector + 3;
5224 it->current.dpvec_index = 0;
5225 it->method = next_element_from_display_vector;
5226 }
5f5c8ee5 5227 }
13f19968 5228 else
54918e2b 5229 {
4aad61f8
GM
5230 /* The face at the current position may be different from the
5231 face we find after the invisible text. Remember what it
5232 was in IT->saved_face_id, and signal that it's there by
5233 setting face_before_selective_p. */
5234 it->saved_face_id = it->face_id;
54918e2b
GM
5235 it->method = next_element_from_buffer;
5236 reseat_at_next_visible_line_start (it, 1);
4aad61f8 5237 it->face_before_selective_p = 1;
54918e2b 5238 }
2311178e 5239
13f19968 5240 return get_next_display_element (it);
5f5c8ee5
GM
5241}
5242
5243
5244/* Deliver an image display element. The iterator IT is already
5245 filled with image information (done in handle_display_prop). Value
5246 is always 1. */
2311178e 5247
5f5c8ee5
GM
5248
5249static int
5250next_element_from_image (it)
5251 struct it *it;
5252{
5253 it->what = IT_IMAGE;
5254 return 1;
5255}
5256
5257
5258/* Fill iterator IT with next display element from a stretch glyph
5259 property. IT->object is the value of the text property. Value is
5260 always 1. */
5261
5262static int
5263next_element_from_stretch (it)
5264 struct it *it;
5265{
5266 it->what = IT_STRETCH;
5267 return 1;
5268}
5269
5270
5271/* Load IT with the next display element from current_buffer. Value
5272 is zero if end of buffer reached. IT->stop_charpos is the next
5273 position at which to stop and check for text properties or buffer
5274 end. */
5275
5276static int
5277next_element_from_buffer (it)
5278 struct it *it;
5279{
5280 int success_p = 1;
5281
5282 /* Check this assumption, otherwise, we would never enter the
5283 if-statement, below. */
5284 xassert (IT_CHARPOS (*it) >= BEGV
5285 && IT_CHARPOS (*it) <= it->stop_charpos);
5286
5287 if (IT_CHARPOS (*it) >= it->stop_charpos)
5288 {
5289 if (IT_CHARPOS (*it) >= it->end_charpos)
5290 {
5291 int overlay_strings_follow_p;
2311178e 5292
5f5c8ee5
GM
5293 /* End of the game, except when overlay strings follow that
5294 haven't been returned yet. */
5295 if (it->overlay_strings_at_end_processed_p)
5296 overlay_strings_follow_p = 0;
5297 else
5298 {
5299 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf 5300 overlay_strings_follow_p = get_overlay_strings (it, 0);
5f5c8ee5
GM
5301 }
5302
5303 if (overlay_strings_follow_p)
5304 success_p = get_next_display_element (it);
5305 else
5306 {
5307 it->what = IT_EOB;
5308 it->position = it->current.pos;
5309 success_p = 0;
5310 }
5311 }
5312 else
5313 {
5314 handle_stop (it);
5315 return get_next_display_element (it);
5316 }
5317 }
5318 else
5319 {
5320 /* No face changes, overlays etc. in sight, so just return a
5321 character from current_buffer. */
5322 unsigned char *p;
5323
5324 /* Maybe run the redisplay end trigger hook. Performance note:
5325 This doesn't seem to cost measurable time. */
5326 if (it->redisplay_end_trigger_charpos
5327 && it->glyph_row
5328 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
5329 run_redisplay_end_trigger_hook (it);
5330
5331 /* Get the next character, maybe multibyte. */
5332 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
260a86a0 5333 if (it->multibyte_p && !ASCII_BYTE_P (*p))
5f5c8ee5
GM
5334 {
5335 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
5336 - IT_BYTEPOS (*it));
4fdb80f2 5337 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
5338 }
5339 else
5340 it->c = *p, it->len = 1;
5341
5342 /* Record what we have and where it came from. */
5343 it->what = IT_CHARACTER;;
5344 it->object = it->w->buffer;
5345 it->position = it->current.pos;
5346
5347 /* Normally we return the character found above, except when we
5348 really want to return an ellipsis for selective display. */
5349 if (it->selective)
5350 {
5351 if (it->c == '\n')
5352 {
5353 /* A value of selective > 0 means hide lines indented more
5354 than that number of columns. */
5355 if (it->selective > 0
5356 && IT_CHARPOS (*it) + 1 < ZV
5357 && indented_beyond_p (IT_CHARPOS (*it) + 1,
5358 IT_BYTEPOS (*it) + 1,
a67e162b 5359 (double) it->selective)) /* iftc */
312246d1 5360 {
13f19968 5361 success_p = next_element_from_ellipsis (it);
312246d1
GM
5362 it->dpvec_char_len = -1;
5363 }
5f5c8ee5
GM
5364 }
5365 else if (it->c == '\r' && it->selective == -1)
5366 {
5367 /* A value of selective == -1 means that everything from the
5368 CR to the end of the line is invisible, with maybe an
5369 ellipsis displayed for it. */
13f19968 5370 success_p = next_element_from_ellipsis (it);
312246d1 5371 it->dpvec_char_len = -1;
5f5c8ee5
GM
5372 }
5373 }
5374 }
5375
5376 /* Value is zero if end of buffer reached. */
c880678e 5377 xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
5f5c8ee5
GM
5378 return success_p;
5379}
5380
2311178e 5381
5f5c8ee5
GM
5382/* Run the redisplay end trigger hook for IT. */
5383
5384static void
5385run_redisplay_end_trigger_hook (it)
5386 struct it *it;
5387{
5388 Lisp_Object args[3];
5389
5390 /* IT->glyph_row should be non-null, i.e. we should be actually
5391 displaying something, or otherwise we should not run the hook. */
5392 xassert (it->glyph_row);
5393
5394 /* Set up hook arguments. */
5395 args[0] = Qredisplay_end_trigger_functions;
5396 args[1] = it->window;
5397 XSETINT (args[2], it->redisplay_end_trigger_charpos);
5398 it->redisplay_end_trigger_charpos = 0;
5399
5400 /* Since we are *trying* to run these functions, don't try to run
5401 them again, even if they get an error. */
5402 it->w->redisplay_end_trigger = Qnil;
5403 Frun_hook_with_args (3, args);
2311178e 5404
5f5c8ee5
GM
5405 /* Notice if it changed the face of the character we are on. */
5406 handle_face_prop (it);
5407}
5408
5409
260a86a0
KH
5410/* Deliver a composition display element. The iterator IT is already
5411 filled with composition information (done in
5412 handle_composition_prop). Value is always 1. */
5413
5414static int
5415next_element_from_composition (it)
5416 struct it *it;
5417{
5418 it->what = IT_COMPOSITION;
5419 it->position = (STRINGP (it->string)
5420 ? it->current.string_pos
5421 : it->current.pos);
5422 return 1;
5423}
5424
5425
5f5c8ee5
GM
5426\f
5427/***********************************************************************
5428 Moving an iterator without producing glyphs
5429 ***********************************************************************/
5430
5431/* Move iterator IT to a specified buffer or X position within one
5432 line on the display without producing glyphs.
5433
c53a1624
RS
5434 OP should be a bit mask including some or all of these bits:
5435 MOVE_TO_X: Stop on reaching x-position TO_X.
5436 MOVE_TO_POS: Stop on reaching buffer or string position TO_CHARPOS.
5437 Regardless of OP's value, stop in reaching the end of the display line.
5f5c8ee5 5438
c53a1624
RS
5439 TO_X is normally a value 0 <= TO_X <= IT->last_visible_x.
5440 This means, in particular, that TO_X includes window's horizontal
5441 scroll amount.
5f5c8ee5 5442
c53a1624
RS
5443 The return value has several possible values that
5444 say what condition caused the scan to stop:
5f5c8ee5
GM
5445
5446 MOVE_POS_MATCH_OR_ZV
5447 - when TO_POS or ZV was reached.
2311178e 5448
5f5c8ee5
GM
5449 MOVE_X_REACHED
5450 -when TO_X was reached before TO_POS or ZV were reached.
2311178e 5451
5f5c8ee5
GM
5452 MOVE_LINE_CONTINUED
5453 - when we reached the end of the display area and the line must
5454 be continued.
2311178e 5455
5f5c8ee5
GM
5456 MOVE_LINE_TRUNCATED
5457 - when we reached the end of the display area and the line is
5458 truncated.
5459
5460 MOVE_NEWLINE_OR_CR
5461 - when we stopped at a line end, i.e. a newline or a CR and selective
5462 display is on. */
5463
701552dd 5464static enum move_it_result
5f5c8ee5
GM
5465move_it_in_display_line_to (it, to_charpos, to_x, op)
5466 struct it *it;
5467 int to_charpos, to_x, op;
5468{
5469 enum move_it_result result = MOVE_UNDEFINED;
5470 struct glyph_row *saved_glyph_row;
5471
5472 /* Don't produce glyphs in produce_glyphs. */
5473 saved_glyph_row = it->glyph_row;
5474 it->glyph_row = NULL;
5475
5f5c8ee5
GM
5476 while (1)
5477 {
ae26e27d 5478 int x, i, ascent = 0, descent = 0;
2311178e 5479
5f5c8ee5
GM
5480 /* Stop when ZV or TO_CHARPOS reached. */
5481 if (!get_next_display_element (it)
5482 || ((op & MOVE_TO_POS) != 0
5483 && BUFFERP (it->object)
5484 && IT_CHARPOS (*it) >= to_charpos))
5485 {
5486 result = MOVE_POS_MATCH_OR_ZV;
5487 break;
5488 }
2311178e 5489
5f5c8ee5
GM
5490 /* The call to produce_glyphs will get the metrics of the
5491 display element IT is loaded with. We record in x the
5492 x-position before this display element in case it does not
5493 fit on the line. */
5494 x = it->current_x;
2311178e 5495
47589c8c
GM
5496 /* Remember the line height so far in case the next element doesn't
5497 fit on the line. */
5498 if (!it->truncate_lines_p)
5499 {
5500 ascent = it->max_ascent;
5501 descent = it->max_descent;
5502 }
2311178e 5503
5f5c8ee5
GM
5504 PRODUCE_GLYPHS (it);
5505
5506 if (it->area != TEXT_AREA)
5507 {
cafafe0b 5508 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5509 continue;
5510 }
5511
5512 /* The number of glyphs we get back in IT->nglyphs will normally
5513 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
5514 character on a terminal frame, or (iii) a line end. For the
5515 second case, IT->nglyphs - 1 padding glyphs will be present
5516 (on X frames, there is only one glyph produced for a
5517 composite character.
5518
5519 The behavior implemented below means, for continuation lines,
5520 that as many spaces of a TAB as fit on the current line are
5521 displayed there. For terminal frames, as many glyphs of a
5522 multi-glyph character are displayed in the current line, too.
5523 This is what the old redisplay code did, and we keep it that
5524 way. Under X, the whole shape of a complex character must
5525 fit on the line or it will be completely displayed in the
5526 next line.
5527
5528 Note that both for tabs and padding glyphs, all glyphs have
5529 the same width. */
5530 if (it->nglyphs)
5531 {
5532 /* More than one glyph or glyph doesn't fit on line. All
5533 glyphs have the same width. */
5534 int single_glyph_width = it->pixel_width / it->nglyphs;
5535 int new_x;
2311178e 5536
5f5c8ee5
GM
5537 for (i = 0; i < it->nglyphs; ++i, x = new_x)
5538 {
5539 new_x = x + single_glyph_width;
5540
5541 /* We want to leave anything reaching TO_X to the caller. */
5542 if ((op & MOVE_TO_X) && new_x > to_x)
5543 {
5544 it->current_x = x;
5545 result = MOVE_X_REACHED;
5546 break;
5547 }
5548 else if (/* Lines are continued. */
5549 !it->truncate_lines_p
5550 && (/* And glyph doesn't fit on the line. */
5551 new_x > it->last_visible_x
5552 /* Or it fits exactly and we're on a window
5553 system frame. */
5554 || (new_x == it->last_visible_x
5555 && FRAME_WINDOW_P (it->f))))
5556 {
5557 if (/* IT->hpos == 0 means the very first glyph
5558 doesn't fit on the line, e.g. a wide image. */
5559 it->hpos == 0
5560 || (new_x == it->last_visible_x
5561 && FRAME_WINDOW_P (it->f)))
5562 {
5563 ++it->hpos;
5564 it->current_x = new_x;
5565 if (i == it->nglyphs - 1)
cafafe0b 5566 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5567 }
5568 else
47589c8c
GM
5569 {
5570 it->current_x = x;
5571 it->max_ascent = ascent;
5572 it->max_descent = descent;
5573 }
2311178e 5574
47589c8c
GM
5575 TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
5576 IT_CHARPOS (*it)));
5f5c8ee5
GM
5577 result = MOVE_LINE_CONTINUED;
5578 break;
5579 }
5580 else if (new_x > it->first_visible_x)
5581 {
5582 /* Glyph is visible. Increment number of glyphs that
5583 would be displayed. */
5584 ++it->hpos;
5585 }
5586 else
5587 {
2311178e 5588 /* Glyph is completely off the left margin of the display
5f5c8ee5
GM
5589 area. Nothing to do. */
5590 }
5591 }
5592
5593 if (result != MOVE_UNDEFINED)
5594 break;
5595 }
5596 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
5597 {
5598 /* Stop when TO_X specified and reached. This check is
5599 necessary here because of lines consisting of a line end,
5600 only. The line end will not produce any glyphs and we
5601 would never get MOVE_X_REACHED. */
5602 xassert (it->nglyphs == 0);
5603 result = MOVE_X_REACHED;
5604 break;
5605 }
2311178e 5606
5f5c8ee5
GM
5607 /* Is this a line end? If yes, we're done. */
5608 if (ITERATOR_AT_END_OF_LINE_P (it))
5609 {
5610 result = MOVE_NEWLINE_OR_CR;
5611 break;
5612 }
2311178e 5613
5f5c8ee5
GM
5614 /* The current display element has been consumed. Advance
5615 to the next. */
cafafe0b 5616 set_iterator_to_next (it, 1);
2311178e 5617
5f5c8ee5
GM
5618 /* Stop if lines are truncated and IT's current x-position is
5619 past the right edge of the window now. */
5620 if (it->truncate_lines_p
5621 && it->current_x >= it->last_visible_x)
5622 {
5623 result = MOVE_LINE_TRUNCATED;
5624 break;
5625 }
5626 }
5627
5628 /* Restore the iterator settings altered at the beginning of this
5629 function. */
5630 it->glyph_row = saved_glyph_row;
5631 return result;
5632}
5633
5634
9b2bba76
RS
5635/* Move IT forward until it satisfies one or more of the criteria in
5636 TO_CHARPOS, TO_X, TO_Y, and TO_VPOS.
5637
5638 OP is a bit-mask that specifies where to stop, and in particular,
5639 which of those four position arguments makes a difference. See the
5640 description of enum move_operation_enum.
2311178e 5641
5f5c8ee5
GM
5642 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
5643 screen line, this function will set IT to the next position >
5644 TO_CHARPOS. */
5645
5646void
5647move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
5648 struct it *it;
5649 int to_charpos, to_x, to_y, to_vpos;
5650 int op;
5651{
5652 enum move_it_result skip, skip2 = MOVE_X_REACHED;
5653 int line_height;
47589c8c 5654 int reached = 0;
5f5c8ee5 5655
47589c8c 5656 for (;;)
5f5c8ee5
GM
5657 {
5658 if (op & MOVE_TO_VPOS)
5659 {
5660 /* If no TO_CHARPOS and no TO_X specified, stop at the
5661 start of the line TO_VPOS. */
5662 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
5663 {
5664 if (it->vpos == to_vpos)
47589c8c
GM
5665 {
5666 reached = 1;
5667 break;
5668 }
5669 else
5670 skip = move_it_in_display_line_to (it, -1, -1, 0);
5f5c8ee5
GM
5671 }
5672 else
5673 {
5674 /* TO_VPOS >= 0 means stop at TO_X in the line at
5675 TO_VPOS, or at TO_POS, whichever comes first. */
47589c8c
GM
5676 if (it->vpos == to_vpos)
5677 {
5678 reached = 2;
5679 break;
5680 }
2311178e 5681
5f5c8ee5
GM
5682 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
5683
5684 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
47589c8c
GM
5685 {
5686 reached = 3;
5687 break;
5688 }
5f5c8ee5
GM
5689 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
5690 {
5691 /* We have reached TO_X but not in the line we want. */
5692 skip = move_it_in_display_line_to (it, to_charpos,
5693 -1, MOVE_TO_POS);
5694 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5695 {
5696 reached = 4;
5697 break;
5698 }
5f5c8ee5
GM
5699 }
5700 }
5701 }
5702 else if (op & MOVE_TO_Y)
5703 {
5704 struct it it_backup;
2311178e 5705
5f5c8ee5
GM
5706 /* TO_Y specified means stop at TO_X in the line containing
5707 TO_Y---or at TO_CHARPOS if this is reached first. The
5708 problem is that we can't really tell whether the line
5709 contains TO_Y before we have completely scanned it, and
5710 this may skip past TO_X. What we do is to first scan to
5711 TO_X.
5712
5713 If TO_X is not specified, use a TO_X of zero. The reason
5714 is to make the outcome of this function more predictable.
5715 If we didn't use TO_X == 0, we would stop at the end of
5716 the line which is probably not what a caller would expect
5717 to happen. */
5718 skip = move_it_in_display_line_to (it, to_charpos,
5719 ((op & MOVE_TO_X)
5720 ? to_x : 0),
5721 (MOVE_TO_X
5722 | (op & MOVE_TO_POS)));
5723
5724 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
5725 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5726 {
5727 reached = 5;
5728 break;
5729 }
2311178e 5730
5f5c8ee5
GM
5731 /* If TO_X was reached, we would like to know whether TO_Y
5732 is in the line. This can only be said if we know the
5733 total line height which requires us to scan the rest of
5734 the line. */
5f5c8ee5
GM
5735 if (skip == MOVE_X_REACHED)
5736 {
5737 it_backup = *it;
47589c8c 5738 TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5739 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
5740 op & MOVE_TO_POS);
47589c8c 5741 TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5742 }
5743
5744 /* Now, decide whether TO_Y is in this line. */
5745 line_height = it->max_ascent + it->max_descent;
47589c8c 5746 TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
2311178e 5747
5f5c8ee5
GM
5748 if (to_y >= it->current_y
5749 && to_y < it->current_y + line_height)
5750 {
5751 if (skip == MOVE_X_REACHED)
5752 /* If TO_Y is in this line and TO_X was reached above,
5753 we scanned too far. We have to restore IT's settings
5754 to the ones before skipping. */
5755 *it = it_backup;
47589c8c 5756 reached = 6;
5f5c8ee5
GM
5757 }
5758 else if (skip == MOVE_X_REACHED)
5759 {
5760 skip = skip2;
5761 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c 5762 reached = 7;
5f5c8ee5
GM
5763 }
5764
47589c8c 5765 if (reached)
5f5c8ee5
GM
5766 break;
5767 }
5768 else
5769 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
5770
5771 switch (skip)
5772 {
5773 case MOVE_POS_MATCH_OR_ZV:
47589c8c
GM
5774 reached = 8;
5775 goto out;
5f5c8ee5
GM
5776
5777 case MOVE_NEWLINE_OR_CR:
cafafe0b 5778 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5779 it->continuation_lines_width = 0;
5780 break;
5781
5782 case MOVE_LINE_TRUNCATED:
5783 it->continuation_lines_width = 0;
312246d1 5784 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
5785 if ((op & MOVE_TO_POS) != 0
5786 && IT_CHARPOS (*it) > to_charpos)
47589c8c
GM
5787 {
5788 reached = 9;
5789 goto out;
5790 }
5f5c8ee5
GM
5791 break;
5792
5793 case MOVE_LINE_CONTINUED:
5794 it->continuation_lines_width += it->current_x;
5795 break;
5796
5797 default:
5798 abort ();
5799 }
5800
5801 /* Reset/increment for the next run. */
5802 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
5803 it->current_x = it->hpos = 0;
5804 it->current_y += it->max_ascent + it->max_descent;
5805 ++it->vpos;
5806 last_height = it->max_ascent + it->max_descent;
5807 last_max_ascent = it->max_ascent;
5808 it->max_ascent = it->max_descent = 0;
5809 }
2311178e 5810
47589c8c
GM
5811 out:
5812
5813 TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
5f5c8ee5
GM
5814}
5815
5816
5817/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
5818
5819 If DY > 0, move IT backward at least that many pixels. DY = 0
5820 means move IT backward to the preceding line start or BEGV. This
5821 function may move over more than DY pixels if IT->current_y - DY
5822 ends up in the middle of a line; in this case IT->current_y will be
5823 set to the top of the line moved to. */
5824
5825void
5826move_it_vertically_backward (it, dy)
5827 struct it *it;
5828 int dy;
5829{
79ddf6f7
GM
5830 int nlines, h;
5831 struct it it2, it3;
5f5c8ee5 5832 int start_pos = IT_CHARPOS (*it);
2311178e 5833
5f5c8ee5
GM
5834 xassert (dy >= 0);
5835
5836 /* Estimate how many newlines we must move back. */
da8b7f4f 5837 nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
5f5c8ee5
GM
5838
5839 /* Set the iterator's position that many lines back. */
5840 while (nlines-- && IT_CHARPOS (*it) > BEGV)
5841 back_to_previous_visible_line_start (it);
5842
5843 /* Reseat the iterator here. When moving backward, we don't want
5844 reseat to skip forward over invisible text, set up the iterator
5845 to deliver from overlay strings at the new position etc. So,
5846 use reseat_1 here. */
5847 reseat_1 (it, it->current.pos, 1);
5848
5849 /* We are now surely at a line start. */
5850 it->current_x = it->hpos = 0;
0e47bbf7 5851 it->continuation_lines_width = 0;
5f5c8ee5
GM
5852
5853 /* Move forward and see what y-distance we moved. First move to the
5854 start of the next line so that we get its height. We need this
5855 height to be able to tell whether we reached the specified
5856 y-distance. */
5857 it2 = *it;
5858 it2.max_ascent = it2.max_descent = 0;
5859 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
5860 MOVE_TO_POS | MOVE_TO_VPOS);
5861 xassert (IT_CHARPOS (*it) >= BEGV);
79ddf6f7 5862 it3 = it2;
2311178e 5863
5f5c8ee5
GM
5864 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
5865 xassert (IT_CHARPOS (*it) >= BEGV);
ccbb9ed2
RS
5866 /* H is the actual vertical distance from the position in *IT
5867 and the starting position. */
5f5c8ee5 5868 h = it2.current_y - it->current_y;
ccbb9ed2 5869 /* NLINES is the distance in number of lines. */
5f5c8ee5
GM
5870 nlines = it2.vpos - it->vpos;
5871
ccbb9ed2
RS
5872 /* Correct IT's y and vpos position
5873 so that they are relative to the starting point. */
5f5c8ee5
GM
5874 it->vpos -= nlines;
5875 it->current_y -= h;
2311178e 5876
5f5c8ee5
GM
5877 if (dy == 0)
5878 {
5879 /* DY == 0 means move to the start of the screen line. The
5880 value of nlines is > 0 if continuation lines were involved. */
5881 if (nlines > 0)
5882 move_it_by_lines (it, nlines, 1);
5883 xassert (IT_CHARPOS (*it) <= start_pos);
5884 }
ccbb9ed2 5885 else
5f5c8ee5 5886 {
ccbb9ed2
RS
5887 /* The y-position we try to reach, relative to *IT.
5888 Note that H has been subtracted in front of the if-statement. */
5f5c8ee5 5889 int target_y = it->current_y + h - dy;
79ddf6f7
GM
5890 int y0 = it3.current_y;
5891 int y1 = line_bottom_y (&it3);
5892 int line_height = y1 - y0;
f7ccfc8c 5893
5f5c8ee5
GM
5894 /* If we did not reach target_y, try to move further backward if
5895 we can. If we moved too far backward, try to move forward. */
5896 if (target_y < it->current_y
79ddf6f7
GM
5897 /* This is heuristic. In a window that's 3 lines high, with
5898 a line height of 13 pixels each, recentering with point
5899 on the bottom line will try to move -39/2 = 19 pixels
5900 backward. Try to avoid moving into the first line. */
798dbe1f 5901 && it->current_y - target_y > line_height / 3 * 2
5f5c8ee5
GM
5902 && IT_CHARPOS (*it) > BEGV)
5903 {
f7ccfc8c
GM
5904 TRACE_MOVE ((stderr, " not far enough -> move_vert %d\n",
5905 target_y - it->current_y));
5f5c8ee5
GM
5906 move_it_vertically (it, target_y - it->current_y);
5907 xassert (IT_CHARPOS (*it) >= BEGV);
5908 }
5909 else if (target_y >= it->current_y + line_height
5910 && IT_CHARPOS (*it) < ZV)
5911 {
55591976 5912 /* Should move forward by at least one line, maybe more.
2311178e 5913
55591976
GM
5914 Note: Calling move_it_by_lines can be expensive on
5915 terminal frames, where compute_motion is used (via
5916 vmotion) to do the job, when there are very long lines
5917 and truncate-lines is nil. That's the reason for
5918 treating terminal frames specially here. */
2311178e 5919
55591976
GM
5920 if (!FRAME_WINDOW_P (it->f))
5921 move_it_vertically (it, target_y - (it->current_y + line_height));
5922 else
f7ccfc8c 5923 {
55591976
GM
5924 do
5925 {
5926 move_it_by_lines (it, 1, 1);
5927 }
5928 while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
f7ccfc8c 5929 }
f7ccfc8c 5930
5f5c8ee5
GM
5931 xassert (IT_CHARPOS (*it) >= BEGV);
5932 }
5933 }
5934}
5935
5936
5937/* Move IT by a specified amount of pixel lines DY. DY negative means
5938 move backwards. DY = 0 means move to start of screen line. At the
5939 end, IT will be on the start of a screen line. */
5940
2311178e 5941void
5f5c8ee5
GM
5942move_it_vertically (it, dy)
5943 struct it *it;
5944 int dy;
5945{
5946 if (dy <= 0)
5947 move_it_vertically_backward (it, -dy);
5948 else if (dy > 0)
5949 {
47589c8c 5950 TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
5f5c8ee5
GM
5951 move_it_to (it, ZV, -1, it->current_y + dy, -1,
5952 MOVE_TO_POS | MOVE_TO_Y);
47589c8c 5953 TRACE_MOVE ((stderr, "move_it_v: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5954
5955 /* If buffer ends in ZV without a newline, move to the start of
5956 the line to satisfy the post-condition. */
5957 if (IT_CHARPOS (*it) == ZV
5958 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
5959 move_it_by_lines (it, 0, 0);
5960 }
5961}
5962
5963
47fc2c10
GM
5964/* Move iterator IT past the end of the text line it is in. */
5965
5966void
5967move_it_past_eol (it)
5968 struct it *it;
5969{
5970 enum move_it_result rc;
2311178e 5971
47fc2c10
GM
5972 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
5973 if (rc == MOVE_NEWLINE_OR_CR)
5974 set_iterator_to_next (it, 0);
5975}
5976
5977
2c79b732
GM
5978#if 0 /* Currently not used. */
5979
5f5c8ee5
GM
5980/* Return non-zero if some text between buffer positions START_CHARPOS
5981 and END_CHARPOS is invisible. IT->window is the window for text
5982 property lookup. */
5983
5984static int
5985invisible_text_between_p (it, start_charpos, end_charpos)
5986 struct it *it;
5987 int start_charpos, end_charpos;
5988{
5f5c8ee5
GM
5989 Lisp_Object prop, limit;
5990 int invisible_found_p;
2311178e 5991
5f5c8ee5
GM
5992 xassert (it != NULL && start_charpos <= end_charpos);
5993
5994 /* Is text at START invisible? */
5995 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
5996 it->window);
5997 if (TEXT_PROP_MEANS_INVISIBLE (prop))
5998 invisible_found_p = 1;
5999 else
6000 {
016b5642
MB
6001 limit = Fnext_single_char_property_change (make_number (start_charpos),
6002 Qinvisible, Qnil,
6003 make_number (end_charpos));
5f5c8ee5
GM
6004 invisible_found_p = XFASTINT (limit) < end_charpos;
6005 }
6006
6007 return invisible_found_p;
5f5c8ee5
GM
6008}
6009
2c79b732
GM
6010#endif /* 0 */
6011
5f5c8ee5
GM
6012
6013/* Move IT by a specified number DVPOS of screen lines down. DVPOS
6014 negative means move up. DVPOS == 0 means move to the start of the
6015 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
6016 NEED_Y_P is zero, IT->current_y will be left unchanged.
6017
6018 Further optimization ideas: If we would know that IT->f doesn't use
6019 a face with proportional font, we could be faster for
6020 truncate-lines nil. */
6021
6022void
6023move_it_by_lines (it, dvpos, need_y_p)
6024 struct it *it;
6025 int dvpos, need_y_p;
6026{
6027 struct position pos;
2311178e 6028
5f5c8ee5
GM
6029 if (!FRAME_WINDOW_P (it->f))
6030 {
6031 struct text_pos textpos;
2311178e 6032
5f5c8ee5
GM
6033 /* We can use vmotion on frames without proportional fonts. */
6034 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
6035 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
6036 reseat (it, textpos, 1);
6037 it->vpos += pos.vpos;
6038 it->current_y += pos.vpos;
6039 }
6040 else if (dvpos == 0)
6041 {
6042 /* DVPOS == 0 means move to the start of the screen line. */
6043 move_it_vertically_backward (it, 0);
6044 xassert (it->current_x == 0 && it->hpos == 0);
6045 }
6046 else if (dvpos > 0)
2c79b732 6047 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
5f5c8ee5
GM
6048 else
6049 {
6050 struct it it2;
6051 int start_charpos, i;
2311178e 6052
e8660d73
GM
6053 /* Start at the beginning of the screen line containing IT's
6054 position. */
6055 move_it_vertically_backward (it, 0);
2311178e 6056
5f5c8ee5
GM
6057 /* Go back -DVPOS visible lines and reseat the iterator there. */
6058 start_charpos = IT_CHARPOS (*it);
6059 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
6060 back_to_previous_visible_line_start (it);
6061 reseat (it, it->current.pos, 1);
6062 it->current_x = it->hpos = 0;
6063
6064 /* Above call may have moved too far if continuation lines
6065 are involved. Scan forward and see if it did. */
6066 it2 = *it;
6067 it2.vpos = it2.current_y = 0;
6068 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
6069 it->vpos -= it2.vpos;
6070 it->current_y -= it2.current_y;
6071 it->current_x = it->hpos = 0;
6072
6073 /* If we moved too far, move IT some lines forward. */
6074 if (it2.vpos > -dvpos)
6075 {
6076 int delta = it2.vpos + dvpos;
6077 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
6078 }
6079 }
6080}
6081
3824b1a6
AS
6082/* Return 1 if IT points into the middle of a display vector. */
6083
6084int
6085in_display_vector_p (it)
6086 struct it *it;
6087{
6088 return (it->method == next_element_from_display_vector
6089 && it->current.dpvec_index > 0
6090 && it->dpvec + it->current.dpvec_index != it->dpend);
6091}
5f5c8ee5
GM
6092
6093\f
6094/***********************************************************************
6095 Messages
6096 ***********************************************************************/
6097
6098
937248bc
GM
6099/* Add a message with format string FORMAT and arguments ARG1 and ARG2
6100 to *Messages*. */
6101
6102void
6103add_to_log (format, arg1, arg2)
6104 char *format;
6105 Lisp_Object arg1, arg2;
6106{
6107 Lisp_Object args[3];
6108 Lisp_Object msg, fmt;
6109 char *buffer;
6110 int len;
6111 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
6112
ae794295
GM
6113 /* Do nothing if called asynchronously. Inserting text into
6114 a buffer may call after-change-functions and alike and
6115 that would means running Lisp asynchronously. */
6116 if (handling_signal)
6117 return;
6118
937248bc
GM
6119 fmt = msg = Qnil;
6120 GCPRO4 (fmt, msg, arg1, arg2);
2311178e 6121
937248bc
GM
6122 args[0] = fmt = build_string (format);
6123 args[1] = arg1;
6124 args[2] = arg2;
6fc556fd 6125 msg = Fformat (3, args);
937248bc 6126
2051c264 6127 len = SBYTES (msg) + 1;
937248bc 6128 buffer = (char *) alloca (len);
2051c264 6129 bcopy (SDATA (msg), buffer, len);
2311178e 6130
796184bc 6131 message_dolog (buffer, len - 1, 1, 0);
937248bc
GM
6132 UNGCPRO;
6133}
6134
6135
5f5c8ee5
GM
6136/* Output a newline in the *Messages* buffer if "needs" one. */
6137
6138void
6139message_log_maybe_newline ()
6140{
6141 if (message_log_need_newline)
6142 message_dolog ("", 0, 1, 0);
6143}
6144
6145
1e313f28 6146/* Add a string M of length NBYTES to the message log, optionally
5f5c8ee5
GM
6147 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
6148 nonzero, means interpret the contents of M as multibyte. This
6149 function calls low-level routines in order to bypass text property
6150 hooks, etc. which might not be safe to run. */
6151
6152void
1e313f28 6153message_dolog (m, nbytes, nlflag, multibyte)
50f80c2f 6154 const char *m;
1e313f28 6155 int nbytes, nlflag, multibyte;
5f5c8ee5 6156{
a67e162b
RS
6157 if (!NILP (Vmemory_full))
6158 return;
6159
5f5c8ee5
GM
6160 if (!NILP (Vmessage_log_max))
6161 {
6162 struct buffer *oldbuf;
6163 Lisp_Object oldpoint, oldbegv, oldzv;
6164 int old_windows_or_buffers_changed = windows_or_buffers_changed;
6165 int point_at_end = 0;
6166 int zv_at_end = 0;
6167 Lisp_Object old_deactivate_mark, tem;
6052529b 6168 struct gcpro gcpro1;
5f5c8ee5
GM
6169
6170 old_deactivate_mark = Vdeactivate_mark;
6171 oldbuf = current_buffer;
6a94510a 6172 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
5f5c8ee5
GM
6173 current_buffer->undo_list = Qt;
6174
b14bc55e
RS
6175 oldpoint = message_dolog_marker1;
6176 set_marker_restricted (oldpoint, make_number (PT), Qnil);
6177 oldbegv = message_dolog_marker2;
6178 set_marker_restricted (oldbegv, make_number (BEGV), Qnil);
6179 oldzv = message_dolog_marker3;
6180 set_marker_restricted (oldzv, make_number (ZV), Qnil);
6181 GCPRO1 (old_deactivate_mark);
5f5c8ee5
GM
6182
6183 if (PT == Z)
6184 point_at_end = 1;
6185 if (ZV == Z)
6186 zv_at_end = 1;
6187
6188 BEGV = BEG;
6189 BEGV_BYTE = BEG_BYTE;
6190 ZV = Z;
6191 ZV_BYTE = Z_BYTE;
6192 TEMP_SET_PT_BOTH (Z, Z_BYTE);
6193
6194 /* Insert the string--maybe converting multibyte to single byte
6195 or vice versa, so that all the text fits the buffer. */
6196 if (multibyte
6197 && NILP (current_buffer->enable_multibyte_characters))
6198 {
1e313f28 6199 int i, c, char_bytes;
5f5c8ee5 6200 unsigned char work[1];
2311178e 6201
5f5c8ee5
GM
6202 /* Convert a multibyte string to single-byte
6203 for the *Message* buffer. */
6e57ec5e 6204 for (i = 0; i < nbytes; i += char_bytes)
5f5c8ee5 6205 {
1e313f28 6206 c = string_char_and_length (m + i, nbytes - i, &char_bytes);
5f5c8ee5
GM
6207 work[0] = (SINGLE_BYTE_CHAR_P (c)
6208 ? c
6209 : multibyte_char_to_unibyte (c, Qnil));
6210 insert_1_both (work, 1, 1, 1, 0, 0);
6211 }
6212 }
6213 else if (! multibyte
6214 && ! NILP (current_buffer->enable_multibyte_characters))
6215 {
1e313f28 6216 int i, c, char_bytes;
5f5c8ee5 6217 unsigned char *msg = (unsigned char *) m;
260a86a0 6218 unsigned char str[MAX_MULTIBYTE_LENGTH];
5f5c8ee5
GM
6219 /* Convert a single-byte string to multibyte
6220 for the *Message* buffer. */
1e313f28 6221 for (i = 0; i < nbytes; i++)
5f5c8ee5
GM
6222 {
6223 c = unibyte_char_to_multibyte (msg[i]);
1e313f28
GM
6224 char_bytes = CHAR_STRING (c, str);
6225 insert_1_both (str, 1, char_bytes, 1, 0, 0);
5f5c8ee5
GM
6226 }
6227 }
1e313f28
GM
6228 else if (nbytes)
6229 insert_1 (m, nbytes, 1, 0, 0);
5f5c8ee5
GM
6230
6231 if (nlflag)
6232 {
6233 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
6234 insert_1 ("\n", 1, 1, 0, 0);
6235
6236 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
6237 this_bol = PT;
6238 this_bol_byte = PT_BYTE;
6239
b14bc55e
RS
6240 /* See if this line duplicates the previous one.
6241 If so, combine duplicates. */
5f5c8ee5
GM
6242 if (this_bol > BEG)
6243 {
6244 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
6245 prev_bol = PT;
6246 prev_bol_byte = PT_BYTE;
6247
6248 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
6249 this_bol, this_bol_byte);
6250 if (dup)
6251 {
6252 del_range_both (prev_bol, prev_bol_byte,
6253 this_bol, this_bol_byte, 0);
6254 if (dup > 1)
6255 {
6256 char dupstr[40];
6257 int duplen;
6258
6259 /* If you change this format, don't forget to also
6260 change message_log_check_duplicate. */
6261 sprintf (dupstr, " [%d times]", dup);
6262 duplen = strlen (dupstr);
6263 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
6264 insert_1 (dupstr, duplen, 1, 0, 1);
6265 }
6266 }
6267 }
6268
b14bc55e
RS
6269 /* If we have more than the desired maximum number of lines
6270 in the *Messages* buffer now, delete the oldest ones.
6271 This is safe because we don't have undo in this buffer. */
6272
5f5c8ee5
GM
6273 if (NATNUMP (Vmessage_log_max))
6274 {
6275 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
6276 -XFASTINT (Vmessage_log_max) - 1, 0);
6277 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
6278 }
6279 }
6280 BEGV = XMARKER (oldbegv)->charpos;
6281 BEGV_BYTE = marker_byte_position (oldbegv);
6282
6283 if (zv_at_end)
6284 {
6285 ZV = Z;
6286 ZV_BYTE = Z_BYTE;
6287 }
6288 else
6289 {
6290 ZV = XMARKER (oldzv)->charpos;
6291 ZV_BYTE = marker_byte_position (oldzv);
6292 }
6293
6294 if (point_at_end)
6295 TEMP_SET_PT_BOTH (Z, Z_BYTE);
6296 else
6297 /* We can't do Fgoto_char (oldpoint) because it will run some
6298 Lisp code. */
6299 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
6300 XMARKER (oldpoint)->bytepos);
6301
6302 UNGCPRO;
cfea0546
SM
6303 unchain_marker (XMARKER (oldpoint));
6304 unchain_marker (XMARKER (oldbegv));
6305 unchain_marker (XMARKER (oldzv));
5f5c8ee5
GM
6306
6307 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
6308 set_buffer_internal (oldbuf);
6309 if (NILP (tem))
6310 windows_or_buffers_changed = old_windows_or_buffers_changed;
6311 message_log_need_newline = !nlflag;
6312 Vdeactivate_mark = old_deactivate_mark;
6313 }
6314}
6315
6316
6317/* We are at the end of the buffer after just having inserted a newline.
6318 (Note: We depend on the fact we won't be crossing the gap.)
6319 Check to see if the most recent message looks a lot like the previous one.
6320 Return 0 if different, 1 if the new one should just replace it, or a
6321 value N > 1 if we should also append " [N times]". */
6322
6323static int
6324message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
6325 int prev_bol, this_bol;
6326 int prev_bol_byte, this_bol_byte;
6327{
6328 int i;
6329 int len = Z_BYTE - 1 - this_bol_byte;
6330 int seen_dots = 0;
6331 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
6332 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
6333
6334 for (i = 0; i < len; i++)
6335 {
509633e3 6336 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.')
5f5c8ee5
GM
6337 seen_dots = 1;
6338 if (p1[i] != p2[i])
6339 return seen_dots;
6340 }
6341 p1 += len;
6342 if (*p1 == '\n')
6343 return 2;
6344 if (*p1++ == ' ' && *p1++ == '[')
6345 {
6346 int n = 0;
6347 while (*p1 >= '0' && *p1 <= '9')
6348 n = n * 10 + *p1++ - '0';
6349 if (strncmp (p1, " times]\n", 8) == 0)
6350 return n+1;
6351 }
6352 return 0;
6353}
6354
6355
1e313f28
GM
6356/* Display an echo area message M with a specified length of NBYTES
6357 bytes. The string may include null characters. If M is 0, clear
6358 out any existing message, and let the mini-buffer text show
6359 through.
5f5c8ee5
GM
6360
6361 The buffer M must continue to exist until after the echo area gets
6362 cleared or some other message gets displayed there. This means do
6363 not pass text that is stored in a Lisp string; do not pass text in
6364 a buffer that was alloca'd. */
6365
6366void
1e313f28 6367message2 (m, nbytes, multibyte)
50f80c2f 6368 const char *m;
1e313f28 6369 int nbytes;
5f5c8ee5
GM
6370 int multibyte;
6371{
6372 /* First flush out any partial line written with print. */
6373 message_log_maybe_newline ();
6374 if (m)
1e313f28
GM
6375 message_dolog (m, nbytes, 1, multibyte);
6376 message2_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
6377}
6378
6379
6380/* The non-logging counterpart of message2. */
6381
6382void
1e313f28 6383message2_nolog (m, nbytes, multibyte)
50f80c2f 6384 const char *m;
e3383b6f 6385 int nbytes, multibyte;
5f5c8ee5 6386{
886bd6f2 6387 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6388 message_enable_multibyte = multibyte;
6389
6390 if (noninteractive)
6391 {
6392 if (noninteractive_need_newline)
6393 putc ('\n', stderr);
6394 noninteractive_need_newline = 0;
6395 if (m)
1e313f28 6396 fwrite (m, nbytes, 1, stderr);
5f5c8ee5
GM
6397 if (cursor_in_echo_area == 0)
6398 fprintf (stderr, "\n");
6399 fflush (stderr);
6400 }
6401 /* A null message buffer means that the frame hasn't really been
6402 initialized yet. Error messages get reported properly by
6403 cmd_error, so this must be just an informative message; toss it. */
2311178e 6404 else if (INTERACTIVE
886bd6f2
GM
6405 && sf->glyphs_initialized_p
6406 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
6407 {
6408 Lisp_Object mini_window;
6409 struct frame *f;
6410
6411 /* Get the frame containing the mini-buffer
6412 that the selected frame is using. */
886bd6f2 6413 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6414 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6415
6416 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 6417 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
6418 && ! FRAME_VISIBLE_P (f))
6419 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
6420
6421 if (m)
6422 {
1e313f28 6423 set_message (m, Qnil, nbytes, multibyte);
5f5c8ee5
GM
6424 if (minibuffer_auto_raise)
6425 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
6426 }
6427 else
c6e89d6c 6428 clear_message (1, 1);
5f5c8ee5 6429
c6e89d6c 6430 do_pending_window_change (0);
5f5c8ee5 6431 echo_area_display (1);
c6e89d6c 6432 do_pending_window_change (0);
5f5c8ee5
GM
6433 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
6434 (*frame_up_to_date_hook) (f);
6435 }
6436}
6437
6438
c6e89d6c
GM
6439/* Display an echo area message M with a specified length of NBYTES
6440 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
6441 string, clear out any existing message, and let the mini-buffer
6442 text show through. */
6443
6444void
c6e89d6c 6445message3 (m, nbytes, multibyte)
5f5c8ee5 6446 Lisp_Object m;
c6e89d6c 6447 int nbytes;
5f5c8ee5
GM
6448 int multibyte;
6449{
6450 struct gcpro gcpro1;
6451
6452 GCPRO1 (m);
2311178e 6453
5f5c8ee5
GM
6454 /* First flush out any partial line written with print. */
6455 message_log_maybe_newline ();
6456 if (STRINGP (m))
2051c264 6457 message_dolog (SDATA (m), nbytes, 1, multibyte);
c6e89d6c 6458 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
6459
6460 UNGCPRO;
6461}
6462
6463
6464/* The non-logging version of message3. */
6465
6466void
c6e89d6c 6467message3_nolog (m, nbytes, multibyte)
5f5c8ee5 6468 Lisp_Object m;
c6e89d6c 6469 int nbytes, multibyte;
5f5c8ee5 6470{
886bd6f2 6471 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6472 message_enable_multibyte = multibyte;
6473
6474 if (noninteractive)
6475 {
6476 if (noninteractive_need_newline)
6477 putc ('\n', stderr);
6478 noninteractive_need_newline = 0;
6479 if (STRINGP (m))
2051c264 6480 fwrite (SDATA (m), nbytes, 1, stderr);
5f5c8ee5
GM
6481 if (cursor_in_echo_area == 0)
6482 fprintf (stderr, "\n");
6483 fflush (stderr);
6484 }
6485 /* A null message buffer means that the frame hasn't really been
6486 initialized yet. Error messages get reported properly by
6487 cmd_error, so this must be just an informative message; toss it. */
2311178e 6488 else if (INTERACTIVE
886bd6f2
GM
6489 && sf->glyphs_initialized_p
6490 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
6491 {
6492 Lisp_Object mini_window;
c6e89d6c 6493 Lisp_Object frame;
5f5c8ee5
GM
6494 struct frame *f;
6495
6496 /* Get the frame containing the mini-buffer
6497 that the selected frame is using. */
886bd6f2 6498 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6499 frame = XWINDOW (mini_window)->frame;
6500 f = XFRAME (frame);
5f5c8ee5
GM
6501
6502 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 6503 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
6504 && !FRAME_VISIBLE_P (f))
6505 Fmake_frame_visible (frame);
5f5c8ee5 6506
2051c264 6507 if (STRINGP (m) && SCHARS (m) > 0)
5f5c8ee5 6508 {
c6e89d6c 6509 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
6510 if (minibuffer_auto_raise)
6511 Fraise_frame (frame);
5f5c8ee5
GM
6512 }
6513 else
c6e89d6c 6514 clear_message (1, 1);
5f5c8ee5 6515
c6e89d6c 6516 do_pending_window_change (0);
5f5c8ee5 6517 echo_area_display (1);
c6e89d6c 6518 do_pending_window_change (0);
5f5c8ee5
GM
6519 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
6520 (*frame_up_to_date_hook) (f);
6521 }
6522}
6523
6524
6525/* Display a null-terminated echo area message M. If M is 0, clear
6526 out any existing message, and let the mini-buffer text show through.
6527
6528 The buffer M must continue to exist until after the echo area gets
6529 cleared or some other message gets displayed there. Do not pass
6530 text that is stored in a Lisp string. Do not pass text in a buffer
6531 that was alloca'd. */
6532
6533void
6534message1 (m)
6535 char *m;
6536{
6537 message2 (m, (m ? strlen (m) : 0), 0);
6538}
6539
6540
6541/* The non-logging counterpart of message1. */
6542
6543void
6544message1_nolog (m)
6545 char *m;
6546{
6547 message2_nolog (m, (m ? strlen (m) : 0), 0);
6548}
6549
6550/* Display a message M which contains a single %s
6551 which gets replaced with STRING. */
6552
6553void
6554message_with_string (m, string, log)
6555 char *m;
6556 Lisp_Object string;
6557 int log;
6558{
5b6d51b6
RS
6559 CHECK_STRING (string);
6560
5f5c8ee5
GM
6561 if (noninteractive)
6562 {
6563 if (m)
6564 {
6565 if (noninteractive_need_newline)
6566 putc ('\n', stderr);
6567 noninteractive_need_newline = 0;
2051c264 6568 fprintf (stderr, m, SDATA (string));
5f5c8ee5
GM
6569 if (cursor_in_echo_area == 0)
6570 fprintf (stderr, "\n");
6571 fflush (stderr);
6572 }
6573 }
6574 else if (INTERACTIVE)
6575 {
6576 /* The frame whose minibuffer we're going to display the message on.
6577 It may be larger than the selected frame, so we need
6578 to use its buffer, not the selected frame's buffer. */
6579 Lisp_Object mini_window;
886bd6f2 6580 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6581
6582 /* Get the frame containing the minibuffer
6583 that the selected frame is using. */
886bd6f2 6584 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6585 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6586
6587 /* A null message buffer means that the frame hasn't really been
6588 initialized yet. Error messages get reported properly by
6589 cmd_error, so this must be just an informative message; toss it. */
6590 if (FRAME_MESSAGE_BUF (f))
6591 {
eb484132
GM
6592 Lisp_Object args[2], message;
6593 struct gcpro gcpro1, gcpro2;
5f5c8ee5 6594
eb484132
GM
6595 args[0] = build_string (m);
6596 args[1] = message = string;
78e17433 6597 GCPRO2 (args[0], message);
eb484132 6598 gcpro1.nvars = 2;
2311178e 6599
eb484132 6600 message = Fformat (2, args);
5f5c8ee5
GM
6601
6602 if (log)
d5db4077 6603 message3 (message, SBYTES (message), STRING_MULTIBYTE (message));
5f5c8ee5 6604 else
d5db4077 6605 message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message));
eb484132
GM
6606
6607 UNGCPRO;
5f5c8ee5
GM
6608
6609 /* Print should start at the beginning of the message
6610 buffer next time. */
6611 message_buf_print = 0;
6612 }
6613 }
6614}
6615
6616
5f5c8ee5
GM
6617/* Dump an informative message to the minibuf. If M is 0, clear out
6618 any existing message, and let the mini-buffer text show through. */
6619
6620/* VARARGS 1 */
6621void
6622message (m, a1, a2, a3)
6623 char *m;
6624 EMACS_INT a1, a2, a3;
6625{
6626 if (noninteractive)
6627 {
6628 if (m)
6629 {
6630 if (noninteractive_need_newline)
6631 putc ('\n', stderr);
6632 noninteractive_need_newline = 0;
6633 fprintf (stderr, m, a1, a2, a3);
6634 if (cursor_in_echo_area == 0)
6635 fprintf (stderr, "\n");
6636 fflush (stderr);
6637 }
6638 }
6639 else if (INTERACTIVE)
6640 {
6641 /* The frame whose mini-buffer we're going to display the message
6642 on. It may be larger than the selected frame, so we need to
6643 use its buffer, not the selected frame's buffer. */
6644 Lisp_Object mini_window;
886bd6f2 6645 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6646
6647 /* Get the frame containing the mini-buffer
6648 that the selected frame is using. */
886bd6f2 6649 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6650 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6651
6652 /* A null message buffer means that the frame hasn't really been
6653 initialized yet. Error messages get reported properly by
6654 cmd_error, so this must be just an informative message; toss
6655 it. */
6656 if (FRAME_MESSAGE_BUF (f))
6657 {
6658 if (m)
6659 {
6660 int len;
6661#ifdef NO_ARG_ARRAY
6662 char *a[3];
6663 a[0] = (char *) a1;
6664 a[1] = (char *) a2;
6665 a[2] = (char *) a3;
6666
6667 len = doprnt (FRAME_MESSAGE_BUF (f),
6668 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
6669#else
6670 len = doprnt (FRAME_MESSAGE_BUF (f),
6671 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
6672 (char **) &a1);
6673#endif /* NO_ARG_ARRAY */
6674
6675 message2 (FRAME_MESSAGE_BUF (f), len, 0);
6676 }
6677 else
6678 message1 (0);
6679
6680 /* Print should start at the beginning of the message
6681 buffer next time. */
6682 message_buf_print = 0;
6683 }
6684 }
6685}
6686
6687
6688/* The non-logging version of message. */
6689
6690void
6691message_nolog (m, a1, a2, a3)
6692 char *m;
6693 EMACS_INT a1, a2, a3;
6694{
6695 Lisp_Object old_log_max;
6696 old_log_max = Vmessage_log_max;
6697 Vmessage_log_max = Qnil;
6698 message (m, a1, a2, a3);
6699 Vmessage_log_max = old_log_max;
6700}
6701
6702
c6e89d6c
GM
6703/* Display the current message in the current mini-buffer. This is
6704 only called from error handlers in process.c, and is not time
6705 critical. */
5f5c8ee5
GM
6706
6707void
6708update_echo_area ()
6709{
c6e89d6c
GM
6710 if (!NILP (echo_area_buffer[0]))
6711 {
6712 Lisp_Object string;
6713 string = Fcurrent_message ();
2311178e 6714 message3 (string, SBYTES (string),
c6e89d6c
GM
6715 !NILP (current_buffer->enable_multibyte_characters));
6716 }
6717}
6718
6719
a67e162b
RS
6720/* Make sure echo area buffers in `echo_buffers' are live.
6721 If they aren't, make new ones. */
5bcfeb49
GM
6722
6723static void
6724ensure_echo_area_buffers ()
6725{
6726 int i;
6727
6728 for (i = 0; i < 2; ++i)
6729 if (!BUFFERP (echo_buffer[i])
6730 || NILP (XBUFFER (echo_buffer[i])->name))
6731 {
6732 char name[30];
ff3d9573
GM
6733 Lisp_Object old_buffer;
6734 int j;
6735
6736 old_buffer = echo_buffer[i];
5bcfeb49
GM
6737 sprintf (name, " *Echo Area %d*", i);
6738 echo_buffer[i] = Fget_buffer_create (build_string (name));
ad4f174e 6739 XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
ff3d9573
GM
6740
6741 for (j = 0; j < 2; ++j)
6742 if (EQ (old_buffer, echo_area_buffer[j]))
6743 echo_area_buffer[j] = echo_buffer[i];
5bcfeb49
GM
6744 }
6745}
6746
6747
23a96c77 6748/* Call FN with args A1..A4 with either the current or last displayed
c6e89d6c
GM
6749 echo_area_buffer as current buffer.
6750
6751 WHICH zero means use the current message buffer
6752 echo_area_buffer[0]. If that is nil, choose a suitable buffer
6753 from echo_buffer[] and clear it.
6754
6755 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
6756 suitable buffer from echo_buffer[] and clear it.
6757
6758 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
6759 that the current message becomes the last displayed one, make
6760 choose a suitable buffer for echo_area_buffer[0], and clear it.
6761
4b41cebb 6762 Value is what FN returns. */
c6e89d6c
GM
6763
6764static int
23a96c77 6765with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
c6e89d6c
GM
6766 struct window *w;
6767 int which;
23dd2d97
KR
6768 int (*fn) P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
6769 EMACS_INT a1;
6770 Lisp_Object a2;
6771 EMACS_INT a3, a4;
c6e89d6c
GM
6772{
6773 Lisp_Object buffer;
15e26c76 6774 int this_one, the_other, clear_buffer_p, rc;
331379bf 6775 int count = SPECPDL_INDEX ();
c6e89d6c 6776
9583b2bb 6777 /* If buffers aren't live, make new ones. */
5bcfeb49 6778 ensure_echo_area_buffers ();
c6e89d6c
GM
6779
6780 clear_buffer_p = 0;
2311178e 6781
c6e89d6c
GM
6782 if (which == 0)
6783 this_one = 0, the_other = 1;
6784 else if (which > 0)
6785 this_one = 1, the_other = 0;
5f5c8ee5 6786 else
c6e89d6c
GM
6787 {
6788 this_one = 0, the_other = 1;
6789 clear_buffer_p = 1;
2311178e 6790
c6e89d6c
GM
6791 /* We need a fresh one in case the current echo buffer equals
6792 the one containing the last displayed echo area message. */
6793 if (!NILP (echo_area_buffer[this_one])
6794 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
6795 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
6796 }
6797
6798 /* Choose a suitable buffer from echo_buffer[] is we don't
6799 have one. */
6800 if (NILP (echo_area_buffer[this_one]))
6801 {
6802 echo_area_buffer[this_one]
6803 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
6804 ? echo_buffer[the_other]
6805 : echo_buffer[this_one]);
6806 clear_buffer_p = 1;
6807 }
6808
6809 buffer = echo_area_buffer[this_one];
6810
1013f4e3
GM
6811 /* Don't get confused by reusing the buffer used for echoing
6812 for a different purpose. */
032906b1 6813 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
1013f4e3
GM
6814 cancel_echoing ();
6815
c6e89d6c
GM
6816 record_unwind_protect (unwind_with_echo_area_buffer,
6817 with_echo_area_buffer_unwind_data (w));
6818
6819 /* Make the echo area buffer current. Note that for display
6820 purposes, it is not necessary that the displayed window's buffer
6821 == current_buffer, except for text property lookup. So, let's
6822 only set that buffer temporarily here without doing a full
6823 Fset_window_buffer. We must also change w->pointm, though,
6824 because otherwise an assertions in unshow_buffer fails, and Emacs
6825 aborts. */
9142dd5b 6826 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
6827 if (w)
6828 {
6829 w->buffer = buffer;
6830 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
6831 }
ad4f174e 6832
c6e89d6c
GM
6833 current_buffer->undo_list = Qt;
6834 current_buffer->read_only = Qnil;
bbbf6d06 6835 specbind (Qinhibit_read_only, Qt);
0b04fa5f 6836 specbind (Qinhibit_modification_hooks, Qt);
c6e89d6c
GM
6837
6838 if (clear_buffer_p && Z > BEG)
6839 del_range (BEG, Z);
6840
6841 xassert (BEGV >= BEG);
6842 xassert (ZV <= Z && ZV >= BEGV);
6843
23a96c77 6844 rc = fn (a1, a2, a3, a4);
c6e89d6c
GM
6845
6846 xassert (BEGV >= BEG);
6847 xassert (ZV <= Z && ZV >= BEGV);
6848
6849 unbind_to (count, Qnil);
6850 return rc;
5f5c8ee5
GM
6851}
6852
6853
c6e89d6c
GM
6854/* Save state that should be preserved around the call to the function
6855 FN called in with_echo_area_buffer. */
5f5c8ee5 6856
c6e89d6c
GM
6857static Lisp_Object
6858with_echo_area_buffer_unwind_data (w)
6859 struct window *w;
5f5c8ee5 6860{
c6e89d6c
GM
6861 int i = 0;
6862 Lisp_Object vector;
5f5c8ee5 6863
c6e89d6c
GM
6864 /* Reduce consing by keeping one vector in
6865 Vwith_echo_area_save_vector. */
6866 vector = Vwith_echo_area_save_vector;
6867 Vwith_echo_area_save_vector = Qnil;
2311178e 6868
c6e89d6c 6869 if (NILP (vector))
9142dd5b 6870 vector = Fmake_vector (make_number (7), Qnil);
2311178e 6871
a61b7058
GM
6872 XSETBUFFER (AREF (vector, i), current_buffer); ++i;
6873 AREF (vector, i) = Vdeactivate_mark, ++i;
6874 AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
2311178e 6875
c6e89d6c
GM
6876 if (w)
6877 {
a61b7058
GM
6878 XSETWINDOW (AREF (vector, i), w); ++i;
6879 AREF (vector, i) = w->buffer; ++i;
6880 AREF (vector, i) = make_number (XMARKER (w->pointm)->charpos); ++i;
6881 AREF (vector, i) = make_number (XMARKER (w->pointm)->bytepos); ++i;
c6e89d6c
GM
6882 }
6883 else
6884 {
6885 int end = i + 4;
a61b7058
GM
6886 for (; i < end; ++i)
6887 AREF (vector, i) = Qnil;
c6e89d6c 6888 }
5f5c8ee5 6889
a61b7058 6890 xassert (i == ASIZE (vector));
c6e89d6c
GM
6891 return vector;
6892}
5f5c8ee5 6893
5f5c8ee5 6894
c6e89d6c
GM
6895/* Restore global state from VECTOR which was created by
6896 with_echo_area_buffer_unwind_data. */
6897
6898static Lisp_Object
6899unwind_with_echo_area_buffer (vector)
6900 Lisp_Object vector;
6901{
bbbf6d06
GM
6902 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
6903 Vdeactivate_mark = AREF (vector, 1);
6904 windows_or_buffers_changed = XFASTINT (AREF (vector, 2));
c6e89d6c 6905
bbbf6d06 6906 if (WINDOWP (AREF (vector, 3)))
c6e89d6c
GM
6907 {
6908 struct window *w;
6909 Lisp_Object buffer, charpos, bytepos;
2311178e 6910
bbbf6d06
GM
6911 w = XWINDOW (AREF (vector, 3));
6912 buffer = AREF (vector, 4);
6913 charpos = AREF (vector, 5);
6914 bytepos = AREF (vector, 6);
2311178e 6915
c6e89d6c
GM
6916 w->buffer = buffer;
6917 set_marker_both (w->pointm, buffer,
6918 XFASTINT (charpos), XFASTINT (bytepos));
6919 }
6920
6921 Vwith_echo_area_save_vector = vector;
6922 return Qnil;
6923}
6924
6925
6926/* Set up the echo area for use by print functions. MULTIBYTE_P
6927 non-zero means we will print multibyte. */
6928
6929void
6930setup_echo_area_for_printing (multibyte_p)
6931 int multibyte_p;
6932{
03b0a4b4
RS
6933 /* If we can't find an echo area any more, exit. */
6934 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
6935 Fkill_emacs (Qnil);
6936
5bcfeb49
GM
6937 ensure_echo_area_buffers ();
6938
c6e89d6c
GM
6939 if (!message_buf_print)
6940 {
6941 /* A message has been output since the last time we printed.
6942 Choose a fresh echo area buffer. */
6943 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 6944 echo_area_buffer[0] = echo_buffer[1];
c6e89d6c
GM
6945 else
6946 echo_area_buffer[0] = echo_buffer[0];
6947
6948 /* Switch to that buffer and clear it. */
6949 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
ab2c5f0a 6950 current_buffer->truncate_lines = Qnil;
2311178e 6951
c6e89d6c 6952 if (Z > BEG)
bbbf6d06 6953 {
331379bf 6954 int count = SPECPDL_INDEX ();
bbbf6d06 6955 specbind (Qinhibit_read_only, Qt);
a67e162b 6956 /* Note that undo recording is always disabled. */
bbbf6d06
GM
6957 del_range (BEG, Z);
6958 unbind_to (count, Qnil);
6959 }
c6e89d6c
GM
6960 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
6961
6962 /* Set up the buffer for the multibyteness we need. */
6963 if (multibyte_p
6964 != !NILP (current_buffer->enable_multibyte_characters))
6965 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
6966
6967 /* Raise the frame containing the echo area. */
6968 if (minibuffer_auto_raise)
6969 {
886bd6f2 6970 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 6971 Lisp_Object mini_window;
886bd6f2 6972 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6973 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
6974 }
6975
8a4e3c0c 6976 message_log_maybe_newline ();
c6e89d6c
GM
6977 message_buf_print = 1;
6978 }
fa77249f
GM
6979 else
6980 {
6981 if (NILP (echo_area_buffer[0]))
6982 {
6983 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 6984 echo_area_buffer[0] = echo_buffer[1];
fa77249f
GM
6985 else
6986 echo_area_buffer[0] = echo_buffer[0];
6987 }
2311178e 6988
fa77249f 6989 if (current_buffer != XBUFFER (echo_area_buffer[0]))
ab2c5f0a
GM
6990 {
6991 /* Someone switched buffers between print requests. */
6992 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
6993 current_buffer->truncate_lines = Qnil;
6994 }
fa77249f 6995 }
c6e89d6c
GM
6996}
6997
6998
dd2eb166
GM
6999/* Display an echo area message in window W. Value is non-zero if W's
7000 height is changed. If display_last_displayed_message_p is
7001 non-zero, display the message that was last displayed, otherwise
7002 display the current message. */
c6e89d6c
GM
7003
7004static int
7005display_echo_area (w)
7006 struct window *w;
7007{
25edb08f
GM
7008 int i, no_message_p, window_height_changed_p, count;
7009
7010 /* Temporarily disable garbage collections while displaying the echo
7011 area. This is done because a GC can print a message itself.
7012 That message would modify the echo area buffer's contents while a
7013 redisplay of the buffer is going on, and seriously confuse
7014 redisplay. */
7015 count = inhibit_garbage_collection ();
dd2eb166
GM
7016
7017 /* If there is no message, we must call display_echo_area_1
7018 nevertheless because it resizes the window. But we will have to
7019 reset the echo_area_buffer in question to nil at the end because
7020 with_echo_area_buffer will sets it to an empty buffer. */
7021 i = display_last_displayed_message_p ? 1 : 0;
7022 no_message_p = NILP (echo_area_buffer[i]);
2311178e 7023
dd2eb166
GM
7024 window_height_changed_p
7025 = with_echo_area_buffer (w, display_last_displayed_message_p,
23a96c77 7026 display_echo_area_1,
23dd2d97 7027 (EMACS_INT) w, Qnil, 0, 0);
dd2eb166
GM
7028
7029 if (no_message_p)
7030 echo_area_buffer[i] = Qnil;
25edb08f
GM
7031
7032 unbind_to (count, Qnil);
dd2eb166 7033 return window_height_changed_p;
c6e89d6c
GM
7034}
7035
7036
7037/* Helper for display_echo_area. Display the current buffer which
23a96c77
GM
7038 contains the current echo area message in window W, a mini-window,
7039 a pointer to which is passed in A1. A2..A4 are currently not used.
c6e89d6c
GM
7040 Change the height of W so that all of the message is displayed.
7041 Value is non-zero if height of W was changed. */
7042
7043static int
23a96c77 7044display_echo_area_1 (a1, a2, a3, a4)
23dd2d97
KR
7045 EMACS_INT a1;
7046 Lisp_Object a2;
7047 EMACS_INT a3, a4;
c6e89d6c 7048{
23a96c77 7049 struct window *w = (struct window *) a1;
c6e89d6c 7050 Lisp_Object window;
c6e89d6c
GM
7051 struct text_pos start;
7052 int window_height_changed_p = 0;
7053
7054 /* Do this before displaying, so that we have a large enough glyph
7055 matrix for the display. */
92a90e89 7056 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
7057
7058 /* Display. */
7059 clear_glyph_matrix (w->desired_matrix);
7060 XSETWINDOW (window, w);
7061 SET_TEXT_POS (start, BEG, BEG_BYTE);
7062 try_window (window, start);
7063
c6e89d6c
GM
7064 return window_height_changed_p;
7065}
7066
7067
92a90e89 7068/* Resize the echo area window to exactly the size needed for the
6d004fea
GM
7069 currently displayed message, if there is one. If a mini-buffer
7070 is active, don't shrink it. */
92a90e89
GM
7071
7072void
308a74d8 7073resize_echo_area_exactly ()
92a90e89
GM
7074{
7075 if (BUFFERP (echo_area_buffer[0])
7076 && WINDOWP (echo_area_window))
7077 {
7078 struct window *w = XWINDOW (echo_area_window);
7079 int resized_p;
6d004fea
GM
7080 Lisp_Object resize_exactly;
7081
7082 if (minibuf_level == 0)
7083 resize_exactly = Qt;
7084 else
7085 resize_exactly = Qnil;
2311178e 7086
23a96c77 7087 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
6d004fea 7088 (EMACS_INT) w, resize_exactly, 0, 0);
92a90e89
GM
7089 if (resized_p)
7090 {
7091 ++windows_or_buffers_changed;
7092 ++update_mode_lines;
7093 redisplay_internal (0);
7094 }
7095 }
7096}
7097
7098
23a96c77 7099/* Callback function for with_echo_area_buffer, when used from
308a74d8 7100 resize_echo_area_exactly. A1 contains a pointer to the window to
6d004fea
GM
7101 resize, EXACTLY non-nil means resize the mini-window exactly to the
7102 size of the text displayed. A3 and A4 are not used. Value is what
7103 resize_mini_window returns. */
23a96c77
GM
7104
7105static int
6d004fea 7106resize_mini_window_1 (a1, exactly, a3, a4)
23dd2d97 7107 EMACS_INT a1;
6d004fea 7108 Lisp_Object exactly;
23dd2d97 7109 EMACS_INT a3, a4;
23a96c77 7110{
6d004fea 7111 return resize_mini_window ((struct window *) a1, !NILP (exactly));
23a96c77
GM
7112}
7113
7114
92a90e89
GM
7115/* Resize mini-window W to fit the size of its contents. EXACT:P
7116 means size the window exactly to the size needed. Otherwise, it's
7117 only enlarged until W's buffer is empty. Value is non-zero if
4b41cebb 7118 the window height has been changed. */
c6e89d6c 7119
9472f927 7120int
92a90e89 7121resize_mini_window (w, exact_p)
c6e89d6c 7122 struct window *w;
92a90e89 7123 int exact_p;
c6e89d6c
GM
7124{
7125 struct frame *f = XFRAME (w->frame);
7126 int window_height_changed_p = 0;
7127
7128 xassert (MINI_WINDOW_P (w));
97cafc0f 7129
2913a9c0
GM
7130 /* Don't resize windows while redisplaying a window; it would
7131 confuse redisplay functions when the size of the window they are
7132 displaying changes from under them. Such a resizing can happen,
7133 for instance, when which-func prints a long message while
7134 we are running fontification-functions. We're running these
7135 functions with safe_call which binds inhibit-redisplay to t. */
7136 if (!NILP (Vinhibit_redisplay))
64c5be50 7137 return 0;
2311178e 7138
97cafc0f 7139 /* Nil means don't try to resize. */
6422c1d7 7140 if (NILP (Vresize_mini_windows)
fa3c6b4d 7141 || (FRAME_X_P (f) && FRAME_X_OUTPUT (f) == NULL))
97cafc0f 7142 return 0;
2311178e 7143
c6e89d6c
GM
7144 if (!FRAME_MINIBUF_ONLY_P (f))
7145 {
7146 struct it it;
dd2eb166 7147 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
da8b7f4f 7148 int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
dd2eb166 7149 int height, max_height;
da8b7f4f 7150 int unit = FRAME_LINE_HEIGHT (f);
dd2eb166 7151 struct text_pos start;
1bfdbe43
GM
7152 struct buffer *old_current_buffer = NULL;
7153
7154 if (current_buffer != XBUFFER (w->buffer))
7155 {
7156 old_current_buffer = current_buffer;
7157 set_buffer_internal (XBUFFER (w->buffer));
7158 }
9142dd5b 7159
c6e89d6c 7160 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 7161
dd2eb166
GM
7162 /* Compute the max. number of lines specified by the user. */
7163 if (FLOATP (Vmax_mini_window_height))
da8b7f4f 7164 max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
dd2eb166
GM
7165 else if (INTEGERP (Vmax_mini_window_height))
7166 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
7167 else
7168 max_height = total_height / 4;
2311178e 7169
4b41cebb 7170 /* Correct that max. height if it's bogus. */
dd2eb166
GM
7171 max_height = max (1, max_height);
7172 max_height = min (total_height, max_height);
2311178e 7173
dd2eb166 7174 /* Find out the height of the text in the window. */
ad4f174e
GM
7175 if (it.truncate_lines_p)
7176 height = 1;
55b064bd 7177 else
ad4f174e
GM
7178 {
7179 last_height = 0;
7180 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
7181 if (it.max_ascent == 0 && it.max_descent == 0)
7182 height = it.current_y + last_height;
7183 else
7184 height = it.current_y + it.max_ascent + it.max_descent;
3c4b7685 7185 height -= it.extra_line_spacing;
ad4f174e
GM
7186 height = (height + unit - 1) / unit;
7187 }
2311178e 7188
dd2eb166
GM
7189 /* Compute a suitable window start. */
7190 if (height > max_height)
7191 {
7192 height = max_height;
7193 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
7194 move_it_vertically_backward (&it, (height - 1) * unit);
7195 start = it.current.pos;
7196 }
7197 else
7198 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
7199 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 7200
6422c1d7 7201 if (EQ (Vresize_mini_windows, Qgrow_only))
dd2eb166 7202 {
6422c1d7
GM
7203 /* Let it grow only, until we display an empty message, in which
7204 case the window shrinks again. */
da8b7f4f 7205 if (height > WINDOW_TOTAL_LINES (w))
6422c1d7 7206 {
da8b7f4f 7207 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7 7208 freeze_window_starts (f, 1);
da8b7f4f
KS
7209 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
7210 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7211 }
da8b7f4f 7212 else if (height < WINDOW_TOTAL_LINES (w)
6422c1d7
GM
7213 && (exact_p || BEGV == ZV))
7214 {
da8b7f4f 7215 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7
GM
7216 freeze_window_starts (f, 0);
7217 shrink_mini_window (w);
da8b7f4f 7218 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7219 }
da448723 7220 }
2311178e 7221 else
da448723 7222 {
6422c1d7 7223 /* Always resize to exact size needed. */
da8b7f4f 7224 if (height > WINDOW_TOTAL_LINES (w))
6422c1d7 7225 {
da8b7f4f 7226 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7 7227 freeze_window_starts (f, 1);
da8b7f4f
KS
7228 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
7229 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7230 }
da8b7f4f 7231 else if (height < WINDOW_TOTAL_LINES (w))
6422c1d7 7232 {
da8b7f4f 7233 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7
GM
7234 freeze_window_starts (f, 0);
7235 shrink_mini_window (w);
7236
7237 if (height)
7238 {
7239 freeze_window_starts (f, 1);
da8b7f4f 7240 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
6422c1d7 7241 }
2311178e 7242
da8b7f4f 7243 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7244 }
9142dd5b 7245 }
1bfdbe43
GM
7246
7247 if (old_current_buffer)
7248 set_buffer_internal (old_current_buffer);
c6e89d6c
GM
7249 }
7250
7251 return window_height_changed_p;
7252}
7253
7254
7255/* Value is the current message, a string, or nil if there is no
7256 current message. */
7257
7258Lisp_Object
7259current_message ()
7260{
7261 Lisp_Object msg;
7262
7263 if (NILP (echo_area_buffer[0]))
7264 msg = Qnil;
7265 else
7266 {
23a96c77 7267 with_echo_area_buffer (0, 0, current_message_1,
23dd2d97 7268 (EMACS_INT) &msg, Qnil, 0, 0);
c6e89d6c
GM
7269 if (NILP (msg))
7270 echo_area_buffer[0] = Qnil;
7271 }
2311178e 7272
c6e89d6c
GM
7273 return msg;
7274}
7275
7276
7277static int
23a96c77 7278current_message_1 (a1, a2, a3, a4)
23dd2d97
KR
7279 EMACS_INT a1;
7280 Lisp_Object a2;
7281 EMACS_INT a3, a4;
c6e89d6c 7282{
23a96c77 7283 Lisp_Object *msg = (Lisp_Object *) a1;
2311178e 7284
c6e89d6c
GM
7285 if (Z > BEG)
7286 *msg = make_buffer_string (BEG, Z, 1);
7287 else
7288 *msg = Qnil;
7289 return 0;
7290}
7291
7292
7293/* Push the current message on Vmessage_stack for later restauration
7294 by restore_message. Value is non-zero if the current message isn't
7295 empty. This is a relatively infrequent operation, so it's not
7296 worth optimizing. */
7297
7298int
7299push_message ()
7300{
7301 Lisp_Object msg;
7302 msg = current_message ();
7303 Vmessage_stack = Fcons (msg, Vmessage_stack);
7304 return STRINGP (msg);
7305}
7306
7307
7308/* Restore message display from the top of Vmessage_stack. */
7309
7310void
7311restore_message ()
7312{
7313 Lisp_Object msg;
2311178e 7314
c6e89d6c
GM
7315 xassert (CONSP (Vmessage_stack));
7316 msg = XCAR (Vmessage_stack);
7317 if (STRINGP (msg))
d5db4077 7318 message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
c6e89d6c
GM
7319 else
7320 message3_nolog (msg, 0, 0);
7321}
7322
7323
37d66095
RS
7324/* Handler for record_unwind_protect calling pop_message. */
7325
7326Lisp_Object
7327pop_message_unwind (dummy)
7328 Lisp_Object dummy;
7329{
7330 pop_message ();
7331 return Qnil;
7332}
7333
c6e89d6c
GM
7334/* Pop the top-most entry off Vmessage_stack. */
7335
7336void
7337pop_message ()
7338{
7339 xassert (CONSP (Vmessage_stack));
7340 Vmessage_stack = XCDR (Vmessage_stack);
7341}
7342
7343
7344/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
7345 exits. If the stack is not empty, we have a missing pop_message
7346 somewhere. */
7347
7348void
7349check_message_stack ()
7350{
7351 if (!NILP (Vmessage_stack))
7352 abort ();
7353}
7354
7355
7356/* Truncate to NCHARS what will be displayed in the echo area the next
7357 time we display it---but don't redisplay it now. */
7358
7359void
7360truncate_echo_area (nchars)
7361 int nchars;
7362{
7363 if (nchars == 0)
7364 echo_area_buffer[0] = Qnil;
7365 /* A null message buffer means that the frame hasn't really been
7366 initialized yet. Error messages get reported properly by
7367 cmd_error, so this must be just an informative message; toss it. */
7368 else if (!noninteractive
7369 && INTERACTIVE
c6e89d6c 7370 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
7371 {
7372 struct frame *sf = SELECTED_FRAME ();
7373 if (FRAME_MESSAGE_BUF (sf))
23dd2d97 7374 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0);
886bd6f2 7375 }
c6e89d6c
GM
7376}
7377
7378
7379/* Helper function for truncate_echo_area. Truncate the current
7380 message to at most NCHARS characters. */
7381
7382static int
23a96c77 7383truncate_message_1 (nchars, a2, a3, a4)
23dd2d97
KR
7384 EMACS_INT nchars;
7385 Lisp_Object a2;
7386 EMACS_INT a3, a4;
c6e89d6c
GM
7387{
7388 if (BEG + nchars < Z)
7389 del_range (BEG + nchars, Z);
7390 if (Z == BEG)
7391 echo_area_buffer[0] = Qnil;
7392 return 0;
7393}
7394
7395
7396/* Set the current message to a substring of S or STRING.
7397
7398 If STRING is a Lisp string, set the message to the first NBYTES
7399 bytes from STRING. NBYTES zero means use the whole string. If
7400 STRING is multibyte, the message will be displayed multibyte.
7401
7402 If S is not null, set the message to the first LEN bytes of S. LEN
7403 zero means use the whole string. MULTIBYTE_P non-zero means S is
7404 multibyte. Display the message multibyte in that case. */
7405
7406void
7407set_message (s, string, nbytes, multibyte_p)
50f80c2f 7408 const char *s;
c6e89d6c 7409 Lisp_Object string;
e3383b6f 7410 int nbytes, multibyte_p;
c6e89d6c
GM
7411{
7412 message_enable_multibyte
7413 = ((s && multibyte_p)
7414 || (STRINGP (string) && STRING_MULTIBYTE (string)));
2311178e 7415
23a96c77
GM
7416 with_echo_area_buffer (0, -1, set_message_1,
7417 (EMACS_INT) s, string, nbytes, multibyte_p);
c6e89d6c 7418 message_buf_print = 0;
21fdfb65 7419 help_echo_showing_p = 0;
c6e89d6c
GM
7420}
7421
7422
7423/* Helper function for set_message. Arguments have the same meaning
23a96c77
GM
7424 as there, with A1 corresponding to S and A2 corresponding to STRING
7425 This function is called with the echo area buffer being
c6e89d6c
GM
7426 current. */
7427
7428static int
23a96c77 7429set_message_1 (a1, a2, nbytes, multibyte_p)
23dd2d97
KR
7430 EMACS_INT a1;
7431 Lisp_Object a2;
7432 EMACS_INT nbytes, multibyte_p;
c6e89d6c 7433{
50f80c2f 7434 const char *s = (const char *) a1;
23dd2d97 7435 Lisp_Object string = a2;
2311178e 7436
c6e89d6c 7437 xassert (BEG == Z);
2311178e 7438
c6e89d6c
GM
7439 /* Change multibyteness of the echo buffer appropriately. */
7440 if (message_enable_multibyte
7441 != !NILP (current_buffer->enable_multibyte_characters))
7442 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
7443
ad4f174e 7444 current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
2311178e 7445
c6e89d6c
GM
7446 /* Insert new message at BEG. */
7447 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
7448
7449 if (STRINGP (string))
7450 {
7451 int nchars;
2311178e 7452
c6e89d6c 7453 if (nbytes == 0)
2051c264 7454 nbytes = SBYTES (string);
c6e89d6c 7455 nchars = string_byte_to_char (string, nbytes);
2311178e 7456
c6e89d6c
GM
7457 /* This function takes care of single/multibyte conversion. We
7458 just have to ensure that the echo area buffer has the right
7459 setting of enable_multibyte_characters. */
7460 insert_from_string (string, 0, 0, nchars, nbytes, 1);
7461 }
7462 else if (s)
7463 {
7464 if (nbytes == 0)
7465 nbytes = strlen (s);
2311178e 7466
c6e89d6c
GM
7467 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
7468 {
7469 /* Convert from multi-byte to single-byte. */
7470 int i, c, n;
7471 unsigned char work[1];
2311178e 7472
c6e89d6c
GM
7473 /* Convert a multibyte string to single-byte. */
7474 for (i = 0; i < nbytes; i += n)
7475 {
7476 c = string_char_and_length (s + i, nbytes - i, &n);
7477 work[0] = (SINGLE_BYTE_CHAR_P (c)
7478 ? c
7479 : multibyte_char_to_unibyte (c, Qnil));
7480 insert_1_both (work, 1, 1, 1, 0, 0);
7481 }
7482 }
7483 else if (!multibyte_p
7484 && !NILP (current_buffer->enable_multibyte_characters))
7485 {
7486 /* Convert from single-byte to multi-byte. */
7487 int i, c, n;
50f80c2f 7488 const unsigned char *msg = (const unsigned char *) s;
260a86a0 7489 unsigned char str[MAX_MULTIBYTE_LENGTH];
2311178e 7490
c6e89d6c
GM
7491 /* Convert a single-byte string to multibyte. */
7492 for (i = 0; i < nbytes; i++)
7493 {
7494 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
7495 n = CHAR_STRING (c, str);
7496 insert_1_both (str, 1, n, 1, 0, 0);
c6e89d6c
GM
7497 }
7498 }
7499 else
7500 insert_1 (s, nbytes, 1, 0, 0);
7501 }
7502
7503 return 0;
7504}
7505
7506
7507/* Clear messages. CURRENT_P non-zero means clear the current
7508 message. LAST_DISPLAYED_P non-zero means clear the message
7509 last displayed. */
7510
7511void
7512clear_message (current_p, last_displayed_p)
7513 int current_p, last_displayed_p;
7514{
7515 if (current_p)
6e019995
GM
7516 {
7517 echo_area_buffer[0] = Qnil;
7518 message_cleared_p = 1;
7519 }
2311178e 7520
c6e89d6c
GM
7521 if (last_displayed_p)
7522 echo_area_buffer[1] = Qnil;
2311178e 7523
c6e89d6c
GM
7524 message_buf_print = 0;
7525}
7526
7527/* Clear garbaged frames.
7528
7529 This function is used where the old redisplay called
7530 redraw_garbaged_frames which in turn called redraw_frame which in
7531 turn called clear_frame. The call to clear_frame was a source of
7532 flickering. I believe a clear_frame is not necessary. It should
7533 suffice in the new redisplay to invalidate all current matrices,
7534 and ensure a complete redisplay of all windows. */
7535
7536static void
7537clear_garbaged_frames ()
7538{
5f5c8ee5
GM
7539 if (frame_garbaged)
7540 {
5f5c8ee5 7541 Lisp_Object tail, frame;
5fb96e96 7542 int changed_count = 0;
2311178e 7543
5f5c8ee5
GM
7544 FOR_EACH_FRAME (tail, frame)
7545 {
7546 struct frame *f = XFRAME (frame);
2311178e 7547
5f5c8ee5
GM
7548 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
7549 {
6bb95882 7550 if (f->resized_p)
573e57f1 7551 Fredraw_frame (frame);
5f5c8ee5 7552 clear_current_matrices (f);
5fb96e96 7553 changed_count++;
5f5c8ee5 7554 f->garbaged = 0;
6bb95882 7555 f->resized_p = 0;
5f5c8ee5
GM
7556 }
7557 }
7558
7559 frame_garbaged = 0;
5fb96e96
RS
7560 if (changed_count)
7561 ++windows_or_buffers_changed;
5f5c8ee5 7562 }
c6e89d6c 7563}
5f5c8ee5 7564
5f5c8ee5 7565
886bd6f2
GM
7566/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
7567 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 7568 mini-windows height has been changed. */
5f5c8ee5 7569
c6e89d6c
GM
7570static int
7571echo_area_display (update_frame_p)
7572 int update_frame_p;
7573{
7574 Lisp_Object mini_window;
7575 struct window *w;
7576 struct frame *f;
7577 int window_height_changed_p = 0;
886bd6f2 7578 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 7579
886bd6f2 7580 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
7581 w = XWINDOW (mini_window);
7582 f = XFRAME (WINDOW_FRAME (w));
7583
7584 /* Don't display if frame is invisible or not yet initialized. */
7585 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
7586 return 0;
5f5c8ee5 7587
1a578e9b 7588/* The terminal frame is used as the first Emacs frame on the Mac OS. */
e0f712ba 7589#ifndef MAC_OS8
1ab3e082 7590#ifdef HAVE_WINDOW_SYSTEM
c6e89d6c
GM
7591 /* When Emacs starts, selected_frame may be a visible terminal
7592 frame, even if we run under a window system. If we let this
7593 through, a message would be displayed on the terminal. */
2311178e 7594 if (EQ (selected_frame, Vterminal_frame)
622e3754 7595 && !NILP (Vwindow_system))
c6e89d6c 7596 return 0;
1ab3e082 7597#endif /* HAVE_WINDOW_SYSTEM */
1a578e9b 7598#endif
c6e89d6c
GM
7599
7600 /* Redraw garbaged frames. */
7601 if (frame_garbaged)
7602 clear_garbaged_frames ();
7603
7604 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
7605 {
7606 echo_area_window = mini_window;
7607 window_height_changed_p = display_echo_area (w);
5f5c8ee5 7608 w->must_be_updated_p = 1;
c59c668a 7609
d4358b37
GM
7610 /* Update the display, unless called from redisplay_internal.
7611 Also don't update the screen during redisplay itself. The
7612 update will happen at the end of redisplay, and an update
7613 here could cause confusion. */
7614 if (update_frame_p && !redisplaying_p)
5f5c8ee5 7615 {
715e84c9 7616 int n = 0;
edc68111 7617
715e84c9
GM
7618 /* If the display update has been interrupted by pending
7619 input, update mode lines in the frame. Due to the
7620 pending input, it might have been that redisplay hasn't
7621 been called, so that mode lines above the echo area are
7622 garbaged. This looks odd, so we prevent it here. */
7623 if (!display_completed)
7624 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
2311178e 7625
8af1308e
GM
7626 if (window_height_changed_p
7627 /* Don't do this if Emacs is shutting down. Redisplay
7628 needs to run hooks. */
7629 && !NILP (Vrun_hooks))
c59c668a 7630 {
c06017fb
GM
7631 /* Must update other windows. Likewise as in other
7632 cases, don't let this update be interrupted by
7633 pending input. */
331379bf 7634 int count = SPECPDL_INDEX ();
c06017fb 7635 specbind (Qredisplay_dont_pause, Qt);
edc68111 7636 windows_or_buffers_changed = 1;
c59c668a 7637 redisplay_internal (0);
c06017fb 7638 unbind_to (count, Qnil);
c59c668a 7639 }
715e84c9 7640 else if (FRAME_WINDOW_P (f) && n == 0)
5f5c8ee5 7641 {
edc68111 7642 /* Window configuration is the same as before.
715e84c9
GM
7643 Can do with a display update of the echo area,
7644 unless we displayed some mode lines. */
5f5c8ee5
GM
7645 update_single_window (w, 1);
7646 rif->flush_display (f);
7647 }
7648 else
7649 update_frame (f, 1, 1);
31b6671b
GM
7650
7651 /* If cursor is in the echo area, make sure that the next
7652 redisplay displays the minibuffer, so that the cursor will
7653 be replaced with what the minibuffer wants. */
7654 if (cursor_in_echo_area)
7655 ++windows_or_buffers_changed;
5f5c8ee5
GM
7656 }
7657 }
7658 else if (!EQ (mini_window, selected_window))
7659 windows_or_buffers_changed++;
c59c668a
GM
7660
7661 /* Last displayed message is now the current message. */
dd2eb166 7662 echo_area_buffer[1] = echo_area_buffer[0];
2311178e 7663
5f5c8ee5
GM
7664 /* Prevent redisplay optimization in redisplay_internal by resetting
7665 this_line_start_pos. This is done because the mini-buffer now
7666 displays the message instead of its buffer text. */
7667 if (EQ (mini_window, selected_window))
7668 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
7669
7670 return window_height_changed_p;
5f5c8ee5
GM
7671}
7672
7673
7674\f
7675/***********************************************************************
7676 Frame Titles
7677 ***********************************************************************/
7678
7679
8143e6ab
KS
7680/* The frame title buffering code is also used by Fformat_mode_line.
7681 So it is not conditioned by HAVE_WINDOW_SYSTEM. */
5f5c8ee5
GM
7682
7683/* A buffer for constructing frame titles in it; allocated from the
7684 heap in init_xdisp and resized as needed in store_frame_title_char. */
7685
7686static char *frame_title_buf;
7687
7688/* The buffer's end, and a current output position in it. */
7689
7690static char *frame_title_buf_end;
7691static char *frame_title_ptr;
7692
7693
7694/* Store a single character C for the frame title in frame_title_buf.
7695 Re-allocate frame_title_buf if necessary. */
7696
7697static void
5d15cc8f
DL
7698#ifdef PROTOTYPES
7699store_frame_title_char (char c)
7700#else
5f5c8ee5
GM
7701store_frame_title_char (c)
7702 char c;
5d15cc8f 7703#endif
5f5c8ee5
GM
7704{
7705 /* If output position has reached the end of the allocated buffer,
7706 double the buffer's size. */
7707 if (frame_title_ptr == frame_title_buf_end)
7708 {
7709 int len = frame_title_ptr - frame_title_buf;
7710 int new_size = 2 * len * sizeof *frame_title_buf;
7711 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
7712 frame_title_buf_end = frame_title_buf + new_size;
7713 frame_title_ptr = frame_title_buf + len;
7714 }
7715
7716 *frame_title_ptr++ = c;
7717}
7718
7719
7720/* Store part of a frame title in frame_title_buf, beginning at
d26b89b8
KH
7721 frame_title_ptr. STR is the string to store. Do not copy
7722 characters that yield more columns than PRECISION; PRECISION <= 0
7723 means copy the whole string. Pad with spaces until FIELD_WIDTH
7724 number of characters have been copied; FIELD_WIDTH <= 0 means don't
7725 pad. Called from display_mode_element when it is used to build a
7726 frame title. */
5f5c8ee5
GM
7727
7728static int
7729store_frame_title (str, field_width, precision)
50f80c2f 7730 const unsigned char *str;
5f5c8ee5
GM
7731 int field_width, precision;
7732{
7733 int n = 0;
3b552d56 7734 int dummy, nbytes;
5f5c8ee5
GM
7735
7736 /* Copy at most PRECISION chars from STR. */
d26b89b8
KH
7737 nbytes = strlen (str);
7738 n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
7739 while (nbytes--)
7740 store_frame_title_char (*str++);
5f5c8ee5
GM
7741
7742 /* Fill up with spaces until FIELD_WIDTH reached. */
7743 while (field_width > 0
7744 && n < field_width)
7745 {
7746 store_frame_title_char (' ');
7747 ++n;
7748 }
7749
7750 return n;
7751}
7752
8143e6ab 7753#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
7754
7755/* Set the title of FRAME, if it has changed. The title format is
7756 Vicon_title_format if FRAME is iconified, otherwise it is
7757 frame_title_format. */
7758
7759static void
7760x_consider_frame_title (frame)
7761 Lisp_Object frame;
7762{
7763 struct frame *f = XFRAME (frame);
7764
7765 if (FRAME_WINDOW_P (f)
7766 || FRAME_MINIBUF_ONLY_P (f)
7767 || f->explicit_name)
7768 {
7769 /* Do we have more than one visible frame on this X display? */
7770 Lisp_Object tail;
7771 Lisp_Object fmt;
7772 struct buffer *obuf;
7773 int len;
7774 struct it it;
7775
9472f927 7776 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 7777 {
74779f52
JR
7778 Lisp_Object other_frame = XCAR (tail);
7779 struct frame *tf = XFRAME (other_frame);
5f5c8ee5 7780
2311178e 7781 if (tf != f
5f5c8ee5
GM
7782 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
7783 && !FRAME_MINIBUF_ONLY_P (tf)
74779f52 7784 && !EQ (other_frame, tip_frame)
5f5c8ee5
GM
7785 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
7786 break;
7787 }
7788
7789 /* Set global variable indicating that multiple frames exist. */
7790 multiple_frames = CONSP (tail);
7791
7792 /* Switch to the buffer of selected window of the frame. Set up
7793 frame_title_ptr so that display_mode_element will output into it;
7794 then display the title. */
7795 obuf = current_buffer;
bb336f8d 7796 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
5f5c8ee5
GM
7797 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
7798 frame_title_ptr = frame_title_buf;
7799 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
7800 NULL, DEFAULT_FACE_ID);
c53a1624 7801 display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
d26b89b8 7802 len = frame_title_ptr - frame_title_buf;
5f5c8ee5 7803 frame_title_ptr = NULL;
bb336f8d 7804 set_buffer_internal_1 (obuf);
5f5c8ee5
GM
7805
7806 /* Set the title only if it's changed. This avoids consing in
7807 the common case where it hasn't. (If it turns out that we've
7808 already wasted too much time by walking through the list with
7809 display_mode_element, then we might need to optimize at a
7810 higher level than this.) */
2311178e 7811 if (! STRINGP (f->name)
2051c264
GM
7812 || SBYTES (f->name) != len
7813 || bcmp (frame_title_buf, SDATA (f->name), len) != 0)
5f5c8ee5
GM
7814 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
7815 }
7816}
7817
5f5c8ee5
GM
7818#endif /* not HAVE_WINDOW_SYSTEM */
7819
7820
7821
7822\f
7823/***********************************************************************
7824 Menu Bars
7825 ***********************************************************************/
7826
7827
7828/* Prepare for redisplay by updating menu-bar item lists when
7829 appropriate. This can call eval. */
7830
7831void
7832prepare_menu_bars ()
7833{
7834 int all_windows;
7835 struct gcpro gcpro1, gcpro2;
7836 struct frame *f;
6b5c4794 7837 Lisp_Object tooltip_frame;
5f5c8ee5 7838
86ffe5cd 7839#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
7840 tooltip_frame = tip_frame;
7841#else
6b5c4794 7842 tooltip_frame = Qnil;
5f5c8ee5
GM
7843#endif
7844
7845 /* Update all frame titles based on their buffer names, etc. We do
7846 this before the menu bars so that the buffer-menu will show the
7847 up-to-date frame titles. */
7848#ifdef HAVE_WINDOW_SYSTEM
7849 if (windows_or_buffers_changed || update_mode_lines)
7850 {
7851 Lisp_Object tail, frame;
7852
7853 FOR_EACH_FRAME (tail, frame)
7854 {
7855 f = XFRAME (frame);
6b5c4794 7856 if (!EQ (frame, tooltip_frame)
5f5c8ee5
GM
7857 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
7858 x_consider_frame_title (frame);
7859 }
7860 }
7861#endif /* HAVE_WINDOW_SYSTEM */
7862
7863 /* Update the menu bar item lists, if appropriate. This has to be
7864 done before any actual redisplay or generation of display lines. */
2311178e 7865 all_windows = (update_mode_lines
5f5c8ee5
GM
7866 || buffer_shared > 1
7867 || windows_or_buffers_changed);
7868 if (all_windows)
7869 {
7870 Lisp_Object tail, frame;
331379bf 7871 int count = SPECPDL_INDEX ();
5f5c8ee5
GM
7872
7873 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
7874
7875 FOR_EACH_FRAME (tail, frame)
7876 {
7877 f = XFRAME (frame);
7878
7879 /* Ignore tooltip frame. */
6b5c4794 7880 if (EQ (frame, tooltip_frame))
5f5c8ee5 7881 continue;
2311178e 7882
5f5c8ee5
GM
7883 /* If a window on this frame changed size, report that to
7884 the user and clear the size-change flag. */
7885 if (FRAME_WINDOW_SIZES_CHANGED (f))
7886 {
7887 Lisp_Object functions;
2311178e 7888
5f5c8ee5
GM
7889 /* Clear flag first in case we get an error below. */
7890 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
7891 functions = Vwindow_size_change_functions;
7892 GCPRO2 (tail, functions);
2311178e 7893
5f5c8ee5
GM
7894 while (CONSP (functions))
7895 {
7896 call1 (XCAR (functions), frame);
7897 functions = XCDR (functions);
7898 }
7899 UNGCPRO;
7900 }
2311178e 7901
5f5c8ee5
GM
7902 GCPRO1 (tail);
7903 update_menu_bar (f, 0);
7904#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 7905 update_tool_bar (f, 0);
5f5c8ee5
GM
7906#endif
7907 UNGCPRO;
7908 }
7909
7910 unbind_to (count, Qnil);
7911 }
7912 else
7913 {
886bd6f2
GM
7914 struct frame *sf = SELECTED_FRAME ();
7915 update_menu_bar (sf, 1);
5f5c8ee5 7916#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 7917 update_tool_bar (sf, 1);
5f5c8ee5
GM
7918#endif
7919 }
7920
7921 /* Motif needs this. See comment in xmenu.c. Turn it off when
7922 pending_menu_activation is not defined. */
7923#ifdef USE_X_TOOLKIT
7924 pending_menu_activation = 0;
7925#endif
7926}
7927
7928
7929/* Update the menu bar item list for frame F. This has to be done
7930 before we start to fill in any display lines, because it can call
7931 eval.
7932
7933 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
7934
7935static void
7936update_menu_bar (f, save_match_data)
7937 struct frame *f;
7938 int save_match_data;
7939{
7940 Lisp_Object window;
7941 register struct window *w;
7942
e1477f43
GM
7943 /* If called recursively during a menu update, do nothing. This can
7944 happen when, for instance, an activate-menubar-hook causes a
7945 redisplay. */
7946 if (inhibit_menubar_update)
7947 return;
7948
5f5c8ee5
GM
7949 window = FRAME_SELECTED_WINDOW (f);
7950 w = XWINDOW (window);
2311178e 7951
84f2e615 7952#if 0 /* The if statement below this if statement used to include the
a5f08374
RS
7953 condition !NILP (w->update_mode_line), rather than using
7954 update_mode_lines directly, and this if statement may have
7955 been added to make that condition work. Now the if
2311178e 7956 statement below matches its comment, this isn't needed. */
5f5c8ee5
GM
7957 if (update_mode_lines)
7958 w->update_mode_line = Qt;
a5f08374 7959#endif
5f5c8ee5
GM
7960
7961 if (FRAME_WINDOW_P (f)
7962 ?
488dd4c4
JD
7963#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
7964 || defined (USE_GTK)
2311178e 7965 FRAME_EXTERNAL_MENU_BAR (f)
5f5c8ee5
GM
7966#else
7967 FRAME_MENU_BAR_LINES (f) > 0
7968#endif
7969 : FRAME_MENU_BAR_LINES (f) > 0)
7970 {
7971 /* If the user has switched buffers or windows, we need to
7972 recompute to reflect the new bindings. But we'll
7973 recompute when update_mode_lines is set too; that means
7974 that people can use force-mode-line-update to request
7975 that the menu bar be recomputed. The adverse effect on
7976 the rest of the redisplay algorithm is about the same as
7977 windows_or_buffers_changed anyway. */
7978 if (windows_or_buffers_changed
a5f08374
RS
7979 /* This used to test w->update_mode_line, but we believe
7980 there is no need to recompute the menu in that case. */
7981 || update_mode_lines
5f5c8ee5
GM
7982 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
7983 < BUF_MODIFF (XBUFFER (w->buffer)))
7984 != !NILP (w->last_had_star))
7985 || ((!NILP (Vtransient_mark_mode)
7986 && !NILP (XBUFFER (w->buffer)->mark_active))
7987 != !NILP (w->region_showing)))
7988 {
7989 struct buffer *prev = current_buffer;
331379bf 7990 int count = SPECPDL_INDEX ();
5f5c8ee5 7991
e1477f43
GM
7992 specbind (Qinhibit_menubar_update, Qt);
7993
5f5c8ee5
GM
7994 set_buffer_internal_1 (XBUFFER (w->buffer));
7995 if (save_match_data)
7996 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
7997 if (NILP (Voverriding_local_map_menu_flag))
7998 {
7999 specbind (Qoverriding_terminal_local_map, Qnil);
8000 specbind (Qoverriding_local_map, Qnil);
8001 }
8002
8003 /* Run the Lucid hook. */
65048e97 8004 safe_run_hooks (Qactivate_menubar_hook);
2311178e 8005
5f5c8ee5
GM
8006 /* If it has changed current-menubar from previous value,
8007 really recompute the menu-bar from the value. */
8008 if (! NILP (Vlucid_menu_bar_dirty_flag))
8009 call0 (Qrecompute_lucid_menubar);
2311178e 8010
5f5c8ee5
GM
8011 safe_run_hooks (Qmenu_bar_update_hook);
8012 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
2311178e 8013
5f5c8ee5 8014 /* Redisplay the menu bar in case we changed it. */
488dd4c4
JD
8015#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
8016 || defined (USE_GTK)
1a578e9b 8017 if (FRAME_WINDOW_P (f)
e0f712ba 8018#if defined (MAC_OS)
1a578e9b
AC
8019 /* All frames on Mac OS share the same menubar. So only the
8020 selected frame should be allowed to set it. */
8021 && f == SELECTED_FRAME ()
8022#endif
8023 )
5f5c8ee5
GM
8024 set_frame_menubar (f, 0, 0);
8025 else
8026 /* On a terminal screen, the menu bar is an ordinary screen
8027 line, and this makes it get updated. */
8028 w->update_mode_line = Qt;
488dd4c4 8029#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
5f5c8ee5
GM
8030 /* In the non-toolkit version, the menu bar is an ordinary screen
8031 line, and this makes it get updated. */
8032 w->update_mode_line = Qt;
488dd4c4 8033#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
5f5c8ee5
GM
8034
8035 unbind_to (count, Qnil);
8036 set_buffer_internal_1 (prev);
8037 }
8038 }
8039}
8040
8041
8042\f
fa3c6b4d
KS
8043/***********************************************************************
8044 Output Cursor
8045 ***********************************************************************/
8046
1dabd0cf
KS
8047#ifdef HAVE_WINDOW_SYSTEM
8048
fa3c6b4d
KS
8049/* EXPORT:
8050 Nominal cursor position -- where to draw output.
8051 HPOS and VPOS are window relative glyph matrix coordinates.
8052 X and Y are window relative pixel coordinates. */
8053
8054struct cursor_pos output_cursor;
8055
8056
8057/* EXPORT:
8058 Set the global variable output_cursor to CURSOR. All cursor
8059 positions are relative to updated_window. */
8060
8061void
8062set_output_cursor (cursor)
8063 struct cursor_pos *cursor;
8064{
8065 output_cursor.hpos = cursor->hpos;
8066 output_cursor.vpos = cursor->vpos;
8067 output_cursor.x = cursor->x;
8068 output_cursor.y = cursor->y;
8069}
8070
8071
8072/* EXPORT for RIF:
8073 Set a nominal cursor position.
8074
8075 HPOS and VPOS are column/row positions in a window glyph matrix. X
8076 and Y are window text area relative pixel positions.
8077
8078 If this is done during an update, updated_window will contain the
8079 window that is being updated and the position is the future output
8080 cursor position for that window. If updated_window is null, use
8081 selected_window and display the cursor at the given position. */
8082
8083void
8084x_cursor_to (vpos, hpos, y, x)
8085 int vpos, hpos, y, x;
8086{
8087 struct window *w;
8088
8089 /* If updated_window is not set, work on selected_window. */
8090 if (updated_window)
8091 w = updated_window;
8092 else
8093 w = XWINDOW (selected_window);
8094
8095 /* Set the output cursor. */
8096 output_cursor.hpos = hpos;
8097 output_cursor.vpos = vpos;
8098 output_cursor.x = x;
8099 output_cursor.y = y;
8100
8101 /* If not called as part of an update, really display the cursor.
8102 This will also set the cursor position of W. */
8103 if (updated_window == NULL)
8104 {
8105 BLOCK_INPUT;
8106 display_and_set_cursor (w, 1, hpos, vpos, x, y);
8107 if (rif->flush_display_optional)
8108 rif->flush_display_optional (SELECTED_FRAME ());
8109 UNBLOCK_INPUT;
8110 }
8111}
8112
1dabd0cf 8113#endif /* HAVE_WINDOW_SYSTEM */
fa3c6b4d
KS
8114
8115\f
5f5c8ee5 8116/***********************************************************************
e037b9ec 8117 Tool-bars
5f5c8ee5
GM
8118 ***********************************************************************/
8119
8120#ifdef HAVE_WINDOW_SYSTEM
8121
fa3c6b4d
KS
8122/* Where the mouse was last time we reported a mouse event. */
8123
8124FRAME_PTR last_mouse_frame;
8125
8126/* Tool-bar item index of the item on which a mouse button was pressed
8127 or -1. */
8128
8129int last_tool_bar_item;
8130
8131
e037b9ec 8132/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
8133 before we start to fill in any display lines. Called from
8134 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
8135 and restore it here. */
8136
8137static void
e037b9ec 8138update_tool_bar (f, save_match_data)
5f5c8ee5
GM
8139 struct frame *f;
8140 int save_match_data;
8141{
488dd4c4
JD
8142#ifdef USE_GTK
8143 int do_update = FRAME_EXTERNAL_TOOL_BAR(f);
8144#else
8145 int do_update = WINDOWP (f->tool_bar_window)
da8b7f4f 8146 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
488dd4c4
JD
8147#endif
8148
8149 if (do_update)
5f5c8ee5
GM
8150 {
8151 Lisp_Object window;
8152 struct window *w;
8153
8154 window = FRAME_SELECTED_WINDOW (f);
8155 w = XWINDOW (window);
2311178e 8156
5f5c8ee5
GM
8157 /* If the user has switched buffers or windows, we need to
8158 recompute to reflect the new bindings. But we'll
8159 recompute when update_mode_lines is set too; that means
8160 that people can use force-mode-line-update to request
8161 that the menu bar be recomputed. The adverse effect on
8162 the rest of the redisplay algorithm is about the same as
8163 windows_or_buffers_changed anyway. */
8164 if (windows_or_buffers_changed
8165 || !NILP (w->update_mode_line)
84f2e615 8166 || update_mode_lines
5f5c8ee5
GM
8167 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
8168 < BUF_MODIFF (XBUFFER (w->buffer)))
8169 != !NILP (w->last_had_star))
8170 || ((!NILP (Vtransient_mark_mode)
8171 && !NILP (XBUFFER (w->buffer)->mark_active))
8172 != !NILP (w->region_showing)))
8173 {
8174 struct buffer *prev = current_buffer;
331379bf 8175 int count = SPECPDL_INDEX ();
84f2e615
RS
8176 Lisp_Object old_tool_bar;
8177 struct gcpro gcpro1;
a2889657 8178
5f5c8ee5
GM
8179 /* Set current_buffer to the buffer of the selected
8180 window of the frame, so that we get the right local
8181 keymaps. */
8182 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 8183
5f5c8ee5
GM
8184 /* Save match data, if we must. */
8185 if (save_match_data)
8186 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
8187
8188 /* Make sure that we don't accidentally use bogus keymaps. */
8189 if (NILP (Voverriding_local_map_menu_flag))
8190 {
8191 specbind (Qoverriding_terminal_local_map, Qnil);
8192 specbind (Qoverriding_local_map, Qnil);
1f40cad2 8193 }
1f40cad2 8194
84f2e615
RS
8195 old_tool_bar = f->tool_bar_items;
8196 GCPRO1 (old_tool_bar);
8197
e037b9ec 8198 /* Build desired tool-bar items from keymaps. */
e3b2c21f 8199 BLOCK_INPUT;
7464726e
GM
8200 f->tool_bar_items
8201 = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
e3b2c21f 8202 UNBLOCK_INPUT;
2311178e 8203
84f2e615
RS
8204 /* Redisplay the tool-bar if we changed it. */
8205 if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
8206 w->update_mode_line = Qt;
1e802fb5
SM
8207
8208 UNGCPRO;
5f5c8ee5
GM
8209
8210 unbind_to (count, Qnil);
8211 set_buffer_internal_1 (prev);
81d478f3 8212 }
a2889657
JB
8213 }
8214}
8215
6c4429a5 8216
e037b9ec 8217/* Set F->desired_tool_bar_string to a Lisp string representing frame
7464726e 8218 F's desired tool-bar contents. F->tool_bar_items must have
5f5c8ee5
GM
8219 been set up previously by calling prepare_menu_bars. */
8220
a2889657 8221static void
e037b9ec 8222build_desired_tool_bar_string (f)
5f5c8ee5 8223 struct frame *f;
a2889657 8224{
a23887b9 8225 int i, size, size_needed;
5f5c8ee5
GM
8226 struct gcpro gcpro1, gcpro2, gcpro3;
8227 Lisp_Object image, plist, props;
a2889657 8228
5f5c8ee5
GM
8229 image = plist = props = Qnil;
8230 GCPRO3 (image, plist, props);
a2889657 8231
e037b9ec 8232 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5 8233 Otherwise, make a new string. */
2311178e 8234
5f5c8ee5 8235 /* The size of the string we might be able to reuse. */
e037b9ec 8236 size = (STRINGP (f->desired_tool_bar_string)
2051c264 8237 ? SCHARS (f->desired_tool_bar_string)
5f5c8ee5
GM
8238 : 0);
8239
b94c0d9c 8240 /* We need one space in the string for each image. */
a23887b9 8241 size_needed = f->n_tool_bar_items;
2311178e 8242
b94c0d9c 8243 /* Reuse f->desired_tool_bar_string, if possible. */
cb2ddc53 8244 if (size < size_needed || NILP (f->desired_tool_bar_string))
6fc556fd
KR
8245 f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
8246 make_number (' '));
5f5c8ee5
GM
8247 else
8248 {
8249 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
8250 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 8251 props, f->desired_tool_bar_string);
5f5c8ee5 8252 }
a2889657 8253
5f5c8ee5 8254 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
8255 put a `menu_item' property on tool-bar items with a value that
8256 is the index of the item in F's tool-bar item vector. */
a23887b9 8257 for (i = 0; i < f->n_tool_bar_items; ++i)
a2889657 8258 {
7464726e 8259#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5f5c8ee5 8260
e037b9ec
GM
8261 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
8262 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
35a41507 8263 int hmargin, vmargin, relief, idx, end;
ecd01a0e 8264 extern Lisp_Object QCrelief, QCmargin, QCconversion, Qimage;
5f5c8ee5
GM
8265
8266 /* If image is a vector, choose the image according to the
8267 button state. */
e037b9ec 8268 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
8269 if (VECTORP (image))
8270 {
5f5c8ee5
GM
8271 if (enabled_p)
8272 idx = (selected_p
e037b9ec
GM
8273 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
8274 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
8275 else
8276 idx = (selected_p
e037b9ec
GM
8277 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
8278 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
2311178e 8279
37e4e482
GM
8280 xassert (ASIZE (image) >= idx);
8281 image = AREF (image, idx);
5f5c8ee5 8282 }
37e4e482
GM
8283 else
8284 idx = -1;
5f5c8ee5
GM
8285
8286 /* Ignore invalid image specifications. */
8287 if (!valid_image_p (image))
8288 continue;
8289
e037b9ec 8290 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
8291 plist = Fcopy_sequence (XCDR (image));
8292
8293 /* Compute margin and relief to draw. */
9f864bf9 8294 relief = (tool_bar_button_relief >= 0
c3d76173
GM
8295 ? tool_bar_button_relief
8296 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
35a41507
GM
8297 hmargin = vmargin = relief;
8298
8299 if (INTEGERP (Vtool_bar_button_margin)
8300 && XINT (Vtool_bar_button_margin) > 0)
8301 {
8302 hmargin += XFASTINT (Vtool_bar_button_margin);
8303 vmargin += XFASTINT (Vtool_bar_button_margin);
8304 }
8305 else if (CONSP (Vtool_bar_button_margin))
8306 {
8307 if (INTEGERP (XCAR (Vtool_bar_button_margin))
8308 && XINT (XCAR (Vtool_bar_button_margin)) > 0)
8309 hmargin += XFASTINT (XCAR (Vtool_bar_button_margin));
2311178e 8310
35a41507
GM
8311 if (INTEGERP (XCDR (Vtool_bar_button_margin))
8312 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
8313 vmargin += XFASTINT (XCDR (Vtool_bar_button_margin));
8314 }
2311178e 8315
e037b9ec 8316 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
8317 {
8318 /* Add a `:relief' property to the image spec if the item is
8319 selected. */
8320 if (selected_p)
8321 {
8322 plist = Fplist_put (plist, QCrelief, make_number (-relief));
35a41507
GM
8323 hmargin -= relief;
8324 vmargin -= relief;
5f5c8ee5
GM
8325 }
8326 }
8327 else
8328 {
8329 /* If image is selected, display it pressed, i.e. with a
8330 negative relief. If it's not selected, display it with a
8331 raised relief. */
8332 plist = Fplist_put (plist, QCrelief,
8333 (selected_p
8334 ? make_number (-relief)
8335 : make_number (relief)));
35a41507
GM
8336 hmargin -= relief;
8337 vmargin -= relief;
5f5c8ee5
GM
8338 }
8339
8340 /* Put a margin around the image. */
35a41507
GM
8341 if (hmargin || vmargin)
8342 {
8343 if (hmargin == vmargin)
8344 plist = Fplist_put (plist, QCmargin, make_number (hmargin));
8345 else
8346 plist = Fplist_put (plist, QCmargin,
8347 Fcons (make_number (hmargin),
8348 make_number (vmargin)));
8349 }
2311178e 8350
37e4e482
GM
8351 /* If button is not enabled, and we don't have special images
8352 for the disabled state, make the image appear disabled by
5f5c8ee5 8353 applying an appropriate algorithm to it. */
37e4e482 8354 if (!enabled_p && idx < 0)
ecd01a0e 8355 plist = Fplist_put (plist, QCconversion, Qdisabled);
2311178e 8356
5f5c8ee5
GM
8357 /* Put a `display' text property on the string for the image to
8358 display. Put a `menu-item' property on the string that gives
e037b9ec 8359 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
8360 vector. */
8361 image = Fcons (Qimage, plist);
8362 props = list4 (Qdisplay, image,
a23887b9
GM
8363 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS));
8364
8365 /* Let the last image hide all remaining spaces in the tool bar
8366 string. The string can be longer than needed when we reuse a
8367 previous string. */
8368 if (i + 1 == f->n_tool_bar_items)
2051c264 8369 end = SCHARS (f->desired_tool_bar_string);
a23887b9
GM
8370 else
8371 end = i + 1;
8372 Fadd_text_properties (make_number (i), make_number (end),
e037b9ec 8373 props, f->desired_tool_bar_string);
5f5c8ee5 8374#undef PROP
a2889657
JB
8375 }
8376
5f5c8ee5
GM
8377 UNGCPRO;
8378}
8379
8380
e037b9ec 8381/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
8382
8383static void
e037b9ec 8384display_tool_bar_line (it)
5f5c8ee5
GM
8385 struct it *it;
8386{
8387 struct glyph_row *row = it->glyph_row;
8388 int max_x = it->last_visible_x;
8389 struct glyph *last;
2311178e 8390
5f5c8ee5
GM
8391 prepare_desired_row (row);
8392 row->y = it->current_y;
90aa2856
GM
8393
8394 /* Note that this isn't made use of if the face hasn't a box,
8395 so there's no need to check the face here. */
8396 it->start_of_box_run_p = 1;
2311178e 8397
5f5c8ee5 8398 while (it->current_x < max_x)
a2889657 8399 {
5f5c8ee5 8400 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 8401
5f5c8ee5
GM
8402 /* Get the next display element. */
8403 if (!get_next_display_element (it))
8404 break;
73af359d 8405
5f5c8ee5
GM
8406 /* Produce glyphs. */
8407 x_before = it->current_x;
8408 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
8409 PRODUCE_GLYPHS (it);
daa37602 8410
5f5c8ee5
GM
8411 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
8412 i = 0;
8413 x = x_before;
8414 while (i < nglyphs)
8415 {
8416 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 8417
5f5c8ee5
GM
8418 if (x + glyph->pixel_width > max_x)
8419 {
8420 /* Glyph doesn't fit on line. */
8421 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
8422 it->current_x = x;
8423 goto out;
8424 }
daa37602 8425
5f5c8ee5
GM
8426 ++it->hpos;
8427 x += glyph->pixel_width;
8428 ++i;
8429 }
8430
8431 /* Stop at line ends. */
8432 if (ITERATOR_AT_END_OF_LINE_P (it))
8433 break;
8434
cafafe0b 8435 set_iterator_to_next (it, 1);
a2889657 8436 }
a2889657 8437
5f5c8ee5 8438 out:;
a2889657 8439
5f5c8ee5
GM
8440 row->displays_text_p = row->used[TEXT_AREA] != 0;
8441 extend_face_to_end_of_line (it);
8442 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
8443 last->right_box_line_p = 1;
90aa2856
GM
8444 if (last == row->glyphs[TEXT_AREA])
8445 last->left_box_line_p = 1;
5f5c8ee5 8446 compute_line_metrics (it);
2311178e 8447
e037b9ec 8448 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
8449 if (!row->displays_text_p)
8450 {
312246d1
GM
8451 row->height = row->phys_height = it->last_visible_y - row->y;
8452 row->ascent = row->phys_ascent = 0;
5f5c8ee5 8453 }
2311178e 8454
5f5c8ee5
GM
8455 row->full_width_p = 1;
8456 row->continued_p = 0;
8457 row->truncated_on_left_p = 0;
8458 row->truncated_on_right_p = 0;
8459
8460 it->current_x = it->hpos = 0;
8461 it->current_y += row->height;
8462 ++it->vpos;
8463 ++it->glyph_row;
a2889657 8464}
96a410bc 8465
5f5c8ee5 8466
e037b9ec 8467/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 8468 items of frame F visible. */
96a410bc 8469
d39b6696 8470static int
e037b9ec 8471tool_bar_lines_needed (f)
5f5c8ee5 8472 struct frame *f;
d39b6696 8473{
e037b9ec 8474 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5 8475 struct it it;
2311178e 8476
e037b9ec
GM
8477 /* Initialize an iterator for iteration over
8478 F->desired_tool_bar_string in the tool-bar window of frame F. */
8479 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5 8480 it.first_visible_x = 0;
da8b7f4f 8481 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
e037b9ec 8482 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
8483
8484 while (!ITERATOR_AT_END_P (&it))
8485 {
8486 it.glyph_row = w->desired_matrix->rows;
8487 clear_glyph_row (it.glyph_row);
e037b9ec 8488 display_tool_bar_line (&it);
5f5c8ee5
GM
8489 }
8490
da8b7f4f 8491 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
d39b6696 8492}
96a410bc 8493
5f5c8ee5 8494
57c28064
GM
8495DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
8496 0, 1, 0,
7ee72033
MB
8497 doc: /* Return the number of lines occupied by the tool bar of FRAME. */)
8498 (frame)
57c28064
GM
8499 Lisp_Object frame;
8500{
8501 struct frame *f;
8502 struct window *w;
8503 int nlines = 0;
8504
8505 if (NILP (frame))
8506 frame = selected_frame;
8507 else
b7826503 8508 CHECK_FRAME (frame);
57c28064 8509 f = XFRAME (frame);
2311178e 8510
57c28064
GM
8511 if (WINDOWP (f->tool_bar_window)
8512 || (w = XWINDOW (f->tool_bar_window),
da8b7f4f 8513 WINDOW_TOTAL_LINES (w) > 0))
57c28064
GM
8514 {
8515 update_tool_bar (f, 1);
8516 if (f->n_tool_bar_items)
8517 {
8518 build_desired_tool_bar_string (f);
8519 nlines = tool_bar_lines_needed (f);
8520 }
8521 }
8522
8523 return make_number (nlines);
8524}
8525
8526
e037b9ec 8527/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
8528 height should be changed. */
8529
8530static int
e037b9ec 8531redisplay_tool_bar (f)
5f5c8ee5 8532 struct frame *f;
96a410bc 8533{
5f5c8ee5
GM
8534 struct window *w;
8535 struct it it;
8536 struct glyph_row *row;
8537 int change_height_p = 0;
177c0ea7 8538
488dd4c4
JD
8539#ifdef USE_GTK
8540 if (FRAME_EXTERNAL_TOOL_BAR(f))
8541 update_frame_tool_bar (f);
8542 return 0;
8543#endif
2311178e 8544
e037b9ec
GM
8545 /* If frame hasn't a tool-bar window or if it is zero-height, don't
8546 do anything. This means you must start with tool-bar-lines
5f5c8ee5 8547 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
8548 can turn off tool-bars by specifying tool-bar-lines zero. */
8549 if (!WINDOWP (f->tool_bar_window)
8550 || (w = XWINDOW (f->tool_bar_window),
da8b7f4f 8551 WINDOW_TOTAL_LINES (w) == 0))
5f5c8ee5 8552 return 0;
96a410bc 8553
e037b9ec
GM
8554 /* Set up an iterator for the tool-bar window. */
8555 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5 8556 it.first_visible_x = 0;
da8b7f4f 8557 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5 8558 row = it.glyph_row;
3450d04c 8559
e037b9ec
GM
8560 /* Build a string that represents the contents of the tool-bar. */
8561 build_desired_tool_bar_string (f);
8562 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 8563
e037b9ec 8564 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 8565 while (it.current_y < it.last_visible_y)
e037b9ec 8566 display_tool_bar_line (&it);
3450d04c 8567
e037b9ec 8568 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
8569 window, so don't do it. */
8570 w->desired_matrix->no_scrolling_p = 1;
8571 w->must_be_updated_p = 1;
3450d04c 8572
e037b9ec 8573 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
8574 {
8575 int nlines;
6e33e6f0
GM
8576
8577 /* If we couldn't display everything, change the tool-bar's
8578 height. */
8579 if (IT_STRING_CHARPOS (it) < it.end_charpos)
8580 change_height_p = 1;
2311178e 8581
5f5c8ee5
GM
8582 /* If there are blank lines at the end, except for a partially
8583 visible blank line at the end that is smaller than
da8b7f4f 8584 FRAME_LINE_HEIGHT, change the tool-bar's height. */
5f5c8ee5
GM
8585 row = it.glyph_row - 1;
8586 if (!row->displays_text_p
da8b7f4f 8587 && row->height >= FRAME_LINE_HEIGHT (f))
5f5c8ee5
GM
8588 change_height_p = 1;
8589
e037b9ec
GM
8590 /* If row displays tool-bar items, but is partially visible,
8591 change the tool-bar's height. */
5f5c8ee5
GM
8592 if (row->displays_text_p
8593 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
8594 change_height_p = 1;
8595
e037b9ec 8596 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
8597 frame parameter. */
8598 if (change_height_p
e037b9ec 8599 && (nlines = tool_bar_lines_needed (f),
da8b7f4f 8600 nlines != WINDOW_TOTAL_LINES (w)))
5f5c8ee5 8601 {
e037b9ec 8602 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5 8603 Lisp_Object frame;
da8b7f4f 8604 int old_height = WINDOW_TOTAL_LINES (w);
2311178e 8605
5f5c8ee5
GM
8606 XSETFRAME (frame, f);
8607 clear_glyph_matrix (w->desired_matrix);
8608 Fmodify_frame_parameters (frame,
e037b9ec 8609 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
8610 make_number (nlines)),
8611 Qnil));
da8b7f4f 8612 if (WINDOW_TOTAL_LINES (w) != old_height)
e85ee976 8613 fonts_changed_p = 1;
5f5c8ee5
GM
8614 }
8615 }
3450d04c 8616
5f5c8ee5 8617 return change_height_p;
96a410bc 8618}
90adcf20 8619
5f5c8ee5 8620
e037b9ec
GM
8621/* Get information about the tool-bar item which is displayed in GLYPH
8622 on frame F. Return in *PROP_IDX the index where tool-bar item
7464726e 8623 properties start in F->tool_bar_items. Value is zero if
e037b9ec 8624 GLYPH doesn't display a tool-bar item. */
5f5c8ee5 8625
fa3c6b4d 8626static int
e037b9ec 8627tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
8628 struct frame *f;
8629 struct glyph *glyph;
8630 int *prop_idx;
90adcf20 8631{
5f5c8ee5
GM
8632 Lisp_Object prop;
8633 int success_p;
be676094
GM
8634 int charpos;
8635
8636 /* This function can be called asynchronously, which means we must
8637 exclude any possibility that Fget_text_property signals an
8638 error. */
2051c264 8639 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
be676094 8640 charpos = max (0, charpos);
2311178e 8641
5f5c8ee5
GM
8642 /* Get the text property `menu-item' at pos. The value of that
8643 property is the start index of this item's properties in
7464726e 8644 F->tool_bar_items. */
be676094 8645 prop = Fget_text_property (make_number (charpos),
e037b9ec 8646 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
8647 if (INTEGERP (prop))
8648 {
8649 *prop_idx = XINT (prop);
8650 success_p = 1;
8651 }
8652 else
8653 success_p = 0;
90adcf20 8654
5f5c8ee5
GM
8655 return success_p;
8656}
2311178e 8657
fa3c6b4d
KS
8658\f
8659/* Get information about the tool-bar item at position X/Y on frame F.
8660 Return in *GLYPH a pointer to the glyph of the tool-bar item in
8661 the current matrix of the tool-bar window of F, or NULL if not
8662 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
8663 item in F->tool_bar_items. Value is
8664
8665 -1 if X/Y is not on a tool-bar item
8666 0 if X/Y is on the same item that was highlighted before.
8667 1 otherwise. */
8668
8669static int
8670get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
8671 struct frame *f;
8672 int x, y;
8673 struct glyph **glyph;
8674 int *hpos, *vpos, *prop_idx;
8675{
8676 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8677 struct window *w = XWINDOW (f->tool_bar_window);
8678 int area;
8679
8680 /* Find the glyph under X/Y. */
8681 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
8682 if (*glyph == NULL)
8683 return -1;
8684
8685 /* Get the start of this tool-bar item's properties in
8686 f->tool_bar_items. */
8687 if (!tool_bar_item_info (f, *glyph, prop_idx))
8688 return -1;
8689
8690 /* Is mouse on the highlighted item? */
8691 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
8692 && *vpos >= dpyinfo->mouse_face_beg_row
8693 && *vpos <= dpyinfo->mouse_face_end_row
8694 && (*vpos > dpyinfo->mouse_face_beg_row
8695 || *hpos >= dpyinfo->mouse_face_beg_col)
8696 && (*vpos < dpyinfo->mouse_face_end_row
8697 || *hpos < dpyinfo->mouse_face_end_col
8698 || dpyinfo->mouse_face_past_end))
8699 return 0;
8700
8701 return 1;
8702}
8703
8704
8705/* EXPORT:
8706 Handle mouse button event on the tool-bar of frame F, at
8707 frame-relative coordinates X/Y. DOWN_P is 1 for a button press,
8708 0 for button release. MODIFIERS is event modifiers for button
8709 release. */
8710
8711void
8712handle_tool_bar_click (f, x, y, down_p, modifiers)
8713 struct frame *f;
8714 int x, y, down_p;
8715 unsigned int modifiers;
8716{
8717 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8718 struct window *w = XWINDOW (f->tool_bar_window);
8719 int hpos, vpos, prop_idx;
8720 struct glyph *glyph;
8721 Lisp_Object enabled_p;
8722
8723 /* If not on the highlighted tool-bar item, return. */
8724 frame_to_window_pixel_xy (w, &x, &y);
8725 if (get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
8726 return;
8727
8728 /* If item is disabled, do nothing. */
8729 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
8730 if (NILP (enabled_p))
8731 return;
8732
8733 if (down_p)
8734 {
8735 /* Show item in pressed state. */
8736 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
8737 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
8738 last_tool_bar_item = prop_idx;
8739 }
8740 else
8741 {
8742 Lisp_Object key, frame;
8743 struct input_event event;
d86705ec 8744 EVENT_INIT (event);
fa3c6b4d
KS
8745
8746 /* Show item in released state. */
8747 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
8748 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
8749
8750 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
8751
8752 XSETFRAME (frame, f);
8753 event.kind = TOOL_BAR_EVENT;
8754 event.frame_or_window = frame;
8755 event.arg = frame;
8756 kbd_buffer_store_event (&event);
8757
8758 event.kind = TOOL_BAR_EVENT;
8759 event.frame_or_window = frame;
8760 event.arg = key;
8761 event.modifiers = modifiers;
8762 kbd_buffer_store_event (&event);
8763 last_tool_bar_item = -1;
8764 }
8765}
8766
8767
8768/* Possibly highlight a tool-bar item on frame F when mouse moves to
8769 tool-bar window-relative coordinates X/Y. Called from
8770 note_mouse_highlight. */
8771
8772static void
8773note_tool_bar_highlight (f, x, y)
8774 struct frame *f;
8775 int x, y;
8776{
8777 Lisp_Object window = f->tool_bar_window;
8778 struct window *w = XWINDOW (window);
8779 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8780 int hpos, vpos;
8781 struct glyph *glyph;
8782 struct glyph_row *row;
8783 int i;
8784 Lisp_Object enabled_p;
8785 int prop_idx;
8786 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
8787 int mouse_down_p, rc;
8788
8789 /* Function note_mouse_highlight is called with negative x(y
8790 values when mouse moves outside of the frame. */
8791 if (x <= 0 || y <= 0)
8792 {
8793 clear_mouse_face (dpyinfo);
8794 return;
8795 }
8796
8797 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
8798 if (rc < 0)
8799 {
8800 /* Not on tool-bar item. */
8801 clear_mouse_face (dpyinfo);
8802 return;
8803 }
8804 else if (rc == 0)
8805 /* On same tool-bar item as before. */
8806 goto set_help_echo;
8807
8808 clear_mouse_face (dpyinfo);
8809
8810 /* Mouse is down, but on different tool-bar item? */
8811 mouse_down_p = (dpyinfo->grabbed
8812 && f == last_mouse_frame
8813 && FRAME_LIVE_P (f));
8814 if (mouse_down_p
8815 && last_tool_bar_item != prop_idx)
8816 return;
8817
8818 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
8819 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
8820
8821 /* If tool-bar item is not enabled, don't highlight it. */
8822 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
8823 if (!NILP (enabled_p))
8824 {
8825 /* Compute the x-position of the glyph. In front and past the
da8b7f4f 8826 image is a space. We include this in the highlighted area. */
fa3c6b4d
KS
8827 row = MATRIX_ROW (w->current_matrix, vpos);
8828 for (i = x = 0; i < hpos; ++i)
8829 x += row->glyphs[TEXT_AREA][i].pixel_width;
8830
8831 /* Record this as the current active region. */
8832 dpyinfo->mouse_face_beg_col = hpos;
8833 dpyinfo->mouse_face_beg_row = vpos;
8834 dpyinfo->mouse_face_beg_x = x;
8835 dpyinfo->mouse_face_beg_y = row->y;
8836 dpyinfo->mouse_face_past_end = 0;
8837
8838 dpyinfo->mouse_face_end_col = hpos + 1;
8839 dpyinfo->mouse_face_end_row = vpos;
8840 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
8841 dpyinfo->mouse_face_end_y = row->y;
8842 dpyinfo->mouse_face_window = window;
8843 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
8844
8845 /* Display it as active. */
8846 show_mouse_face (dpyinfo, draw);
8847 dpyinfo->mouse_face_image_state = draw;
8848 }
8849
8850 set_help_echo:
8851
8852 /* Set help_echo_string to a help string to display for this tool-bar item.
8853 XTread_socket does the rest. */
8854 help_echo_object = help_echo_window = Qnil;
8855 help_echo_pos = -1;
8856 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
8857 if (NILP (help_echo_string))
8858 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
8859}
8860
5f5c8ee5 8861#endif /* HAVE_WINDOW_SYSTEM */
ffbbc941
KS
8862
8863
8864\f
8865/***********************************************************************
8866 Fringes
8867 ***********************************************************************/
8868
8869#ifdef HAVE_WINDOW_SYSTEM
8870
8871/* An arrow like this: `<-'. */
8872static unsigned char left_bits[] = {
8873 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
8874
8875/* Right truncation arrow bitmap `->'. */
8876static unsigned char right_bits[] = {
8877 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
8878
8879/* Marker for continued lines. */
8880static unsigned char continued_bits[] = {
8881 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
8882
8883/* Marker for continuation lines. */
8884static unsigned char continuation_bits[] = {
8885 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
8886
8887/* Overlay arrow bitmap. A triangular arrow. */
8888static unsigned char ov_bits[] = {
8889 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
8890
8891/* Bitmap drawn to indicate lines not displaying text if
8892 `indicate-empty-lines' is non-nil. */
8893static unsigned char zv_bits[] = {
8894 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
8895 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
8896 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
8897 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
8898 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
8899 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
8900 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
8901 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
8902
8903struct fringe_bitmap fringe_bitmaps[MAX_FRINGE_BITMAPS] =
8904{
8905 { 0, 0, 0, NULL /* NO_FRINGE_BITMAP */ },
8906 { 8, sizeof (left_bits), 0, left_bits },
8907 { 8, sizeof (right_bits), 0, right_bits },
8908 { 8, sizeof (continued_bits), 0, continued_bits },
8909 { 8, sizeof (continuation_bits), 0, continuation_bits },
8910 { 8, sizeof (ov_bits), 0, ov_bits },
8911 { 8, sizeof (zv_bits), 3, zv_bits }
8912};
8913
8914
8915/* Draw the bitmap WHICH in one of the left or right fringes of
8916 window W. ROW is the glyph row for which to display the bitmap; it
8917 determines the vertical position at which the bitmap has to be
8918 drawn. */
8919
8920static void
8921draw_fringe_bitmap (w, row, which, left_p)
8922 struct window *w;
8923 struct glyph_row *row;
8924 enum fringe_bitmap_type which;
8925 int left_p;
8926{
8927 struct frame *f = XFRAME (WINDOW_FRAME (w));
8928 struct draw_fringe_bitmap_params p;
8929
8930 /* Convert row to frame coordinates. */
8931 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8932
8933 p.which = which;
8934 p.wd = fringe_bitmaps[which].width;
8935
8936 p.h = fringe_bitmaps[which].height;
8937 p.dh = (fringe_bitmaps[which].period
8938 ? (p.y % fringe_bitmaps[which].period)
8939 : 0);
8940 p.h -= p.dh;
8941 /* Clip bitmap if too high. */
8942 if (p.h > row->height)
8943 p.h = row->height;
8944
8945 p.face = FACE_FROM_ID (f, FRINGE_FACE_ID);
8946 PREPARE_FACE_FOR_DISPLAY (f, p.face);
8947
8948 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
8949 the fringe. */
8950 p.bx = -1;
8951 if (left_p)
8952 {
da8b7f4f
KS
8953 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
8954 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
8955 ? LEFT_MARGIN_AREA
8956 : TEXT_AREA));
8957 if (p.wd > wd)
8958 p.wd = wd;
8959 p.x = x - p.wd - (wd - p.wd) / 2;
8960
8961 if (p.wd < wd || row->height > p.h)
ffbbc941
KS
8962 {
8963 /* If W has a vertical border to its left, don't draw over it. */
da8b7f4f
KS
8964 wd -= ((!WINDOW_LEFTMOST_P (w)
8965 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
8966 ? 1 : 0);
8967 p.bx = x - wd;
8968 p.nx = wd;
ffbbc941
KS
8969 }
8970 }
8971 else
8972 {
da8b7f4f
KS
8973 int x = window_box_right (w,
8974 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
8975 ? RIGHT_MARGIN_AREA
8976 : TEXT_AREA));
8977 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
8978 if (p.wd > wd)
8979 p.wd = wd;
8980 p.x = x + (wd - p.wd) / 2;
ffbbc941
KS
8981 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
8982 the fringe. */
da8b7f4f 8983 if (p.wd < wd || row->height > p.h)
ffbbc941 8984 {
da8b7f4f
KS
8985 p.bx = x;
8986 p.nx = wd;
ffbbc941
KS
8987 }
8988 }
8989
8990 if (p.bx >= 0)
8991 {
da8b7f4f 8992 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
ffbbc941
KS
8993
8994 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
8995 p.ny = row->visible_height;
8996 }
8997
8998 /* Adjust y to the offset in the row to start drawing the bitmap. */
8999 p.y += (row->height - p.h) / 2;
9000
9001 rif->draw_fringe_bitmap (w, row, &p);
9002}
9003
9004/* Draw fringe bitmaps for glyph row ROW on window W. Call this
9005 function with input blocked. */
9006
9007void
9008draw_row_fringe_bitmaps (w, row)
9009 struct window *w;
9010 struct glyph_row *row;
9011{
ffbbc941
KS
9012 enum fringe_bitmap_type bitmap;
9013
9014 xassert (interrupt_input_blocked);
9015
9016 /* If row is completely invisible, because of vscrolling, we
9017 don't have to draw anything. */
9018 if (row->visible_height <= 0)
9019 return;
9020
da8b7f4f 9021 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
ffbbc941
KS
9022 {
9023 /* Decide which bitmap to draw in the left fringe. */
9024 if (row->overlay_arrow_p)
9025 bitmap = OVERLAY_ARROW_BITMAP;
9026 else if (row->truncated_on_left_p)
9027 bitmap = LEFT_TRUNCATION_BITMAP;
9028 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
9029 bitmap = CONTINUATION_LINE_BITMAP;
9030 else if (row->indicate_empty_line_p)
9031 bitmap = ZV_LINE_BITMAP;
9032 else
9033 bitmap = NO_FRINGE_BITMAP;
9034
9035 draw_fringe_bitmap (w, row, bitmap, 1);
9036 }
9037
da8b7f4f 9038 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
ffbbc941
KS
9039 {
9040 /* Decide which bitmap to draw in the right fringe. */
9041 if (row->truncated_on_right_p)
9042 bitmap = RIGHT_TRUNCATION_BITMAP;
9043 else if (row->continued_p)
9044 bitmap = CONTINUED_LINE_BITMAP;
da8b7f4f 9045 else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
ffbbc941
KS
9046 bitmap = ZV_LINE_BITMAP;
9047 else
9048 bitmap = NO_FRINGE_BITMAP;
9049
9050 draw_fringe_bitmap (w, row, bitmap, 0);
9051 }
9052}
9053
9054
9055/* Compute actual fringe widths */
9056
9057void
9058compute_fringe_widths (f, redraw)
9059 struct frame *f;
9060 int redraw;
9061{
da8b7f4f
KS
9062 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
9063 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
9064 int o_cols = FRAME_FRINGE_COLS (f);
ffbbc941
KS
9065
9066 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9067 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9068 int left_fringe_width, right_fringe_width;
9069
9070 if (!NILP (left_fringe))
9071 left_fringe = Fcdr (left_fringe);
9072 if (!NILP (right_fringe))
9073 right_fringe = Fcdr (right_fringe);
9074
9075 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9076 XINT (left_fringe));
9077 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9078 XINT (right_fringe));
9079
9080 if (left_fringe_width || right_fringe_width)
9081 {
9082 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9083 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9084 int conf_wid = left_wid + right_wid;
da8b7f4f 9085 int font_wid = FRAME_COLUMN_WIDTH (f);
ffbbc941
KS
9086 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9087 int real_wid = cols * font_wid;
9088 if (left_wid && right_wid)
9089 {
9090 if (left_fringe_width < 0)
9091 {
9092 /* Left fringe width is fixed, adjust right fringe if necessary */
da8b7f4f
KS
9093 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
9094 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
ffbbc941
KS
9095 }
9096 else if (right_fringe_width < 0)
9097 {
9098 /* Right fringe width is fixed, adjust left fringe if necessary */
da8b7f4f
KS
9099 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
9100 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
ffbbc941
KS
9101 }
9102 else
9103 {
9104 /* Adjust both fringes with an equal amount.
9105 Note that we are doing integer arithmetic here, so don't
9106 lose a pixel if the total width is an odd number. */
9107 int fill = real_wid - conf_wid;
da8b7f4f
KS
9108 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
9109 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
ffbbc941
KS
9110 }
9111 }
9112 else if (left_fringe_width)
9113 {
da8b7f4f
KS
9114 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
9115 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
ffbbc941
KS
9116 }
9117 else
9118 {
da8b7f4f
KS
9119 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
9120 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
ffbbc941 9121 }
da8b7f4f 9122 FRAME_FRINGE_COLS (f) = cols;
ffbbc941
KS
9123 }
9124 else
9125 {
da8b7f4f
KS
9126 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
9127 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
9128 FRAME_FRINGE_COLS (f) = 0;
ffbbc941
KS
9129 }
9130
9131 if (redraw && FRAME_VISIBLE_P (f))
da8b7f4f
KS
9132 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
9133 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
9134 o_cols != FRAME_FRINGE_COLS (f))
ffbbc941
KS
9135 redraw_frame (f);
9136}
9137
9138#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 9139
feb0c42f 9140
5f5c8ee5
GM
9141\f
9142/************************************************************************
9143 Horizontal scrolling
9144 ************************************************************************/
feb0c42f 9145
5f5c8ee5
GM
9146static int hscroll_window_tree P_ ((Lisp_Object));
9147static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 9148
5f5c8ee5
GM
9149/* For all leaf windows in the window tree rooted at WINDOW, set their
9150 hscroll value so that PT is (i) visible in the window, and (ii) so
9151 that it is not within a certain margin at the window's left and
9152 right border. Value is non-zero if any window's hscroll has been
9153 changed. */
9154
9155static int
9156hscroll_window_tree (window)
9157 Lisp_Object window;
9158{
9159 int hscrolled_p = 0;
e76d28d5 9160 int hscroll_relative_p = FLOATP (Vhscroll_step);
1df7e8f0
EZ
9161 int hscroll_step_abs = 0;
9162 double hscroll_step_rel = 0;
9163
9164 if (hscroll_relative_p)
9165 {
e76d28d5 9166 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
1df7e8f0
EZ
9167 if (hscroll_step_rel < 0)
9168 {
9169 hscroll_relative_p = 0;
9170 hscroll_step_abs = 0;
9171 }
9172 }
e76d28d5 9173 else if (INTEGERP (Vhscroll_step))
1df7e8f0 9174 {
e76d28d5 9175 hscroll_step_abs = XINT (Vhscroll_step);
1df7e8f0
EZ
9176 if (hscroll_step_abs < 0)
9177 hscroll_step_abs = 0;
9178 }
9179 else
9180 hscroll_step_abs = 0;
9181
5f5c8ee5 9182 while (WINDOWP (window))
90adcf20 9183 {
5f5c8ee5 9184 struct window *w = XWINDOW (window);
1df7e8f0 9185
5f5c8ee5
GM
9186 if (WINDOWP (w->hchild))
9187 hscrolled_p |= hscroll_window_tree (w->hchild);
9188 else if (WINDOWP (w->vchild))
9189 hscrolled_p |= hscroll_window_tree (w->vchild);
9190 else if (w->cursor.vpos >= 0)
9191 {
da8b7f4f
KS
9192 int h_margin;
9193 int text_area_width;
92a90e89
GM
9194 struct glyph_row *current_cursor_row
9195 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
9196 struct glyph_row *desired_cursor_row
9197 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
9198 struct glyph_row *cursor_row
9199 = (desired_cursor_row->enabled_p
9200 ? desired_cursor_row
9201 : current_cursor_row);
a2725ab2 9202
da8b7f4f 9203 text_area_width = window_box_width (w, TEXT_AREA);
90adcf20 9204
5f5c8ee5 9205 /* Scroll when cursor is inside this scroll margin. */
da8b7f4f 9206 h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
1df7e8f0 9207
5f5c8ee5 9208 if ((XFASTINT (w->hscroll)
e76d28d5 9209 && w->cursor.x <= h_margin)
92a90e89
GM
9210 || (cursor_row->enabled_p
9211 && cursor_row->truncated_on_right_p
e76d28d5 9212 && (w->cursor.x >= text_area_width - h_margin)))
08b610e4 9213 {
5f5c8ee5
GM
9214 struct it it;
9215 int hscroll;
9216 struct buffer *saved_current_buffer;
9217 int pt;
1df7e8f0 9218 int wanted_x;
5f5c8ee5
GM
9219
9220 /* Find point in a display of infinite width. */
9221 saved_current_buffer = current_buffer;
9222 current_buffer = XBUFFER (w->buffer);
1df7e8f0 9223
5f5c8ee5
GM
9224 if (w == XWINDOW (selected_window))
9225 pt = BUF_PT (current_buffer);
9226 else
08b610e4 9227 {
5f5c8ee5
GM
9228 pt = marker_position (w->pointm);
9229 pt = max (BEGV, pt);
9230 pt = min (ZV, pt);
9231 }
9232
9233 /* Move iterator to pt starting at cursor_row->start in
9234 a line with infinite width. */
9235 init_to_row_start (&it, w, cursor_row);
9236 it.last_visible_x = INFINITY;
9237 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
9238 current_buffer = saved_current_buffer;
9239
1df7e8f0
EZ
9240 /* Position cursor in window. */
9241 if (!hscroll_relative_p && hscroll_step_abs == 0)
9242 hscroll = max (0, it.current_x - text_area_width / 2)
da8b7f4f 9243 / FRAME_COLUMN_WIDTH (it.f);
e76d28d5 9244 else if (w->cursor.x >= text_area_width - h_margin)
1df7e8f0
EZ
9245 {
9246 if (hscroll_relative_p)
9247 wanted_x = text_area_width * (1 - hscroll_step_rel)
e76d28d5 9248 - h_margin;
1df7e8f0
EZ
9249 else
9250 wanted_x = text_area_width
da8b7f4f 9251 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
e76d28d5 9252 - h_margin;
1df7e8f0 9253 hscroll
da8b7f4f 9254 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
1df7e8f0
EZ
9255 }
9256 else
9257 {
9258 if (hscroll_relative_p)
9259 wanted_x = text_area_width * hscroll_step_rel
e76d28d5 9260 + h_margin;
1df7e8f0 9261 else
da8b7f4f 9262 wanted_x = hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
e76d28d5 9263 + h_margin;
1df7e8f0 9264 hscroll
da8b7f4f 9265 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
1df7e8f0 9266 }
3172f70b 9267 hscroll = max (hscroll, XFASTINT (w->min_hscroll));
5f5c8ee5
GM
9268
9269 /* Don't call Fset_window_hscroll if value hasn't
9270 changed because it will prevent redisplay
9271 optimizations. */
9272 if (XFASTINT (w->hscroll) != hscroll)
9273 {
3172f70b
GM
9274 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
9275 w->hscroll = make_number (hscroll);
5f5c8ee5 9276 hscrolled_p = 1;
08b610e4 9277 }
08b610e4 9278 }
08b610e4 9279 }
a2725ab2 9280
5f5c8ee5 9281 window = w->next;
90adcf20 9282 }
cd6dfed6 9283
5f5c8ee5
GM
9284 /* Value is non-zero if hscroll of any leaf window has been changed. */
9285 return hscrolled_p;
9286}
9287
9288
9289/* Set hscroll so that cursor is visible and not inside horizontal
9290 scroll margins for all windows in the tree rooted at WINDOW. See
9291 also hscroll_window_tree above. Value is non-zero if any window's
9292 hscroll has been changed. If it has, desired matrices on the frame
9293 of WINDOW are cleared. */
9294
9295static int
9296hscroll_windows (window)
9297 Lisp_Object window;
9298{
d475bcb8 9299 int hscrolled_p;
2311178e 9300
d475bcb8
GM
9301 if (automatic_hscrolling_p)
9302 {
9303 hscrolled_p = hscroll_window_tree (window);
9304 if (hscrolled_p)
9305 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
9306 }
9307 else
9308 hscrolled_p = 0;
5f5c8ee5 9309 return hscrolled_p;
90adcf20 9310}
5f5c8ee5
GM
9311
9312
90adcf20 9313\f
5f5c8ee5
GM
9314/************************************************************************
9315 Redisplay
9316 ************************************************************************/
9317
9318/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
9319 to a non-zero value. This is sometimes handy to have in a debugger
9320 session. */
9321
9322#if GLYPH_DEBUG
a2889657 9323
5f5c8ee5
GM
9324/* First and last unchanged row for try_window_id. */
9325
9326int debug_first_unchanged_at_end_vpos;
9327int debug_last_unchanged_at_beg_vpos;
9328
9329/* Delta vpos and y. */
9330
9331int debug_dvpos, debug_dy;
9332
9333/* Delta in characters and bytes for try_window_id. */
9334
9335int debug_delta, debug_delta_bytes;
9336
9337/* Values of window_end_pos and window_end_vpos at the end of
9338 try_window_id. */
9339
31ade731 9340EMACS_INT debug_end_pos, debug_end_vpos;
5f5c8ee5
GM
9341
9342/* Append a string to W->desired_matrix->method. FMT is a printf
9343 format string. A1...A9 are a supplement for a variable-length
9344 argument list. If trace_redisplay_p is non-zero also printf the
9345 resulting string to stderr. */
9346
9347static void
9348debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
9349 struct window *w;
9350 char *fmt;
9351 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
9352{
9353 char buffer[512];
9354 char *method = w->desired_matrix->method;
9355 int len = strlen (method);
9356 int size = sizeof w->desired_matrix->method;
9357 int remaining = size - len - 1;
9358
9359 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
9360 if (len && remaining)
9361 {
9362 method[len] = '|';
9363 --remaining, ++len;
9364 }
2311178e 9365
5f5c8ee5
GM
9366 strncpy (method + len, buffer, remaining);
9367
9368 if (trace_redisplay_p)
9369 fprintf (stderr, "%p (%s): %s\n",
9370 w,
9371 ((BUFFERP (w->buffer)
9372 && STRINGP (XBUFFER (w->buffer)->name))
2051c264 9373 ? (char *) SDATA (XBUFFER (w->buffer)->name)
5f5c8ee5
GM
9374 : "no buffer"),
9375 buffer);
9376}
a2889657 9377
5f5c8ee5 9378#endif /* GLYPH_DEBUG */
90adcf20 9379
a2889657 9380
5f5c8ee5
GM
9381/* Value is non-zero if all changes in window W, which displays
9382 current_buffer, are in the text between START and END. START is a
9383 buffer position, END is given as a distance from Z. Used in
9384 redisplay_internal for display optimization. */
9385
9386static INLINE int
9387text_outside_line_unchanged_p (w, start, end)
9388 struct window *w;
9389 int start, end;
9390{
9391 int unchanged_p = 1;
2311178e 9392
5f5c8ee5
GM
9393 /* If text or overlays have changed, see where. */
9394 if (XFASTINT (w->last_modified) < MODIFF
9395 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
9396 {
9397 /* Gap in the line? */
9398 if (GPT < start || Z - GPT < end)
9399 unchanged_p = 0;
9400
9401 /* Changes start in front of the line, or end after it? */
9402 if (unchanged_p
9142dd5b
GM
9403 && (BEG_UNCHANGED < start - 1
9404 || END_UNCHANGED < end))
5f5c8ee5 9405 unchanged_p = 0;
2311178e 9406
5f5c8ee5
GM
9407 /* If selective display, can't optimize if changes start at the
9408 beginning of the line. */
9409 if (unchanged_p
9410 && INTEGERP (current_buffer->selective_display)
9411 && XINT (current_buffer->selective_display) > 0
9142dd5b 9412 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5 9413 unchanged_p = 0;
47d57b22
GM
9414
9415 /* If there are overlays at the start or end of the line, these
9416 may have overlay strings with newlines in them. A change at
9417 START, for instance, may actually concern the display of such
9418 overlay strings as well, and they are displayed on different
9419 lines. So, quickly rule out this case. (For the future, it
9420 might be desirable to implement something more telling than
9421 just BEG/END_UNCHANGED.) */
9422 if (unchanged_p)
9423 {
9424 if (BEG + BEG_UNCHANGED == start
9425 && overlay_touches_p (start))
9426 unchanged_p = 0;
9427 if (END_UNCHANGED == end
9428 && overlay_touches_p (Z - end))
9429 unchanged_p = 0;
9430 }
5f5c8ee5
GM
9431 }
9432
9433 return unchanged_p;
9434}
9435
9436
9437/* Do a frame update, taking possible shortcuts into account. This is
9438 the main external entry point for redisplay.
9439
9440 If the last redisplay displayed an echo area message and that message
9441 is no longer requested, we clear the echo area or bring back the
9442 mini-buffer if that is in use. */
20de20dc 9443
a2889657
JB
9444void
9445redisplay ()
e9874cee
RS
9446{
9447 redisplay_internal (0);
9448}
9449
47d57b22 9450
260a86a0
KH
9451/* Return 1 if point moved out of or into a composition. Otherwise
9452 return 0. PREV_BUF and PREV_PT are the last point buffer and
9453 position. BUF and PT are the current point buffer and position. */
9454
9455int
9456check_point_in_composition (prev_buf, prev_pt, buf, pt)
9457 struct buffer *prev_buf, *buf;
9458 int prev_pt, pt;
9459{
9460 int start, end;
9461 Lisp_Object prop;
9462 Lisp_Object buffer;
9463
9464 XSETBUFFER (buffer, buf);
9465 /* Check a composition at the last point if point moved within the
9466 same buffer. */
9467 if (prev_buf == buf)
9468 {
9469 if (prev_pt == pt)
9470 /* Point didn't move. */
9471 return 0;
2311178e 9472
260a86a0
KH
9473 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
9474 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
9475 && COMPOSITION_VALID_P (start, end, prop)
9476 && start < prev_pt && end > prev_pt)
9477 /* The last point was within the composition. Return 1 iff
9478 point moved out of the composition. */
9479 return (pt <= start || pt >= end);
9480 }
9481
9482 /* Check a composition at the current point. */
9483 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
9484 && find_composition (pt, -1, &start, &end, &prop, buffer)
9485 && COMPOSITION_VALID_P (start, end, prop)
9486 && start < pt && end > pt);
9487}
5f5c8ee5 9488
47d57b22 9489
9142dd5b
GM
9490/* Reconsider the setting of B->clip_changed which is displayed
9491 in window W. */
9492
9493static INLINE void
9494reconsider_clip_changes (w, b)
9495 struct window *w;
9496 struct buffer *b;
9497{
c62c1bb5 9498 if (b->clip_changed
9142dd5b
GM
9499 && !NILP (w->window_end_valid)
9500 && w->current_matrix->buffer == b
9501 && w->current_matrix->zv == BUF_ZV (b)
9502 && w->current_matrix->begv == BUF_BEGV (b))
9503 b->clip_changed = 0;
260a86a0
KH
9504
9505 /* If display wasn't paused, and W is not a tool bar window, see if
9506 point has been moved into or out of a composition. In that case,
9507 we set b->clip_changed to 1 to force updating the screen. If
9508 b->clip_changed has already been set to 1, we can skip this
9509 check. */
9510 if (!b->clip_changed
9511 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
9512 {
9513 int pt;
9514
9515 if (w == XWINDOW (selected_window))
9516 pt = BUF_PT (current_buffer);
9517 else
9518 pt = marker_position (w->pointm);
9519
9520 if ((w->current_matrix->buffer != XBUFFER (w->buffer)
6fc556fd 9521 || pt != XINT (w->last_point))
260a86a0 9522 && check_point_in_composition (w->current_matrix->buffer,
6fc556fd 9523 XINT (w->last_point),
260a86a0
KH
9524 XBUFFER (w->buffer), pt))
9525 b->clip_changed = 1;
9526 }
9142dd5b 9527}
aac2d8b2
RS
9528\f
9529#define STOP_POLLING \
9530do { if (! polling_stopped_here) stop_polling (); \
9531 polling_stopped_here = 1; } while (0)
9532
9533#define RESUME_POLLING \
9534do { if (polling_stopped_here) start_polling (); \
9535 polling_stopped_here = 0; } while (0)
9142dd5b
GM
9536
9537
5f5c8ee5
GM
9538/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
9539 response to any user action; therefore, we should preserve the echo
9540 area. (Actually, our caller does that job.) Perhaps in the future
9541 avoid recentering windows if it is not necessary; currently that
9542 causes some problems. */
e9874cee
RS
9543
9544static void
9545redisplay_internal (preserve_echo_area)
9546 int preserve_echo_area;
a2889657 9547{
5f5c8ee5
GM
9548 struct window *w = XWINDOW (selected_window);
9549 struct frame *f = XFRAME (w->frame);
9550 int pause;
a2889657 9551 int must_finish = 0;
5f5c8ee5 9552 struct text_pos tlbufpos, tlendpos;
89819bdd 9553 int number_of_visible_frames;
28514cd9 9554 int count;
886bd6f2 9555 struct frame *sf = SELECTED_FRAME ();
aac2d8b2 9556 int polling_stopped_here = 0;
a2889657 9557
5f5c8ee5
GM
9558 /* Non-zero means redisplay has to consider all windows on all
9559 frames. Zero means, only selected_window is considered. */
9560 int consider_all_windows_p;
2311178e 9561
5f5c8ee5
GM
9562 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
9563
9564 /* No redisplay if running in batch mode or frame is not yet fully
9565 initialized, or redisplay is explicitly turned off by setting
9566 Vinhibit_redisplay. */
9567 if (noninteractive
9568 || !NILP (Vinhibit_redisplay)
9569 || !f->glyphs_initialized_p)
a2889657
JB
9570 return;
9571
5f5c8ee5
GM
9572 /* The flag redisplay_performed_directly_p is set by
9573 direct_output_for_insert when it already did the whole screen
9574 update necessary. */
9575 if (redisplay_performed_directly_p)
9576 {
9577 redisplay_performed_directly_p = 0;
9578 if (!hscroll_windows (selected_window))
9579 return;
9580 }
9581
488dd4c4 9582#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
15f0cf78
RS
9583 if (popup_activated ())
9584 return;
9585#endif
9586
28514cd9 9587 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 9588 if (redisplaying_p)
735c094c
KH
9589 return;
9590
28514cd9
GM
9591 /* Record a function that resets redisplaying_p to its old value
9592 when we leave this function. */
331379bf 9593 count = SPECPDL_INDEX ();
28514cd9
GM
9594 record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
9595 ++redisplaying_p;
26683087 9596 specbind (Qinhibit_free_realized_faces, Qnil);
2311178e 9597
8b32d885 9598 retry:
bd9d0f3f 9599 pause = 0;
9142dd5b
GM
9600 reconsider_clip_changes (w, current_buffer);
9601
5f5c8ee5
GM
9602 /* If new fonts have been loaded that make a glyph matrix adjustment
9603 necessary, do it. */
9604 if (fonts_changed_p)
9605 {
9606 adjust_glyphs (NULL);
9607 ++windows_or_buffers_changed;
9608 fonts_changed_p = 0;
9609 }
9610
6961e0c1
GM
9611 /* If face_change_count is non-zero, init_iterator will free all
9612 realized faces, which includes the faces referenced from current
9613 matrices. So, we can't reuse current matrices in this case. */
9614 if (face_change_count)
9615 ++windows_or_buffers_changed;
9616
886bd6f2
GM
9617 if (! FRAME_WINDOW_P (sf)
9618 && previous_terminal_frame != sf)
20de20dc 9619 {
5f5c8ee5
GM
9620 /* Since frames on an ASCII terminal share the same display
9621 area, displaying a different frame means redisplay the whole
9622 thing. */
20de20dc 9623 windows_or_buffers_changed++;
886bd6f2
GM
9624 SET_FRAME_GARBAGED (sf);
9625 XSETFRAME (Vterminal_frame, sf);
20de20dc 9626 }
886bd6f2 9627 previous_terminal_frame = sf;
20de20dc 9628
5f5c8ee5
GM
9629 /* Set the visible flags for all frames. Do this before checking
9630 for resized or garbaged frames; they want to know if their frames
9631 are visible. See the comment in frame.h for
9632 FRAME_SAMPLE_VISIBILITY. */
d724d989 9633 {
35f56f96 9634 Lisp_Object tail, frame;
d724d989 9635
89819bdd
RS
9636 number_of_visible_frames = 0;
9637
35f56f96 9638 FOR_EACH_FRAME (tail, frame)
f82aff7c 9639 {
5f5c8ee5 9640 struct frame *f = XFRAME (frame);
2311178e 9641
5f5c8ee5
GM
9642 FRAME_SAMPLE_VISIBILITY (f);
9643 if (FRAME_VISIBLE_P (f))
9644 ++number_of_visible_frames;
9645 clear_desired_matrices (f);
f82aff7c 9646 }
d724d989
JB
9647 }
9648
44fa5b1e 9649 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 9650 do_pending_window_change (1);
a2889657 9651
5f5c8ee5 9652 /* Clear frames marked as garbaged. */
44fa5b1e 9653 if (frame_garbaged)
c6e89d6c 9654 clear_garbaged_frames ();
a2889657 9655
e037b9ec 9656 /* Build menubar and tool-bar items. */
f82aff7c
RS
9657 prepare_menu_bars ();
9658
28995e67 9659 if (windows_or_buffers_changed)
a2889657
JB
9660 update_mode_lines++;
9661
538f13d4
RS
9662 /* Detect case that we need to write or remove a star in the mode line. */
9663 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
9664 {
9665 w->update_mode_line = Qt;
9666 if (buffer_shared > 1)
9667 update_mode_lines++;
9668 }
9669
5f5c8ee5 9670 /* If %c is in the mode line, update it if needed. */
28995e67
RS
9671 if (!NILP (w->column_number_displayed)
9672 /* This alternative quickly identifies a common case
9673 where no change is needed. */
9674 && !(PT == XFASTINT (w->last_point)
8850a573
RS
9675 && XFASTINT (w->last_modified) >= MODIFF
9676 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
9677 && (XFASTINT (w->column_number_displayed)
9678 != (int) current_column ())) /* iftc */
9679 w->update_mode_line = Qt;
28995e67 9680
44fa5b1e 9681 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 9682
5f5c8ee5
GM
9683 /* The variable buffer_shared is set in redisplay_window and
9684 indicates that we redisplay a buffer in different windows. See
9685 there. */
5fb96e96
RS
9686 consider_all_windows_p = (update_mode_lines || buffer_shared > 1
9687 || cursor_type_changed);
a2889657
JB
9688
9689 /* If specs for an arrow have changed, do thorough redisplay
9690 to ensure we remove any arrow that should no longer exist. */
d45de95b 9691 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 9692 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 9693 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 9694
90adcf20
RS
9695 /* Normally the message* functions will have already displayed and
9696 updated the echo area, but the frame may have been trashed, or
9697 the update may have been preempted, so display the echo area
6e019995 9698 again here. Checking message_cleared_p captures the case that
c6e89d6c 9699 the echo area should be cleared. */
96d5e9a0
GM
9700 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
9701 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
3fa69ee7
GM
9702 || (message_cleared_p
9703 && minibuf_level == 0
9704 /* If the mini-window is currently selected, this means the
9705 echo-area doesn't show through. */
9706 && !MINI_WINDOW_P (XWINDOW (selected_window))))
90adcf20 9707 {
c6e89d6c 9708 int window_height_changed_p = echo_area_display (0);
90adcf20 9709 must_finish = 1;
6e019995
GM
9710
9711 /* If we don't display the current message, don't clear the
9712 message_cleared_p flag, because, if we did, we wouldn't clear
9713 the echo area in the next redisplay which doesn't preserve
9714 the echo area. */
9715 if (!display_last_displayed_message_p)
9716 message_cleared_p = 0;
2311178e 9717
c6e89d6c
GM
9718 if (fonts_changed_p)
9719 goto retry;
9720 else if (window_height_changed_p)
9721 {
9722 consider_all_windows_p = 1;
9723 ++update_mode_lines;
9724 ++windows_or_buffers_changed;
2311178e 9725
9142dd5b
GM
9726 /* If window configuration was changed, frames may have been
9727 marked garbaged. Clear them or we will experience
9728 surprises wrt scrolling. */
9729 if (frame_garbaged)
9730 clear_garbaged_frames ();
c6e89d6c 9731 }
90adcf20 9732 }
97a36635 9733 else if (EQ (selected_window, minibuf_window)
dd2eb166
GM
9734 && (current_buffer->clip_changed
9735 || XFASTINT (w->last_modified) < MODIFF
9736 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 9737 && resize_mini_window (w, 0))
c6e89d6c
GM
9738 {
9739 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
9740 showing if its contents might have changed. */
9741 must_finish = 1;
9742 consider_all_windows_p = 1;
c6e89d6c 9743 ++windows_or_buffers_changed;
dd2eb166 9744 ++update_mode_lines;
2311178e 9745
9142dd5b
GM
9746 /* If window configuration was changed, frames may have been
9747 marked garbaged. Clear them or we will experience
9748 surprises wrt scrolling. */
9749 if (frame_garbaged)
9750 clear_garbaged_frames ();
c6e89d6c 9751 }
2311178e 9752
90adcf20 9753
5f5c8ee5
GM
9754 /* If showing the region, and mark has changed, we must redisplay
9755 the whole window. The assignment to this_line_start_pos prevents
9756 the optimization directly below this if-statement. */
bd66d1ba
RS
9757 if (((!NILP (Vtransient_mark_mode)
9758 && !NILP (XBUFFER (w->buffer)->mark_active))
9759 != !NILP (w->region_showing))
82d04750
JB
9760 || (!NILP (w->region_showing)
9761 && !EQ (w->region_showing,
9762 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
9763 CHARPOS (this_line_start_pos) = 0;
9764
9765 /* Optimize the case that only the line containing the cursor in the
9766 selected window has changed. Variables starting with this_ are
9767 set in display_line and record information about the line
9768 containing the cursor. */
9769 tlbufpos = this_line_start_pos;
9770 tlendpos = this_line_end_pos;
9771 if (!consider_all_windows_p
9772 && CHARPOS (tlbufpos) > 0
9773 && NILP (w->update_mode_line)
73af359d 9774 && !current_buffer->clip_changed
c62c1bb5 9775 && !current_buffer->prevent_redisplay_optimizations_p
44fa5b1e 9776 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 9777 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 9778 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
9779 && this_line_buffer == current_buffer
9780 && current_buffer == XBUFFER (w->buffer)
265a9e55 9781 && NILP (w->force_start)
acda20e1 9782 && NILP (w->optional_new_start)
5f5c8ee5
GM
9783 /* Point must be on the line that we have info recorded about. */
9784 && PT >= CHARPOS (tlbufpos)
9785 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
9786 /* All text outside that line, including its final newline,
9787 must be unchanged */
5f5c8ee5
GM
9788 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
9789 CHARPOS (tlendpos)))
9790 {
9791 if (CHARPOS (tlbufpos) > BEGV
9792 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
9793 && (CHARPOS (tlbufpos) == ZV
9794 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
9795 /* Former continuation line has disappeared by becoming empty */
9796 goto cancel;
9797 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 9798 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
9799 || MINI_WINDOW_P (w))
9800 {
1c9241f5
KH
9801 /* We have to handle the case of continuation around a
9802 wide-column character (See the comment in indent.c around
9803 line 885).
9804
9805 For instance, in the following case:
9806
9807 -------- Insert --------
9808 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
9809 J_I_ ==> J_I_ `^^' are cursors.
9810 ^^ ^^
9811 -------- --------
9812
9813 As we have to redraw the line above, we should goto cancel. */
9814
5f5c8ee5
GM
9815 struct it it;
9816 int line_height_before = this_line_pixel_height;
9817
9818 /* Note that start_display will handle the case that the
9819 line starting at tlbufpos is a continuation lines. */
9820 start_display (&it, w, tlbufpos);
9821
9822 /* Implementation note: It this still necessary? */
9823 if (it.current_x != this_line_start_x)
1c9241f5
KH
9824 goto cancel;
9825
5f5c8ee5
GM
9826 TRACE ((stderr, "trying display optimization 1\n"));
9827 w->cursor.vpos = -1;
a2889657 9828 overlay_arrow_seen = 0;
5f5c8ee5
GM
9829 it.vpos = this_line_vpos;
9830 it.current_y = this_line_y;
9831 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
9832 display_line (&it);
9833
a2889657 9834 /* If line contains point, is not continued,
5f5c8ee5 9835 and ends at same distance from eob as before, we win */
2311178e 9836 if (w->cursor.vpos >= 0
5f5c8ee5
GM
9837 /* Line is not continued, otherwise this_line_start_pos
9838 would have been set to 0 in display_line. */
9839 && CHARPOS (this_line_start_pos)
9840 /* Line ends as before. */
9841 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
9842 /* Line has same height as before. Otherwise other lines
9843 would have to be shifted up or down. */
9844 && this_line_pixel_height == line_height_before)
a2889657 9845 {
5f5c8ee5
GM
9846 /* If this is not the window's last line, we must adjust
9847 the charstarts of the lines below. */
9848 if (it.current_y < it.last_visible_y)
9849 {
9850 struct glyph_row *row
9851 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
9852 int delta, delta_bytes;
2311178e 9853
5f5c8ee5
GM
9854 if (Z - CHARPOS (tlendpos) == ZV)
9855 {
9856 /* This line ends at end of (accessible part of)
9857 buffer. There is no newline to count. */
9858 delta = (Z
9859 - CHARPOS (tlendpos)
9860 - MATRIX_ROW_START_CHARPOS (row));
9861 delta_bytes = (Z_BYTE
9862 - BYTEPOS (tlendpos)
9863 - MATRIX_ROW_START_BYTEPOS (row));
9864 }
9865 else
9866 {
9867 /* This line ends in a newline. Must take
9868 account of the newline and the rest of the
9869 text that follows. */
9870 delta = (Z
9871 - CHARPOS (tlendpos)
9872 - MATRIX_ROW_START_CHARPOS (row));
9873 delta_bytes = (Z_BYTE
9874 - BYTEPOS (tlendpos)
9875 - MATRIX_ROW_START_BYTEPOS (row));
9876 }
2311178e 9877
f2d86d7a
GM
9878 increment_matrix_positions (w->current_matrix,
9879 this_line_vpos + 1,
9880 w->current_matrix->nrows,
9881 delta, delta_bytes);
85bcef6c 9882 }
46db8486 9883
5f5c8ee5
GM
9884 /* If this row displays text now but previously didn't,
9885 or vice versa, w->window_end_vpos may have to be
9886 adjusted. */
9887 if ((it.glyph_row - 1)->displays_text_p)
9888 {
9889 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
9890 XSETINT (w->window_end_vpos, this_line_vpos);
9891 }
9892 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
9893 && this_line_vpos > 0)
9894 XSETINT (w->window_end_vpos, this_line_vpos - 1);
9895 w->window_end_valid = Qnil;
2311178e 9896
5f5c8ee5
GM
9897 /* Update hint: No need to try to scroll in update_window. */
9898 w->desired_matrix->no_scrolling_p = 1;
9899
9900#if GLYPH_DEBUG
9901 *w->desired_matrix->method = 0;
9902 debug_method_add (w, "optimization 1");
9903#endif
a2889657
JB
9904 goto update;
9905 }
9906 else
9907 goto cancel;
9908 }
5f5c8ee5
GM
9909 else if (/* Cursor position hasn't changed. */
9910 PT == XFASTINT (w->last_point)
b6f0fe04
RS
9911 /* Make sure the cursor was last displayed
9912 in this window. Otherwise we have to reposition it. */
5f5c8ee5 9913 && 0 <= w->cursor.vpos
da8b7f4f 9914 && WINDOW_TOTAL_LINES (w) > w->cursor.vpos)
a2889657
JB
9915 {
9916 if (!must_finish)
9917 {
c6e89d6c 9918 do_pending_window_change (1);
5f5c8ee5 9919
2311178e 9920 /* We used to always goto end_of_redisplay here, but this
5f5c8ee5
GM
9921 isn't enough if we have a blinking cursor. */
9922 if (w->cursor_off_p == w->last_cursor_off_p)
9923 goto end_of_redisplay;
a2889657
JB
9924 }
9925 goto update;
9926 }
8b51f1e3
KH
9927 /* If highlighting the region, or if the cursor is in the echo area,
9928 then we can't just move the cursor. */
bd66d1ba
RS
9929 else if (! (!NILP (Vtransient_mark_mode)
9930 && !NILP (current_buffer->mark_active))
97a36635 9931 && (EQ (selected_window, current_buffer->last_selected_window)
293a54ce 9932 || highlight_nonselected_windows)
8b51f1e3 9933 && NILP (w->region_showing)
8f897821 9934 && NILP (Vshow_trailing_whitespace)
8b51f1e3 9935 && !cursor_in_echo_area)
a2889657 9936 {
5f5c8ee5
GM
9937 struct it it;
9938 struct glyph_row *row;
9939
9940 /* Skip from tlbufpos to PT and see where it is. Note that
9941 PT may be in invisible text. If so, we will end at the
9942 next visible position. */
9943 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
9944 NULL, DEFAULT_FACE_ID);
9945 it.current_x = this_line_start_x;
9946 it.current_y = this_line_y;
9947 it.vpos = this_line_vpos;
2311178e 9948
5f5c8ee5
GM
9949 /* The call to move_it_to stops in front of PT, but
9950 moves over before-strings. */
9951 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
9952
9953 if (it.vpos == this_line_vpos
9954 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
9955 row->enabled_p))
a2889657 9956 {
5f5c8ee5
GM
9957 xassert (this_line_vpos == it.vpos);
9958 xassert (this_line_y == it.current_y);
9959 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
ade0bee1
GM
9960#if GLYPH_DEBUG
9961 *w->desired_matrix->method = 0;
9962 debug_method_add (w, "optimization 3");
9963#endif
a2889657
JB
9964 goto update;
9965 }
9966 else
9967 goto cancel;
9968 }
5f5c8ee5 9969
a2889657 9970 cancel:
5f5c8ee5
GM
9971 /* Text changed drastically or point moved off of line. */
9972 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
9973 }
9974
5f5c8ee5
GM
9975 CHARPOS (this_line_start_pos) = 0;
9976 consider_all_windows_p |= buffer_shared > 1;
9977 ++clear_face_cache_count;
a2889657 9978
2311178e 9979
bd9d0f3f
GM
9980 /* Build desired matrices, and update the display. If
9981 consider_all_windows_p is non-zero, do it for all windows on all
9982 frames. Otherwise do it for selected_window, only. */
463f6b91 9983
5f5c8ee5 9984 if (consider_all_windows_p)
a2889657 9985 {
35f56f96 9986 Lisp_Object tail, frame;
0528abe1
GM
9987 int i, n = 0, size = 50;
9988 struct frame **updated
9989 = (struct frame **) alloca (size * sizeof *updated);
a2889657 9990
5f5c8ee5
GM
9991 /* Clear the face cache eventually. */
9992 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 9993 {
5f5c8ee5 9994 clear_face_cache (0);
463f6b91
RS
9995 clear_face_cache_count = 0;
9996 }
31b24551 9997
5f5c8ee5
GM
9998 /* Recompute # windows showing selected buffer. This will be
9999 incremented each time such a window is displayed. */
a2889657
JB
10000 buffer_shared = 0;
10001
35f56f96 10002 FOR_EACH_FRAME (tail, frame)
30c566e4 10003 {
5f5c8ee5 10004 struct frame *f = XFRAME (frame);
2311178e 10005
886bd6f2 10006 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 10007 {
ae02e06a 10008#ifdef HAVE_WINDOW_SYSTEM
bb336f8d
RS
10009 if (clear_face_cache_count % 50 == 0
10010 && FRAME_WINDOW_P (f))
10011 clear_image_cache (f, 0);
ae02e06a 10012#endif /* HAVE_WINDOW_SYSTEM */
bb336f8d 10013
5f5c8ee5
GM
10014 /* Mark all the scroll bars to be removed; we'll redeem
10015 the ones we want when we redisplay their windows. */
9769686d 10016 if (condemn_scroll_bars_hook)
504454e8 10017 condemn_scroll_bars_hook (f);
30c566e4 10018
f21ef775 10019 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 10020 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 10021
5f5c8ee5
GM
10022 /* Any scroll bars which redisplay_windows should have
10023 nuked should now go away. */
9769686d 10024 if (judge_scroll_bars_hook)
504454e8 10025 judge_scroll_bars_hook (f);
bd9d0f3f
GM
10026
10027 /* If fonts changed, display again. */
b60c9653
RS
10028 /* ??? rms: I suspect it is a mistake to jump all the way
10029 back to retry here. It should just retry this frame. */
bd9d0f3f
GM
10030 if (fonts_changed_p)
10031 goto retry;
2311178e 10032
bd9d0f3f
GM
10033 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
10034 {
10035 /* See if we have to hscroll. */
10036 if (hscroll_windows (f->root_window))
10037 goto retry;
10038
10039 /* Prevent various kinds of signals during display
10040 update. stdio is not robust about handling
10041 signals, which can cause an apparent I/O
10042 error. */
10043 if (interrupt_input)
10044 unrequest_sigio ();
aac2d8b2 10045 STOP_POLLING;
bd9d0f3f
GM
10046
10047 /* Update the display. */
10048 set_window_update_flags (XWINDOW (f->root_window), 1);
10049 pause |= update_frame (f, 0, 0);
ccbb9ed2 10050#if 0 /* Exiting the loop can leave the wrong value for buffer_shared. */
bd9d0f3f
GM
10051 if (pause)
10052 break;
ccbb9ed2 10053#endif
bd9d0f3f 10054
0528abe1
GM
10055 if (n == size)
10056 {
10057 int nbytes = size * sizeof *updated;
10058 struct frame **p = (struct frame **) alloca (2 * nbytes);
10059 bcopy (updated, p, nbytes);
10060 size *= 2;
10061 }
2311178e 10062
0528abe1 10063 updated[n++] = f;
bd9d0f3f 10064 }
9769686d 10065 }
30c566e4 10066 }
0528abe1 10067
6f68b035
GM
10068 if (!pause)
10069 {
10070 /* Do the mark_window_display_accurate after all windows have
10071 been redisplayed because this call resets flags in buffers
10072 which are needed for proper redisplay. */
10073 for (i = 0; i < n; ++i)
10074 {
10075 struct frame *f = updated[i];
10076 mark_window_display_accurate (f->root_window, 1);
10077 if (frame_up_to_date_hook)
10078 frame_up_to_date_hook (f);
10079 }
0528abe1 10080 }
a2889657 10081 }
bd9d0f3f
GM
10082 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
10083 {
10084 Lisp_Object mini_window;
10085 struct frame *mini_frame;
5f5c8ee5 10086
82a7ab23 10087 displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
7033d6df
RS
10088 /* Use list_of_error, not Qerror, so that
10089 we catch only errors and don't run the debugger. */
10090 internal_condition_case_1 (redisplay_window_1, selected_window,
10091 list_of_error,
82a7ab23 10092 redisplay_window_error);
2311178e 10093
bd9d0f3f 10094 /* Compare desired and current matrices, perform output. */
7d0393cf 10095
26683087 10096 update:
bd9d0f3f
GM
10097 /* If fonts changed, display again. */
10098 if (fonts_changed_p)
92a90e89 10099 goto retry;
a2889657 10100
bd9d0f3f
GM
10101 /* Prevent various kinds of signals during display update.
10102 stdio is not robust about handling signals,
10103 which can cause an apparent I/O error. */
10104 if (interrupt_input)
10105 unrequest_sigio ();
aac2d8b2 10106 STOP_POLLING;
1af9f229 10107
bd9d0f3f 10108 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
5f5c8ee5 10109 {
92a90e89
GM
10110 if (hscroll_windows (selected_window))
10111 goto retry;
2311178e 10112
5f5c8ee5 10113 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 10114 pause = update_frame (sf, 0, 0);
5f5c8ee5 10115 }
d724d989 10116
8de2d90b 10117 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
10118 function. If the echo area is on another frame, that may
10119 have put text on a frame other than the selected one, so the
10120 above call to update_frame would not have caught it. Catch
8de2d90b 10121 it here. */
bd9d0f3f
GM
10122 mini_window = FRAME_MINIBUF_WINDOW (sf);
10123 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
2311178e 10124
bd9d0f3f
GM
10125 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
10126 {
10127 XWINDOW (mini_window)->must_be_updated_p = 1;
10128 pause |= update_frame (mini_frame, 0, 0);
10129 if (!pause && hscroll_windows (mini_window))
10130 goto retry;
10131 }
6e8290aa 10132 }
a2889657 10133
5f5c8ee5
GM
10134 /* If display was paused because of pending input, make sure we do a
10135 thorough update the next time. */
a2889657
JB
10136 if (pause)
10137 {
5f5c8ee5
GM
10138 /* Prevent the optimization at the beginning of
10139 redisplay_internal that tries a single-line update of the
10140 line containing the cursor in the selected window. */
10141 CHARPOS (this_line_start_pos) = 0;
10142
10143 /* Let the overlay arrow be updated the next time. */
265a9e55 10144 if (!NILP (last_arrow_position))
a2889657
JB
10145 {
10146 last_arrow_position = Qt;
10147 last_arrow_string = Qt;
10148 }
2311178e 10149
5f5c8ee5
GM
10150 /* If we pause after scrolling, some rows in the current
10151 matrices of some windows are not valid. */
10152 if (!WINDOW_FULL_WIDTH_P (w)
10153 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
10154 update_mode_lines = 1;
10155 }
43c09969 10156 else
a2889657 10157 {
43c09969 10158 if (!consider_all_windows_p)
a2889657 10159 {
43c09969
GM
10160 /* This has already been done above if
10161 consider_all_windows_p is set. */
10162 mark_window_display_accurate_1 (w, 1);
2311178e 10163
927c5b3b
GM
10164 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
10165 last_arrow_string = Voverlay_arrow_string;
2311178e 10166
efc63ef0 10167 if (frame_up_to_date_hook != 0)
43c09969 10168 frame_up_to_date_hook (sf);
a2889657 10169 }
15e26c76 10170
a2889657
JB
10171 update_mode_lines = 0;
10172 windows_or_buffers_changed = 0;
5fb96e96 10173 cursor_type_changed = 0;
a2889657
JB
10174 }
10175
5f5c8ee5
GM
10176 /* Start SIGIO interrupts coming again. Having them off during the
10177 code above makes it less likely one will discard output, but not
10178 impossible, since there might be stuff in the system buffer here.
a2889657 10179 But it is much hairier to try to do anything about that. */
a2889657
JB
10180 if (interrupt_input)
10181 request_sigio ();
aac2d8b2 10182 RESUME_POLLING;
a2889657 10183
5f5c8ee5
GM
10184 /* If a frame has become visible which was not before, redisplay
10185 again, so that we display it. Expose events for such a frame
10186 (which it gets when becoming visible) don't call the parts of
10187 redisplay constructing glyphs, so simply exposing a frame won't
10188 display anything in this case. So, we have to display these
10189 frames here explicitly. */
11c52c4f
RS
10190 if (!pause)
10191 {
10192 Lisp_Object tail, frame;
10193 int new_count = 0;
10194
10195 FOR_EACH_FRAME (tail, frame)
10196 {
10197 int this_is_visible = 0;
8e83f802
RS
10198
10199 if (XFRAME (frame)->visible)
10200 this_is_visible = 1;
10201 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
10202 if (XFRAME (frame)->visible)
10203 this_is_visible = 1;
11c52c4f
RS
10204
10205 if (this_is_visible)
10206 new_count++;
10207 }
10208
89819bdd 10209 if (new_count != number_of_visible_frames)
11c52c4f
RS
10210 windows_or_buffers_changed++;
10211 }
10212
44fa5b1e 10213 /* Change frame size now if a change is pending. */
c6e89d6c 10214 do_pending_window_change (1);
d8e242fd 10215
8b32d885
RS
10216 /* If we just did a pending size change, or have additional
10217 visible frames, redisplay again. */
3c8c72e0 10218 if (windows_or_buffers_changed && !pause)
8b32d885 10219 goto retry;
5f5c8ee5 10220
1987b083 10221 end_of_redisplay:
28514cd9 10222 unbind_to (count, Qnil);
aac2d8b2 10223 RESUME_POLLING;
a2889657
JB
10224}
10225
5f5c8ee5
GM
10226
10227/* Redisplay, but leave alone any recent echo area message unless
10228 another message has been requested in its place.
a2889657
JB
10229
10230 This is useful in situations where you need to redisplay but no
10231 user action has occurred, making it inappropriate for the message
10232 area to be cleared. See tracking_off and
9bf76936
GM
10233 wait_reading_process_input for examples of these situations.
10234
10235 FROM_WHERE is an integer saying from where this function was
10236 called. This is useful for debugging. */
a2889657 10237
8991bb31 10238void
9bf76936
GM
10239redisplay_preserve_echo_area (from_where)
10240 int from_where;
a2889657 10241{
9bf76936
GM
10242 TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where));
10243
c6e89d6c 10244 if (!NILP (echo_area_buffer[1]))
a2889657 10245 {
c6e89d6c
GM
10246 /* We have a previously displayed message, but no current
10247 message. Redisplay the previous message. */
10248 display_last_displayed_message_p = 1;
e9874cee 10249 redisplay_internal (1);
c6e89d6c 10250 display_last_displayed_message_p = 0;
a2889657
JB
10251 }
10252 else
e9874cee 10253 redisplay_internal (1);
a2889657
JB
10254}
10255
5f5c8ee5 10256
28514cd9 10257/* Function registered with record_unwind_protect in
acfca545
RS
10258 redisplay_internal. Reset redisplaying_p to the value it had
10259 before redisplay_internal was called, and clear
26683087 10260 prevent_freeing_realized_faces_p. */
28514cd9
GM
10261
10262static Lisp_Object
10263unwind_redisplay (old_redisplaying_p)
10264 Lisp_Object old_redisplaying_p;
10265{
10266 redisplaying_p = XFASTINT (old_redisplaying_p);
c6e89d6c 10267 return Qnil;
28514cd9
GM
10268}
10269
10270
43c09969
GM
10271/* Mark the display of window W as accurate or inaccurate. If
10272 ACCURATE_P is non-zero mark display of W as accurate. If
10273 ACCURATE_P is zero, arrange for W to be redisplayed the next time
10274 redisplay_internal is called. */
5f5c8ee5 10275
43c09969
GM
10276static void
10277mark_window_display_accurate_1 (w, accurate_p)
10278 struct window *w;
5f5c8ee5 10279 int accurate_p;
a2889657 10280{
43c09969 10281 if (BUFFERP (w->buffer))
a2889657 10282 {
43c09969 10283 struct buffer *b = XBUFFER (w->buffer);
2311178e 10284
43c09969
GM
10285 w->last_modified
10286 = make_number (accurate_p ? BUF_MODIFF (b) : 0);
10287 w->last_overlay_modified
10288 = make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
10289 w->last_had_star
10290 = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b) ? Qt : Qnil;
a2889657 10291
43c09969 10292 if (accurate_p)
bd66d1ba 10293 {
43c09969
GM
10294 b->clip_changed = 0;
10295 b->prevent_redisplay_optimizations_p = 0;
10296
10297 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
10298 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
10299 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
10300 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
2311178e 10301
43c09969
GM
10302 w->current_matrix->buffer = b;
10303 w->current_matrix->begv = BUF_BEGV (b);
10304 w->current_matrix->zv = BUF_ZV (b);
2311178e 10305
43c09969
GM
10306 w->last_cursor = w->cursor;
10307 w->last_cursor_off_p = w->cursor_off_p;
2311178e 10308
43c09969
GM
10309 if (w == XWINDOW (selected_window))
10310 w->last_point = make_number (BUF_PT (b));
10311 else
10312 w->last_point = make_number (XMARKER (w->pointm)->charpos);
bd66d1ba 10313 }
43c09969 10314 }
bd66d1ba 10315
43c09969
GM
10316 if (accurate_p)
10317 {
d2f84654 10318 w->window_end_valid = w->buffer;
99332eb6 10319#if 0 /* This is incorrect with variable-height lines. */
2913a9c0 10320 xassert (XINT (w->window_end_vpos)
da8b7f4f 10321 < (WINDOW_TOTAL_LINES (w)
2913a9c0 10322 - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
99332eb6 10323#endif
a2889657 10324 w->update_mode_line = Qnil;
43c09969
GM
10325 }
10326}
10327
10328
10329/* Mark the display of windows in the window tree rooted at WINDOW as
10330 accurate or inaccurate. If ACCURATE_P is non-zero mark display of
10331 windows as accurate. If ACCURATE_P is zero, arrange for windows to
10332 be redisplayed the next time redisplay_internal is called. */
10333
10334void
10335mark_window_display_accurate (window, accurate_p)
10336 Lisp_Object window;
10337 int accurate_p;
10338{
10339 struct window *w;
2311178e 10340
43c09969
GM
10341 for (; !NILP (window); window = w->next)
10342 {
10343 w = XWINDOW (window);
10344 mark_window_display_accurate_1 (w, accurate_p);
a2889657 10345
265a9e55 10346 if (!NILP (w->vchild))
5f5c8ee5 10347 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 10348 if (!NILP (w->hchild))
5f5c8ee5 10349 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
10350 }
10351
5f5c8ee5 10352 if (accurate_p)
a2889657 10353 {
d45de95b 10354 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
10355 last_arrow_string = Voverlay_arrow_string;
10356 }
10357 else
10358 {
5f5c8ee5
GM
10359 /* Force a thorough redisplay the next time by setting
10360 last_arrow_position and last_arrow_string to t, which is
4b41cebb 10361 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
10362 last_arrow_position = Qt;
10363 last_arrow_string = Qt;
10364 }
10365}
5f5c8ee5
GM
10366
10367
10368/* Return value in display table DP (Lisp_Char_Table *) for character
10369 C. Since a display table doesn't have any parent, we don't have to
10370 follow parent. Do not call this function directly but use the
10371 macro DISP_CHAR_VECTOR. */
10372
10373Lisp_Object
10374disp_char_vector (dp, c)
10375 struct Lisp_Char_Table *dp;
10376 int c;
10377{
10378 int code[4], i;
10379 Lisp_Object val;
10380
10381 if (SINGLE_BYTE_CHAR_P (c))
10382 return (dp->contents[c]);
2311178e 10383
c5924f47 10384 SPLIT_CHAR (c, code[0], code[1], code[2]);
260a86a0
KH
10385 if (code[1] < 32)
10386 code[1] = -1;
10387 else if (code[2] < 32)
10388 code[2] = -1;
2311178e 10389
5f5c8ee5
GM
10390 /* Here, the possible range of code[0] (== charset ID) is
10391 128..max_charset. Since the top level char table contains data
10392 for multibyte characters after 256th element, we must increment
10393 code[0] by 128 to get a correct index. */
10394 code[0] += 128;
10395 code[3] = -1; /* anchor */
10396
10397 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
10398 {
10399 val = dp->contents[code[i]];
10400 if (!SUB_CHAR_TABLE_P (val))
10401 return (NILP (val) ? dp->defalt : val);
10402 }
2311178e 10403
5f5c8ee5
GM
10404 /* Here, val is a sub char table. We return the default value of
10405 it. */
10406 return (dp->defalt);
10407}
10408
10409
a2889657 10410\f
5f5c8ee5
GM
10411/***********************************************************************
10412 Window Redisplay
10413 ***********************************************************************/
a2725ab2 10414
5f5c8ee5 10415/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
10416
10417static void
5f5c8ee5
GM
10418redisplay_windows (window)
10419 Lisp_Object window;
90adcf20 10420{
5f5c8ee5
GM
10421 while (!NILP (window))
10422 {
10423 struct window *w = XWINDOW (window);
2311178e 10424
5f5c8ee5
GM
10425 if (!NILP (w->hchild))
10426 redisplay_windows (w->hchild);
10427 else if (!NILP (w->vchild))
10428 redisplay_windows (w->vchild);
10429 else
82a7ab23
RS
10430 {
10431 displayed_buffer = XBUFFER (w->buffer);
7033d6df
RS
10432 /* Use list_of_error, not Qerror, so that
10433 we catch only errors and don't run the debugger. */
2311178e 10434 internal_condition_case_1 (redisplay_window_0, window,
7033d6df 10435 list_of_error,
82a7ab23
RS
10436 redisplay_window_error);
10437 }
a2725ab2 10438
5f5c8ee5
GM
10439 window = w->next;
10440 }
10441}
10442
82a7ab23
RS
10443static Lisp_Object
10444redisplay_window_error ()
10445{
10446 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
10447 return Qnil;
10448}
10449
10450static Lisp_Object
10451redisplay_window_0 (window)
10452 Lisp_Object window;
10453{
10454 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
10455 redisplay_window (window, 0);
10456 return Qnil;
10457}
5f5c8ee5 10458
82a7ab23
RS
10459static Lisp_Object
10460redisplay_window_1 (window)
10461 Lisp_Object window;
10462{
10463 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
10464 redisplay_window (window, 1);
10465 return Qnil;
10466}
10467\f
bc6371a6
KH
10468
10469/* Increment GLYPH until it reaches END or CONDITION fails while
10470 adding (GLYPH)->pixel_width to X. */
10471
10472#define SKIP_GLYPHS(glyph, end, x, condition) \
10473 do \
10474 { \
10475 (x) += (glyph)->pixel_width; \
10476 ++(glyph); \
10477 } \
10478 while ((glyph) < (end) && (condition))
10479
10480
5f5c8ee5
GM
10481/* Set cursor position of W. PT is assumed to be displayed in ROW.
10482 DELTA is the number of bytes by which positions recorded in ROW
10483 differ from current buffer positions. */
10484
10485void
10486set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
10487 struct window *w;
10488 struct glyph_row *row;
10489 struct glyph_matrix *matrix;
10490 int delta, delta_bytes, dy, dvpos;
10491{
10492 struct glyph *glyph = row->glyphs[TEXT_AREA];
10493 struct glyph *end = glyph + row->used[TEXT_AREA];
ae73dc1c
KH
10494 /* The first glyph that starts a sequence of glyphs from string. */
10495 struct glyph *string_start;
10496 /* The X coordinate of string_start. */
10497 int string_start_x;
10498 /* The last known character position. */
10499 int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
10500 /* The last known character position before string_start. */
10501 int string_before_pos;
5f5c8ee5
GM
10502 int x = row->x;
10503 int pt_old = PT - delta;
10504
10505 /* Skip over glyphs not having an object at the start of the row.
10506 These are special glyphs like truncation marks on terminal
10507 frames. */
10508 if (row->displays_text_p)
10509 while (glyph < end
6fc556fd 10510 && INTEGERP (glyph->object)
5f5c8ee5
GM
10511 && glyph->charpos < 0)
10512 {
10513 x += glyph->pixel_width;
10514 ++glyph;
10515 }
10516
ae73dc1c 10517 string_start = NULL;
5f5c8ee5 10518 while (glyph < end
6fc556fd 10519 && !INTEGERP (glyph->object)
5f5c8ee5 10520 && (!BUFFERP (glyph->object)
ae73dc1c 10521 || (last_pos = glyph->charpos) < pt_old))
5f5c8ee5 10522 {
ae73dc1c
KH
10523 if (! STRINGP (glyph->object))
10524 {
10525 string_start = NULL;
10526 x += glyph->pixel_width;
10527 ++glyph;
10528 }
10529 else
10530 {
10531 string_before_pos = last_pos;
10532 string_start = glyph;
10533 string_start_x = x;
10534 /* Skip all glyphs from string. */
bc6371a6 10535 SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
ae73dc1c
KH
10536 }
10537 }
10538
10539 if (string_start
10540 && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
10541 {
10542 /* We may have skipped over point because the previous glyphs
10543 are from string. As there's no easy way to know the
10544 character position of the current glyph, find the correct
10545 glyph on point by scanning from string_start again. */
bc6371a6
KH
10546 Lisp_Object limit;
10547 Lisp_Object string;
10548 int pos;
ae73dc1c 10549
bc6371a6
KH
10550 limit = make_number (pt_old + 1);
10551 end = glyph;
ae73dc1c
KH
10552 glyph = string_start;
10553 x = string_start_x;
bc6371a6
KH
10554 string = glyph->object;
10555 pos = string_buffer_position (w, string, string_before_pos);
10556 /* If STRING is from overlay, LAST_POS == 0. We skip such glyphs
10557 because we always put cursor after overlay strings. */
10558 while (pos == 0 && glyph < end)
ae73dc1c 10559 {
bc6371a6
KH
10560 string = glyph->object;
10561 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
10562 if (glyph < end)
10563 pos = string_buffer_position (w, glyph->object, string_before_pos);
10564 }
10565
10566 while (glyph < end)
10567 {
10568 pos = XINT (Fnext_single_char_property_change
10569 (make_number (pos), Qdisplay, Qnil, limit));
10570 if (pos > pt_old)
10571 break;
ae73dc1c 10572 /* Skip glyphs from the same string. */
bc6371a6
KH
10573 string = glyph->object;
10574 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
10575 /* Skip glyphs from an overlay. */
10576 while (glyph < end
10577 && ! string_buffer_position (w, glyph->object, pos))
ae73dc1c 10578 {
bc6371a6
KH
10579 string = glyph->object;
10580 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
ae73dc1c 10581 }
ae73dc1c 10582 }
5f5c8ee5
GM
10583 }
10584
10585 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
10586 w->cursor.x = x;
10587 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
10588 w->cursor.y = row->y + dy;
10589
10590 if (w == XWINDOW (selected_window))
10591 {
10592 if (!row->continued_p
10593 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
10594 && row->x == 0)
10595 {
10596 this_line_buffer = XBUFFER (w->buffer);
2311178e 10597
5f5c8ee5
GM
10598 CHARPOS (this_line_start_pos)
10599 = MATRIX_ROW_START_CHARPOS (row) + delta;
10600 BYTEPOS (this_line_start_pos)
10601 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
2311178e 10602
5f5c8ee5
GM
10603 CHARPOS (this_line_end_pos)
10604 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
10605 BYTEPOS (this_line_end_pos)
10606 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
2311178e 10607
5f5c8ee5
GM
10608 this_line_y = w->cursor.y;
10609 this_line_pixel_height = row->height;
10610 this_line_vpos = w->cursor.vpos;
10611 this_line_start_x = row->x;
10612 }
10613 else
10614 CHARPOS (this_line_start_pos) = 0;
10615 }
10616}
10617
10618
10619/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
10620 start STARTP. Sets the window start of WINDOW to that position.
10621
10622 We assume that the window's buffer is really current. */
5f5c8ee5
GM
10623
10624static INLINE struct text_pos
10625run_window_scroll_functions (window, startp)
10626 Lisp_Object window;
10627 struct text_pos startp;
10628{
10629 struct window *w = XWINDOW (window);
10630 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
10631
10632 if (current_buffer != XBUFFER (w->buffer))
10633 abort ();
10634
5f5c8ee5
GM
10635 if (!NILP (Vwindow_scroll_functions))
10636 {
2311178e 10637 run_hook_with_args_2 (Qwindow_scroll_functions, window,
5f5c8ee5
GM
10638 make_number (CHARPOS (startp)));
10639 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
10640 /* In case the hook functions switch buffers. */
10641 if (current_buffer != XBUFFER (w->buffer))
10642 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 10643 }
90adcf20 10644
5f5c8ee5
GM
10645 return startp;
10646}
10647
10648
ddf6b9a3
RS
10649/* Make sure the line containing the cursor is fully visible.
10650 A value of 1 means there is nothing to be done.
10651 (Either the line is fully visible, or it cannot be made so,
10652 or we cannot tell.)
10653 A value of 0 means the caller should do scrolling
10654 as if point had gone off the screen. */
5f5c8ee5 10655
cb617e7c 10656static int
5f5c8ee5
GM
10657make_cursor_line_fully_visible (w)
10658 struct window *w;
10659{
10660 struct glyph_matrix *matrix;
10661 struct glyph_row *row;
478d746b 10662 int window_height;
2311178e 10663
5f5c8ee5
GM
10664 /* It's not always possible to find the cursor, e.g, when a window
10665 is full of overlay strings. Don't do anything in that case. */
10666 if (w->cursor.vpos < 0)
cb617e7c 10667 return 1;
2311178e 10668
5f5c8ee5
GM
10669 matrix = w->desired_matrix;
10670 row = MATRIX_ROW (matrix, w->cursor.vpos);
10671
acda20e1 10672 /* If the cursor row is not partially visible, there's nothing to do. */
b28cb6ed 10673 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
cb617e7c 10674 return 1;
b28cb6ed
GM
10675
10676 /* If the row the cursor is in is taller than the window's height,
10677 it's not clear what to do, so do nothing. */
10678 window_height = window_box_height (w);
10679 if (row->height >= window_height)
cb617e7c 10680 return 1;
b28cb6ed 10681
ddf6b9a3
RS
10682 return 0;
10683
10684#if 0
10685 /* This code used to try to scroll the window just enough to make
10686 the line visible. It returned 0 to say that the caller should
10687 allocate larger glyph matrices. */
10688
b28cb6ed 10689 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
5f5c8ee5
GM
10690 {
10691 int dy = row->height - row->visible_height;
10692 w->vscroll = 0;
10693 w->cursor.y += dy;
10694 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
10695 }
b28cb6ed 10696 else /* MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) */
5f5c8ee5
GM
10697 {
10698 int dy = - (row->height - row->visible_height);
10699 w->vscroll = dy;
10700 w->cursor.y += dy;
10701 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
10702 }
2311178e 10703
5f5c8ee5
GM
10704 /* When we change the cursor y-position of the selected window,
10705 change this_line_y as well so that the display optimization for
10706 the cursor line of the selected window in redisplay_internal uses
10707 the correct y-position. */
10708 if (w == XWINDOW (selected_window))
10709 this_line_y = w->cursor.y;
cb617e7c
GM
10710
10711 /* If vscrolling requires a larger glyph matrix, arrange for a fresh
10712 redisplay with larger matrices. */
10713 if (matrix->nrows < required_matrix_height (w))
10714 {
10715 fonts_changed_p = 1;
10716 return 0;
10717 }
10718
10719 return 1;
ddf6b9a3 10720#endif /* 0 */
5f5c8ee5
GM
10721}
10722
10723
10724/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
10725 non-zero means only WINDOW is redisplayed in redisplay_internal.
10726 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
10727 in redisplay_window to bring a partially visible line into view in
10728 the case that only the cursor has moved.
10729
03b0a4b4
RS
10730 LAST_LINE_MISFIT should be nonzero if we're scrolling because the
10731 last screen line's vertical height extends past the end of the screen.
10732
5f5c8ee5
GM
10733 Value is
10734
10735 1 if scrolling succeeded
2311178e 10736
5f5c8ee5 10737 0 if scrolling didn't find point.
2311178e 10738
5f5c8ee5
GM
10739 -1 if new fonts have been loaded so that we must interrupt
10740 redisplay, adjust glyph matrices, and try again. */
10741
cb617e7c
GM
10742enum
10743{
10744 SCROLLING_SUCCESS,
10745 SCROLLING_FAILED,
10746 SCROLLING_NEED_LARGER_MATRICES
10747};
10748
5f5c8ee5
GM
10749static int
10750try_scrolling (window, just_this_one_p, scroll_conservatively,
03b0a4b4 10751 scroll_step, temp_scroll_step, last_line_misfit)
5f5c8ee5
GM
10752 Lisp_Object window;
10753 int just_this_one_p;
31ade731 10754 EMACS_INT scroll_conservatively, scroll_step;
5f5c8ee5 10755 int temp_scroll_step;
03b0a4b4 10756 int last_line_misfit;
5f5c8ee5
GM
10757{
10758 struct window *w = XWINDOW (window);
10759 struct frame *f = XFRAME (w->frame);
10760 struct text_pos scroll_margin_pos;
10761 struct text_pos pos;
10762 struct text_pos startp;
10763 struct it it;
10764 Lisp_Object window_end;
10765 int this_scroll_margin;
10766 int dy = 0;
10767 int scroll_max;
b8a63ccb 10768 int rc;
5f5c8ee5
GM
10769 int amount_to_scroll = 0;
10770 Lisp_Object aggressive;
10771 int height;
03b0a4b4 10772 int end_scroll_margin;
5f5c8ee5
GM
10773
10774#if GLYPH_DEBUG
10775 debug_method_add (w, "try_scrolling");
78614721 10776#endif
5f5c8ee5
GM
10777
10778 SET_TEXT_POS_FROM_MARKER (startp, w->start);
2311178e 10779
5f5c8ee5
GM
10780 /* Compute scroll margin height in pixels. We scroll when point is
10781 within this distance from the top or bottom of the window. */
10782 if (scroll_margin > 0)
90adcf20 10783 {
da8b7f4f
KS
10784 this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
10785 this_scroll_margin *= FRAME_LINE_HEIGHT (f);
5f5c8ee5
GM
10786 }
10787 else
10788 this_scroll_margin = 0;
10789
10790 /* Compute how much we should try to scroll maximally to bring point
10791 into view. */
0894e696
SM
10792 if (scroll_step || scroll_conservatively || temp_scroll_step)
10793 scroll_max = max (scroll_step,
10794 max (scroll_conservatively, temp_scroll_step));
5f5c8ee5
GM
10795 else if (NUMBERP (current_buffer->scroll_down_aggressively)
10796 || NUMBERP (current_buffer->scroll_up_aggressively))
10797 /* We're trying to scroll because of aggressive scrolling
10798 but no scroll_step is set. Choose an arbitrary one. Maybe
10799 there should be a variable for this. */
10800 scroll_max = 10;
10801 else
10802 scroll_max = 0;
da8b7f4f 10803 scroll_max *= FRAME_LINE_HEIGHT (f);
5f5c8ee5
GM
10804
10805 /* Decide whether we have to scroll down. Start at the window end
10806 and move this_scroll_margin up to find the position of the scroll
10807 margin. */
10808 window_end = Fwindow_end (window, Qt);
03b0a4b4
RS
10809
10810 too_near_end:
10811
5f5c8ee5
GM
10812 CHARPOS (scroll_margin_pos) = XINT (window_end);
10813 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
03b0a4b4
RS
10814
10815 end_scroll_margin = this_scroll_margin + !!last_line_misfit;
10816 if (end_scroll_margin)
5f5c8ee5
GM
10817 {
10818 start_display (&it, w, scroll_margin_pos);
03b0a4b4 10819 move_it_vertically (&it, - end_scroll_margin);
5f5c8ee5
GM
10820 scroll_margin_pos = it.current.pos;
10821 }
10822
10823 if (PT >= CHARPOS (scroll_margin_pos))
10824 {
10825 int y0;
2311178e 10826
5f5c8ee5
GM
10827 /* Point is in the scroll margin at the bottom of the window, or
10828 below. Compute a new window start that makes point visible. */
47589c8c 10829
5f5c8ee5
GM
10830 /* Compute the distance from the scroll margin to PT.
10831 Give up if the distance is greater than scroll_max. */
10832 start_display (&it, w, scroll_margin_pos);
10833 y0 = it.current_y;
10834 move_it_to (&it, PT, 0, it.last_visible_y, -1,
10835 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
539e92ad
GM
10836
10837 /* To make point visible, we have to move the window start
10838 down so that the line the cursor is in is visible, which
10839 means we have to add in the height of the cursor line. */
10840 dy = line_bottom_y (&it) - y0;
2311178e 10841
5f5c8ee5 10842 if (dy > scroll_max)
cb617e7c 10843 return SCROLLING_FAILED;
2311178e 10844
5f5c8ee5
GM
10845 /* Move the window start down. If scrolling conservatively,
10846 move it just enough down to make point visible. If
10847 scroll_step is set, move it down by scroll_step. */
10848 start_display (&it, w, startp);
10849
10850 if (scroll_conservatively)
03b0a4b4
RS
10851 /* Set AMOUNT_TO_SCROLL to at least one line,
10852 and at most scroll_conservatively lines. */
e89aaabd 10853 amount_to_scroll
da8b7f4f
KS
10854 = min (max (dy, FRAME_LINE_HEIGHT (f)),
10855 FRAME_LINE_HEIGHT (f) * scroll_conservatively);
5f5c8ee5
GM
10856 else if (scroll_step || temp_scroll_step)
10857 amount_to_scroll = scroll_max;
10858 else
90adcf20 10859 {
46226c1d 10860 aggressive = current_buffer->scroll_up_aggressively;
da8b7f4f 10861 height = WINDOW_BOX_TEXT_HEIGHT (w);
5f5c8ee5
GM
10862 if (NUMBERP (aggressive))
10863 amount_to_scroll = XFLOATINT (aggressive) * height;
10864 }
a2725ab2 10865
5f5c8ee5 10866 if (amount_to_scroll <= 0)
cb617e7c 10867 return SCROLLING_FAILED;
a2725ab2 10868
03b0a4b4
RS
10869 /* If moving by amount_to_scroll leaves STARTP unchanged,
10870 move it down one screen line. */
10871
5f5c8ee5 10872 move_it_vertically (&it, amount_to_scroll);
03b0a4b4
RS
10873 if (CHARPOS (it.current.pos) == CHARPOS (startp))
10874 move_it_by_lines (&it, 1, 1);
5f5c8ee5
GM
10875 startp = it.current.pos;
10876 }
10877 else
10878 {
10879 /* See if point is inside the scroll margin at the top of the
10880 window. */
10881 scroll_margin_pos = startp;
10882 if (this_scroll_margin)
10883 {
10884 start_display (&it, w, startp);
10885 move_it_vertically (&it, this_scroll_margin);
10886 scroll_margin_pos = it.current.pos;
10887 }
10888
10889 if (PT < CHARPOS (scroll_margin_pos))
10890 {
10891 /* Point is in the scroll margin at the top of the window or
10892 above what is displayed in the window. */
10893 int y0;
2311178e 10894
5f5c8ee5
GM
10895 /* Compute the vertical distance from PT to the scroll
10896 margin position. Give up if distance is greater than
10897 scroll_max. */
10898 SET_TEXT_POS (pos, PT, PT_BYTE);
10899 start_display (&it, w, pos);
10900 y0 = it.current_y;
10901 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
10902 it.last_visible_y, -1,
10903 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
10904 dy = it.current_y - y0;
10905 if (dy > scroll_max)
cb617e7c 10906 return SCROLLING_FAILED;
2311178e 10907
5f5c8ee5
GM
10908 /* Compute new window start. */
10909 start_display (&it, w, startp);
2311178e 10910
5f5c8ee5 10911 if (scroll_conservatively)
0894e696 10912 amount_to_scroll =
da8b7f4f 10913 max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
5f5c8ee5
GM
10914 else if (scroll_step || temp_scroll_step)
10915 amount_to_scroll = scroll_max;
538f13d4 10916 else
5f5c8ee5 10917 {
46226c1d 10918 aggressive = current_buffer->scroll_down_aggressively;
da8b7f4f 10919 height = WINDOW_BOX_TEXT_HEIGHT (w);
5f5c8ee5
GM
10920 if (NUMBERP (aggressive))
10921 amount_to_scroll = XFLOATINT (aggressive) * height;
10922 }
a2725ab2 10923
5f5c8ee5 10924 if (amount_to_scroll <= 0)
cb617e7c 10925 return SCROLLING_FAILED;
2311178e 10926
5f5c8ee5
GM
10927 move_it_vertically (&it, - amount_to_scroll);
10928 startp = it.current.pos;
90adcf20
RS
10929 }
10930 }
a2889657 10931
5f5c8ee5
GM
10932 /* Run window scroll functions. */
10933 startp = run_window_scroll_functions (window, startp);
90adcf20 10934
5f5c8ee5
GM
10935 /* Display the window. Give up if new fonts are loaded, or if point
10936 doesn't appear. */
10937 if (!try_window (window, startp))
cb617e7c 10938 rc = SCROLLING_NEED_LARGER_MATRICES;
5f5c8ee5
GM
10939 else if (w->cursor.vpos < 0)
10940 {
10941 clear_glyph_matrix (w->desired_matrix);
cb617e7c 10942 rc = SCROLLING_FAILED;
5f5c8ee5
GM
10943 }
10944 else
10945 {
10946 /* Maybe forget recorded base line for line number display. */
2311178e 10947 if (!just_this_one_p
5f5c8ee5 10948 || current_buffer->clip_changed
9142dd5b 10949 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5 10950 w->base_line_number = Qnil;
2311178e 10951
ddf6b9a3
RS
10952 /* If cursor ends up on a partially visible line,
10953 treat that as being off the bottom of the screen. */
10954 if (! make_cursor_line_fully_visible (w))
ef3c2c73
RS
10955 {
10956 clear_glyph_matrix (w->desired_matrix);
03b0a4b4 10957 last_line_misfit = 1;
ef3c2c73
RS
10958 goto too_near_end;
10959 }
ddf6b9a3 10960 rc = SCROLLING_SUCCESS;
5f5c8ee5
GM
10961 }
10962
10963 return rc;
a2889657
JB
10964}
10965
5f5c8ee5
GM
10966
10967/* Compute a suitable window start for window W if display of W starts
10968 on a continuation line. Value is non-zero if a new window start
10969 was computed.
10970
10971 The new window start will be computed, based on W's width, starting
10972 from the start of the continued line. It is the start of the
10973 screen line with the minimum distance from the old start W->start. */
10974
10975static int
10976compute_window_start_on_continuation_line (w)
10977 struct window *w;
1f1ff51d 10978{
5f5c8ee5
GM
10979 struct text_pos pos, start_pos;
10980 int window_start_changed_p = 0;
1f1ff51d 10981
5f5c8ee5 10982 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 10983
5f5c8ee5 10984 /* If window start is on a continuation line... Window start may be
2311178e 10985 < BEGV in case there's invisible text at the start of the
5f5c8ee5
GM
10986 buffer (M-x rmail, for example). */
10987 if (CHARPOS (start_pos) > BEGV
10988 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 10989 {
5f5c8ee5
GM
10990 struct it it;
10991 struct glyph_row *row;
f3751a65
GM
10992
10993 /* Handle the case that the window start is out of range. */
10994 if (CHARPOS (start_pos) < BEGV)
10995 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
10996 else if (CHARPOS (start_pos) > ZV)
10997 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
2311178e 10998
5f5c8ee5
GM
10999 /* Find the start of the continued line. This should be fast
11000 because scan_buffer is fast (newline cache). */
045dee35 11001 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
11002 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
11003 row, DEFAULT_FACE_ID);
11004 reseat_at_previous_visible_line_start (&it);
11005
11006 /* If the line start is "too far" away from the window start,
11007 say it takes too much time to compute a new window start. */
11008 if (CHARPOS (start_pos) - IT_CHARPOS (it)
da8b7f4f 11009 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
5f5c8ee5
GM
11010 {
11011 int min_distance, distance;
2311178e 11012
5f5c8ee5
GM
11013 /* Move forward by display lines to find the new window
11014 start. If window width was enlarged, the new start can
11015 be expected to be > the old start. If window width was
11016 decreased, the new window start will be < the old start.
11017 So, we're looking for the display line start with the
11018 minimum distance from the old window start. */
11019 pos = it.current.pos;
11020 min_distance = INFINITY;
11021 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
11022 distance < min_distance)
11023 {
11024 min_distance = distance;
11025 pos = it.current.pos;
11026 move_it_by_lines (&it, 1, 0);
11027 }
2311178e 11028
5f5c8ee5
GM
11029 /* Set the window start there. */
11030 SET_MARKER_FROM_TEXT_POS (w->start, pos);
11031 window_start_changed_p = 1;
11032 }
1f1ff51d 11033 }
2311178e 11034
5f5c8ee5 11035 return window_start_changed_p;
1f1ff51d
KH
11036}
11037
5f5c8ee5 11038
1dd5768b 11039/* Try cursor movement in case text has not changed in window WINDOW,
47589c8c
GM
11040 with window start STARTP. Value is
11041
cb617e7c 11042 CURSOR_MOVEMENT_SUCCESS if successful
2311178e 11043
cb617e7c
GM
11044 CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used
11045
11046 CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the
11047 display. *SCROLL_STEP is set to 1, under certain circumstances, if
11048 we want to scroll as if scroll-step were set to 1. See the code.
11049
11050 CURSOR_MOVEMENT_NEED_LARGER_MATRICES if we need larger matrices, in
11051 which case we have to abort this redisplay, and adjust matrices
11052 first. */
11053
2311178e 11054enum
cb617e7c
GM
11055{
11056 CURSOR_MOVEMENT_SUCCESS,
11057 CURSOR_MOVEMENT_CANNOT_BE_USED,
11058 CURSOR_MOVEMENT_MUST_SCROLL,
11059 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
11060};
47589c8c
GM
11061
11062static int
11063try_cursor_movement (window, startp, scroll_step)
11064 Lisp_Object window;
11065 struct text_pos startp;
11066 int *scroll_step;
11067{
11068 struct window *w = XWINDOW (window);
11069 struct frame *f = XFRAME (w->frame);
cb617e7c 11070 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
2311178e 11071
69d1f7c9 11072#if GLYPH_DEBUG
76cb5e06
GM
11073 if (inhibit_try_cursor_movement)
11074 return rc;
11075#endif
11076
47589c8c
GM
11077 /* Handle case where text has not changed, only point, and it has
11078 not moved off the frame. */
11079 if (/* Point may be in this window. */
11080 PT >= CHARPOS (startp)
47589c8c
GM
11081 /* Selective display hasn't changed. */
11082 && !current_buffer->clip_changed
4db87380
GM
11083 /* Function force-mode-line-update is used to force a thorough
11084 redisplay. It sets either windows_or_buffers_changed or
11085 update_mode_lines. So don't take a shortcut here for these
11086 cases. */
11087 && !update_mode_lines
11088 && !windows_or_buffers_changed
5fb96e96 11089 && !cursor_type_changed
2311178e 11090 /* Can't use this case if highlighting a region. When a
47589c8c
GM
11091 region exists, cursor movement has to do more than just
11092 set the cursor. */
11093 && !(!NILP (Vtransient_mark_mode)
11094 && !NILP (current_buffer->mark_active))
11095 && NILP (w->region_showing)
11096 && NILP (Vshow_trailing_whitespace)
11097 /* Right after splitting windows, last_point may be nil. */
11098 && INTEGERP (w->last_point)
11099 /* This code is not used for mini-buffer for the sake of the case
11100 of redisplaying to replace an echo area message; since in
11101 that case the mini-buffer contents per se are usually
11102 unchanged. This code is of no real use in the mini-buffer
11103 since the handling of this_line_start_pos, etc., in redisplay
11104 handles the same cases. */
11105 && !EQ (window, minibuf_window)
11106 /* When splitting windows or for new windows, it happens that
11107 redisplay is called with a nil window_end_vpos or one being
11108 larger than the window. This should really be fixed in
11109 window.c. I don't have this on my list, now, so we do
11110 approximately the same as the old redisplay code. --gerd. */
11111 && INTEGERP (w->window_end_vpos)
11112 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
11113 && (FRAME_WINDOW_P (f)
11114 || !MARKERP (Voverlay_arrow_position)
11115 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
11116 {
11117 int this_scroll_margin;
8ee5b6a3 11118 struct glyph_row *row = NULL;
47589c8c
GM
11119
11120#if GLYPH_DEBUG
11121 debug_method_add (w, "cursor movement");
11122#endif
11123
11124 /* Scroll if point within this distance from the top or bottom
11125 of the window. This is a pixel value. */
11126 this_scroll_margin = max (0, scroll_margin);
da8b7f4f
KS
11127 this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
11128 this_scroll_margin *= FRAME_LINE_HEIGHT (f);
47589c8c
GM
11129
11130 /* Start with the row the cursor was displayed during the last
11131 not paused redisplay. Give up if that row is not valid. */
bd9d0f3f
GM
11132 if (w->last_cursor.vpos < 0
11133 || w->last_cursor.vpos >= w->current_matrix->nrows)
cb617e7c 11134 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11135 else
11136 {
11137 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
11138 if (row->mode_line_p)
11139 ++row;
11140 if (!row->enabled_p)
cb617e7c 11141 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11142 }
11143
cb617e7c 11144 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
47589c8c
GM
11145 {
11146 int scroll_p = 0;
68c5d1db 11147 int last_y = window_text_bottom_y (w) - this_scroll_margin;
2311178e 11148
47589c8c
GM
11149 if (PT > XFASTINT (w->last_point))
11150 {
11151 /* Point has moved forward. */
47589c8c
GM
11152 while (MATRIX_ROW_END_CHARPOS (row) < PT
11153 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
11154 {
11155 xassert (row->enabled_p);
11156 ++row;
11157 }
11158
11159 /* The end position of a row equals the start position
11160 of the next row. If PT is there, we would rather
cafafe0b
GM
11161 display it in the next line. */
11162 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
11163 && MATRIX_ROW_END_CHARPOS (row) == PT
11164 && !cursor_row_p (w, row))
11165 ++row;
47589c8c
GM
11166
11167 /* If within the scroll margin, scroll. Note that
11168 MATRIX_ROW_BOTTOM_Y gives the pixel position at which
11169 the next line would be drawn, and that
11170 this_scroll_margin can be zero. */
11171 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
11172 || PT > MATRIX_ROW_END_CHARPOS (row)
11173 /* Line is completely visible last line in window
11174 and PT is to be set in the next line. */
11175 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
11176 && PT == MATRIX_ROW_END_CHARPOS (row)
11177 && !row->ends_at_zv_p
11178 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
11179 scroll_p = 1;
11180 }
11181 else if (PT < XFASTINT (w->last_point))
11182 {
11183 /* Cursor has to be moved backward. Note that PT >=
11184 CHARPOS (startp) because of the outer
11185 if-statement. */
11186 while (!row->mode_line_p
11187 && (MATRIX_ROW_START_CHARPOS (row) > PT
11188 || (MATRIX_ROW_START_CHARPOS (row) == PT
11189 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
11190 && (row->y > this_scroll_margin
11191 || CHARPOS (startp) == BEGV))
11192 {
11193 xassert (row->enabled_p);
11194 --row;
11195 }
11196
11197 /* Consider the following case: Window starts at BEGV,
11198 there is invisible, intangible text at BEGV, so that
11199 display starts at some point START > BEGV. It can
11200 happen that we are called with PT somewhere between
11201 BEGV and START. Try to handle that case. */
11202 if (row < w->current_matrix->rows
11203 || row->mode_line_p)
11204 {
11205 row = w->current_matrix->rows;
11206 if (row->mode_line_p)
11207 ++row;
11208 }
11209
11210 /* Due to newlines in overlay strings, we may have to
11211 skip forward over overlay strings. */
68c5d1db
GM
11212 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
11213 && MATRIX_ROW_END_CHARPOS (row) == PT
11214 && !cursor_row_p (w, row))
47589c8c 11215 ++row;
2311178e 11216
47589c8c
GM
11217 /* If within the scroll margin, scroll. */
11218 if (row->y < this_scroll_margin
11219 && CHARPOS (startp) != BEGV)
11220 scroll_p = 1;
11221 }
11222
11223 if (PT < MATRIX_ROW_START_CHARPOS (row)
11224 || PT > MATRIX_ROW_END_CHARPOS (row))
11225 {
11226 /* if PT is not in the glyph row, give up. */
cb617e7c 11227 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c 11228 }
440fc135 11229 else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
47589c8c 11230 {
8de4aaf8
GM
11231 if (PT == MATRIX_ROW_END_CHARPOS (row)
11232 && !row->ends_at_zv_p
11233 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
cb617e7c 11234 rc = CURSOR_MOVEMENT_MUST_SCROLL;
3f7e3031 11235 else if (row->height > window_box_height (w))
440fc135 11236 {
8de4aaf8
GM
11237 /* If we end up in a partially visible line, let's
11238 make it fully visible, except when it's taller
11239 than the window, in which case we can't do much
11240 about it. */
440fc135 11241 *scroll_step = 1;
cb617e7c 11242 rc = CURSOR_MOVEMENT_MUST_SCROLL;
440fc135
GM
11243 }
11244 else
11245 {
11246 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
cb617e7c 11247 if (!make_cursor_line_fully_visible (w))
ddf6b9a3 11248 rc = CURSOR_MOVEMENT_MUST_SCROLL;
cb617e7c
GM
11249 else
11250 rc = CURSOR_MOVEMENT_SUCCESS;
440fc135 11251 }
47589c8c
GM
11252 }
11253 else if (scroll_p)
cb617e7c 11254 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11255 else
11256 {
11257 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
cb617e7c 11258 rc = CURSOR_MOVEMENT_SUCCESS;
47589c8c
GM
11259 }
11260 }
11261 }
11262
11263 return rc;
11264}
11265
9a08d928
SM
11266void
11267set_vertical_scroll_bar (w)
11268 struct window *w;
11269{
11270 int start, end, whole;
11271
11272 /* Calculate the start and end positions for the current window.
11273 At some point, it would be nice to choose between scrollbars
11274 which reflect the whole buffer size, with special markers
11275 indicating narrowing, and scrollbars which reflect only the
11276 visible region.
11277
11278 Note that mini-buffers sometimes aren't displaying any text. */
11279 if (!MINI_WINDOW_P (w)
11280 || (w == XWINDOW (minibuf_window)
11281 && NILP (echo_area_buffer[0])))
11282 {
11283 struct buffer *buf = XBUFFER (w->buffer);
11284 whole = BUF_ZV (buf) - BUF_BEGV (buf);
11285 start = marker_position (w->start) - BUF_BEGV (buf);
11286 /* I don't think this is guaranteed to be right. For the
11287 moment, we'll pretend it is. */
11288 end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf);
11289
11290 if (end < start)
11291 end = start;
11292 if (whole < (end - start))
11293 whole = end - start;
11294 }
11295 else
11296 start = end = whole = 0;
11297
11298 /* Indicate what this scroll bar ought to be displaying now. */
11299 set_vertical_scroll_bar_hook (w, end - start, whole, start);
11300}
47589c8c 11301
5f5c8ee5 11302/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
b60c9653
RS
11303 selected_window is redisplayed.
11304
11305 We can return without actually redisplaying the window if
11306 fonts_changed_p is nonzero. In that case, redisplay_internal will
11307 retry. */
90adcf20 11308
a2889657 11309static void
5f5c8ee5 11310redisplay_window (window, just_this_one_p)
a2889657 11311 Lisp_Object window;
5f5c8ee5 11312 int just_this_one_p;
a2889657 11313{
5f5c8ee5
GM
11314 struct window *w = XWINDOW (window);
11315 struct frame *f = XFRAME (w->frame);
11316 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 11317 struct buffer *old = current_buffer;
5f5c8ee5 11318 struct text_pos lpoint, opoint, startp;
e481f960 11319 int update_mode_line;
5f5c8ee5
GM
11320 int tem;
11321 struct it it;
11322 /* Record it now because it's overwritten. */
11323 int current_matrix_up_to_date_p = 0;
c62c1bb5
RS
11324 /* This is less strict than current_matrix_up_to_date_p.
11325 It indictes that the buffer contents and narrowing are unchanged. */
11326 int buffer_unchanged_p = 0;
5f5c8ee5 11327 int temp_scroll_step = 0;
331379bf 11328 int count = SPECPDL_INDEX ();
47589c8c 11329 int rc;
ddf6b9a3 11330 int centering_position;
03b0a4b4 11331 int last_line_misfit = 0;
a2889657 11332
5f5c8ee5
GM
11333 SET_TEXT_POS (lpoint, PT, PT_BYTE);
11334 opoint = lpoint;
a2889657 11335
5f5c8ee5
GM
11336 /* W must be a leaf window here. */
11337 xassert (!NILP (w->buffer));
11338#if GLYPH_DEBUG
11339 *w->desired_matrix->method = 0;
11340#endif
2e54982e
RS
11341
11342 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
11343
11344 reconsider_clip_changes (w, buffer);
2311178e
TTN
11345
11346 /* Has the mode line to be updated? */
5f5c8ee5
GM
11347 update_mode_line = (!NILP (w->update_mode_line)
11348 || update_mode_lines
c62c1bb5
RS
11349 || buffer->clip_changed
11350 || buffer->prevent_redisplay_optimizations_p);
8de2d90b
JB
11351
11352 if (MINI_WINDOW_P (w))
11353 {
5f5c8ee5 11354 if (w == XWINDOW (echo_area_window)
c6e89d6c 11355 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
11356 {
11357 if (update_mode_line)
11358 /* We may have to update a tty frame's menu bar or a
e037b9ec 11359 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
11360 goto finish_menu_bars;
11361 else
11362 /* We've already displayed the echo area glyphs in this window. */
11363 goto finish_scroll_bars;
11364 }
b2b5455d
RS
11365 else if ((w != XWINDOW (minibuf_window)
11366 || minibuf_level == 0)
c0bcce6f
JPW
11367 /* When buffer is nonempty, redisplay window normally. */
11368 && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
3354fdcf
RS
11369 /* Quail displays non-mini buffers in minibuffer window.
11370 In that case, redisplay the window normally. */
b2b5455d 11371 && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
8de2d90b 11372 {
3354fdcf
RS
11373 /* W is a mini-buffer window, but it's not active, so clear
11374 it. */
5f5c8ee5
GM
11375 int yb = window_text_bottom_y (w);
11376 struct glyph_row *row;
11377 int y;
11378
11379 for (y = 0, row = w->desired_matrix->rows;
11380 y < yb;
11381 y += row->height, ++row)
11382 blank_row (w, row, y);
88f22aff 11383 goto finish_scroll_bars;
8de2d90b 11384 }
c095a1dd
GM
11385
11386 clear_glyph_matrix (w->desired_matrix);
8de2d90b 11387 }
a2889657 11388
5f5c8ee5
GM
11389 /* Otherwise set up data on this window; select its buffer and point
11390 value. */
6a93695f
GM
11391 /* Really select the buffer, for the sake of buffer-local
11392 variables. */
11393 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5
GM
11394 SET_TEXT_POS (opoint, PT, PT_BYTE);
11395
11396 current_matrix_up_to_date_p
11397 = (!NILP (w->window_end_valid)
11398 && !current_buffer->clip_changed
c62c1bb5 11399 && !current_buffer->prevent_redisplay_optimizations_p
5f5c8ee5
GM
11400 && XFASTINT (w->last_modified) >= MODIFF
11401 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 11402
c62c1bb5
RS
11403 buffer_unchanged_p
11404 = (!NILP (w->window_end_valid)
11405 && !current_buffer->clip_changed
3f1258d0 11406 && XFASTINT (w->last_modified) >= MODIFF
c62c1bb5
RS
11407 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
11408
5f5c8ee5
GM
11409 /* When windows_or_buffers_changed is non-zero, we can't rely on
11410 the window end being valid, so set it to nil there. */
11411 if (windows_or_buffers_changed)
11412 {
11413 /* If window starts on a continuation line, maybe adjust the
11414 window start in case the window's width changed. */
11415 if (XMARKER (w->start)->buffer == current_buffer)
11416 compute_window_start_on_continuation_line (w);
2311178e 11417
5f5c8ee5
GM
11418 w->window_end_valid = Qnil;
11419 }
12adba34 11420
5f5c8ee5
GM
11421 /* Some sanity checks. */
11422 CHECK_WINDOW_END (w);
11423 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 11424 abort ();
5f5c8ee5 11425 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 11426 abort ();
a2889657 11427
28995e67
RS
11428 /* If %c is in mode line, update it if needed. */
11429 if (!NILP (w->column_number_displayed)
11430 /* This alternative quickly identifies a common case
11431 where no change is needed. */
11432 && !(PT == XFASTINT (w->last_point)
8850a573
RS
11433 && XFASTINT (w->last_modified) >= MODIFF
11434 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
11435 && (XFASTINT (w->column_number_displayed)
11436 != (int) current_column ())) /* iftc */
11437 update_mode_line = 1;
28995e67 11438
5f5c8ee5
GM
11439 /* Count number of windows showing the selected buffer. An indirect
11440 buffer counts as its base buffer. */
11441 if (!just_this_one_p)
42640f83
RS
11442 {
11443 struct buffer *current_base, *window_base;
11444 current_base = current_buffer;
11445 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
11446 if (current_base->base_buffer)
11447 current_base = current_base->base_buffer;
11448 if (window_base->base_buffer)
11449 window_base = window_base->base_buffer;
11450 if (current_base == window_base)
11451 buffer_shared++;
11452 }
a2889657 11453
5f5c8ee5
GM
11454 /* Point refers normally to the selected window. For any other
11455 window, set up appropriate value. */
a2889657
JB
11456 if (!EQ (window, selected_window))
11457 {
12adba34
RS
11458 int new_pt = XMARKER (w->pointm)->charpos;
11459 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 11460 if (new_pt < BEGV)
a2889657 11461 {
f67a0f51 11462 new_pt = BEGV;
12adba34
RS
11463 new_pt_byte = BEGV_BYTE;
11464 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 11465 }
f67a0f51 11466 else if (new_pt > (ZV - 1))
a2889657 11467 {
f67a0f51 11468 new_pt = ZV;
12adba34
RS
11469 new_pt_byte = ZV_BYTE;
11470 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 11471 }
2311178e 11472
f67a0f51 11473 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 11474 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
11475 }
11476
f4faa47c 11477 /* If any of the character widths specified in the display table
5f5c8ee5
GM
11478 have changed, invalidate the width run cache. It's true that
11479 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
11480 redisplay goes (non-fatally) haywire when the display table is
11481 changed, so why should we worry about doing any better? */
11482 if (current_buffer->width_run_cache)
11483 {
f908610f 11484 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
11485
11486 if (! disptab_matches_widthtab (disptab,
11487 XVECTOR (current_buffer->width_table)))
11488 {
11489 invalidate_region_cache (current_buffer,
11490 current_buffer->width_run_cache,
11491 BEG, Z);
11492 recompute_width_table (current_buffer, disptab);
11493 }
11494 }
11495
a2889657 11496 /* If window-start is screwed up, choose a new one. */
a2889657
JB
11497 if (XMARKER (w->start)->buffer != current_buffer)
11498 goto recenter;
11499
5f5c8ee5 11500 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 11501
cf0df6ab
RS
11502 /* If someone specified a new starting point but did not insist,
11503 check whether it can be used. */
cfad01b4
GM
11504 if (!NILP (w->optional_new_start)
11505 && CHARPOS (startp) >= BEGV
11506 && CHARPOS (startp) <= ZV)
cf0df6ab
RS
11507 {
11508 w->optional_new_start = Qnil;
5f5c8ee5
GM
11509 start_display (&it, w, startp);
11510 move_it_to (&it, PT, 0, it.last_visible_y, -1,
11511 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
11512 if (IT_CHARPOS (it) == PT)
cf0df6ab
RS
11513 w->force_start = Qt;
11514 }
11515
8de2d90b 11516 /* Handle case where place to start displaying has been specified,
aa6d10fa 11517 unless the specified location is outside the accessible range. */
9472f927
GM
11518 if (!NILP (w->force_start)
11519 || w->frozen_window_start_p)
a2889657 11520 {
b60c9653
RS
11521 /* We set this later on if we have to adjust point. */
11522 int new_vpos = -1;
11523
e63574d7 11524 w->force_start = Qnil;
5f5c8ee5 11525 w->vscroll = 0;
b5174a51 11526 w->window_end_valid = Qnil;
5f5c8ee5
GM
11527
11528 /* Forget any recorded base line for line number display. */
c62c1bb5 11529 if (!buffer_unchanged_p)
5f5c8ee5
GM
11530 w->base_line_number = Qnil;
11531
75c43375
RS
11532 /* Redisplay the mode line. Select the buffer properly for that.
11533 Also, run the hook window-scroll-functions
11534 because we have scrolled. */
e63574d7
RS
11535 /* Note, we do this after clearing force_start because
11536 if there's an error, it is better to forget about force_start
11537 than to get into an infinite loop calling the hook functions
11538 and having them get more errors. */
75c43375
RS
11539 if (!update_mode_line
11540 || ! NILP (Vwindow_scroll_functions))
e481f960 11541 {
e481f960
RS
11542 update_mode_line = 1;
11543 w->update_mode_line = Qt;
5f5c8ee5 11544 startp = run_window_scroll_functions (window, startp);
e481f960 11545 }
2311178e 11546
ac90c44f
GM
11547 w->last_modified = make_number (0);
11548 w->last_overlay_modified = make_number (0);
5f5c8ee5
GM
11549 if (CHARPOS (startp) < BEGV)
11550 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
11551 else if (CHARPOS (startp) > ZV)
11552 SET_TEXT_POS (startp, ZV, ZV_BYTE);
2311178e
TTN
11553
11554 /* Redisplay, then check if cursor has been set during the
5f5c8ee5
GM
11555 redisplay. Give up if new fonts were loaded. */
11556 if (!try_window (window, startp))
11557 {
11558 w->force_start = Qt;
11559 clear_glyph_matrix (w->desired_matrix);
b60c9653 11560 goto need_larger_matrices;
5f5c8ee5
GM
11561 }
11562
9472f927 11563 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5 11564 {
b28cb6ed
GM
11565 /* If point does not appear, try to move point so it does
11566 appear. The desired matrix has been built above, so we
11567 can use it here. */
b60c9653
RS
11568 new_vpos = window_box_height (w) / 2;
11569 }
11570
11571 if (!make_cursor_line_fully_visible (w))
11572 {
11573 /* Point does appear, but on a line partly visible at end of window.
11574 Move it back to a fully-visible line. */
11575 new_vpos = window_box_height (w);
11576 }
11577
11578 /* If we need to move point for either of the above reasons,
11579 now actually do it. */
11580 if (new_vpos >= 0)
11581 {
b28cb6ed
GM
11582 struct glyph_row *row;
11583
b28cb6ed 11584 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
b60c9653 11585 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos)
5f5c8ee5
GM
11586 ++row;
11587
11588 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
11589 MATRIX_ROW_START_BYTEPOS (row));
11590
90adcf20 11591 if (w != XWINDOW (selected_window))
12adba34 11592 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
11593 else if (current_buffer == old)
11594 SET_TEXT_POS (lpoint, PT, PT_BYTE);
11595
11596 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
2311178e 11597
5f5c8ee5
GM
11598 /* If we are highlighting the region, then we just changed
11599 the region, so redisplay to show it. */
df0b5ea1
RS
11600 if (!NILP (Vtransient_mark_mode)
11601 && !NILP (current_buffer->mark_active))
6f27fa9b 11602 {
5f5c8ee5
GM
11603 clear_glyph_matrix (w->desired_matrix);
11604 if (!try_window (window, startp))
cb617e7c 11605 goto need_larger_matrices;
6f27fa9b 11606 }
a2889657 11607 }
5f5c8ee5 11608
5f5c8ee5
GM
11609#if GLYPH_DEBUG
11610 debug_method_add (w, "forced window start");
11611#endif
a2889657
JB
11612 goto done;
11613 }
11614
5f5c8ee5 11615 /* Handle case where text has not changed, only point, and it has
3f029ea0
RS
11616 not moved off the frame, and we are not retrying after hscroll.
11617 (current_matrix_up_to_date_p is nonzero when retrying.) */
11618 if (current_matrix_up_to_date_p
47589c8c 11619 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
cb617e7c 11620 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
a2889657 11621 {
cb617e7c
GM
11622 switch (rc)
11623 {
11624 case CURSOR_MOVEMENT_SUCCESS:
11625 goto done;
2311178e 11626
b60c9653 11627#if 0 /* try_cursor_movement never returns this value. */
cb617e7c
GM
11628 case CURSOR_MOVEMENT_NEED_LARGER_MATRICES:
11629 goto need_larger_matrices;
b60c9653 11630#endif
2311178e 11631
cb617e7c
GM
11632 case CURSOR_MOVEMENT_MUST_SCROLL:
11633 goto try_to_scroll;
2311178e 11634
cb617e7c
GM
11635 default:
11636 abort ();
11637 }
a2889657
JB
11638 }
11639 /* If current starting point was originally the beginning of a line
11640 but no longer is, find a new starting point. */
265a9e55 11641 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
11642 && !(CHARPOS (startp) <= BEGV
11643 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 11644 {
5f5c8ee5
GM
11645#if GLYPH_DEBUG
11646 debug_method_add (w, "recenter 1");
11647#endif
a2889657
JB
11648 goto recenter;
11649 }
2311178e 11650
27d16f05
GM
11651 /* Try scrolling with try_window_id. Value is > 0 if update has
11652 been done, it is -1 if we know that the same window start will
11653 not work. It is 0 if unsuccessful for some other reason. */
11654 else if ((tem = try_window_id (w)) != 0)
a2889657 11655 {
5f5c8ee5 11656#if GLYPH_DEBUG
ef121659 11657 debug_method_add (w, "try_window_id %d", tem);
5f5c8ee5
GM
11658#endif
11659
11660 if (fonts_changed_p)
cb617e7c 11661 goto need_larger_matrices;
a2889657
JB
11662 if (tem > 0)
11663 goto done;
ef121659 11664
5f5c8ee5
GM
11665 /* Otherwise try_window_id has returned -1 which means that we
11666 don't want the alternative below this comment to execute. */
a2889657 11667 }
5f5c8ee5
GM
11668 else if (CHARPOS (startp) >= BEGV
11669 && CHARPOS (startp) <= ZV
11670 && PT >= CHARPOS (startp)
11671 && (CHARPOS (startp) < ZV
e9874cee 11672 /* Avoid starting at end of buffer. */
5f5c8ee5 11673 || CHARPOS (startp) == BEGV
8850a573
RS
11674 || (XFASTINT (w->last_modified) >= MODIFF
11675 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 11676 {
5f5c8ee5
GM
11677#if GLYPH_DEBUG
11678 debug_method_add (w, "same window start");
11679#endif
2311178e 11680
5f5c8ee5
GM
11681 /* Try to redisplay starting at same place as before.
11682 If point has not moved off frame, accept the results. */
11683 if (!current_matrix_up_to_date_p
11684 /* Don't use try_window_reusing_current_matrix in this case
15e26c76
GM
11685 because a window scroll function can have changed the
11686 buffer. */
5f5c8ee5
GM
11687 || !NILP (Vwindow_scroll_functions)
11688 || MINI_WINDOW_P (w)
11689 || !try_window_reusing_current_matrix (w))
11690 {
11691 IF_DEBUG (debug_method_add (w, "1"));
11692 try_window (window, startp);
11693 }
11694
11695 if (fonts_changed_p)
cb617e7c 11696 goto need_larger_matrices;
2311178e 11697
5f5c8ee5 11698 if (w->cursor.vpos >= 0)
aa6d10fa 11699 {
2311178e 11700 if (!just_this_one_p
5f5c8ee5 11701 || current_buffer->clip_changed
9142dd5b 11702 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
11703 /* Forget any recorded base line for line number display. */
11704 w->base_line_number = Qnil;
2311178e 11705
cb617e7c 11706 if (!make_cursor_line_fully_visible (w))
03b0a4b4
RS
11707 {
11708 clear_glyph_matrix (w->desired_matrix);
11709 last_line_misfit = 1;
11710 }
ddf6b9a3 11711 /* Drop through and scroll. */
ef3c2c73
RS
11712 else
11713 goto done;
aa6d10fa 11714 }
a2889657 11715 else
5f5c8ee5 11716 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
11717 }
11718
5f5c8ee5
GM
11719 try_to_scroll:
11720
ac90c44f
GM
11721 w->last_modified = make_number (0);
11722 w->last_overlay_modified = make_number (0);
5f5c8ee5 11723
e481f960
RS
11724 /* Redisplay the mode line. Select the buffer properly for that. */
11725 if (!update_mode_line)
11726 {
e481f960
RS
11727 update_mode_line = 1;
11728 w->update_mode_line = Qt;
11729 }
a2889657 11730
5f5c8ee5
GM
11731 /* Try to scroll by specified few lines. */
11732 if ((scroll_conservatively
11733 || scroll_step
11734 || temp_scroll_step
11735 || NUMBERP (current_buffer->scroll_up_aggressively)
11736 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 11737 && !current_buffer->clip_changed
2311178e 11738 && CHARPOS (startp) >= BEGV
5f5c8ee5 11739 && CHARPOS (startp) <= ZV)
0789adb2 11740 {
5f5c8ee5
GM
11741 /* The function returns -1 if new fonts were loaded, 1 if
11742 successful, 0 if not successful. */
11743 int rc = try_scrolling (window, just_this_one_p,
11744 scroll_conservatively,
11745 scroll_step,
03b0a4b4 11746 temp_scroll_step, last_line_misfit);
cb617e7c
GM
11747 switch (rc)
11748 {
11749 case SCROLLING_SUCCESS:
11750 goto done;
2311178e 11751
cb617e7c
GM
11752 case SCROLLING_NEED_LARGER_MATRICES:
11753 goto need_larger_matrices;
2311178e 11754
cb617e7c
GM
11755 case SCROLLING_FAILED:
11756 break;
2311178e 11757
cb617e7c
GM
11758 default:
11759 abort ();
11760 }
5f5c8ee5 11761 }
f9c8af06 11762
5f5c8ee5 11763 /* Finally, just choose place to start which centers point */
5936754e 11764
5f5c8ee5 11765 recenter:
ddf6b9a3
RS
11766 centering_position = window_box_height (w) / 2;
11767
11768 point_at_top:
11769 /* Jump here with centering_position already set to 0. */
44173109 11770
5f5c8ee5
GM
11771#if GLYPH_DEBUG
11772 debug_method_add (w, "recenter");
11773#endif
0789adb2 11774
5f5c8ee5 11775 /* w->vscroll = 0; */
0789adb2 11776
5f5c8ee5 11777 /* Forget any previously recorded base line for line number display. */
c62c1bb5 11778 if (!buffer_unchanged_p)
5f5c8ee5
GM
11779 w->base_line_number = Qnil;
11780
11781 /* Move backward half the height of the window. */
11782 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
11783 it.current_y = it.last_visible_y;
ddf6b9a3 11784 move_it_vertically_backward (&it, centering_position);
5f5c8ee5
GM
11785 xassert (IT_CHARPOS (it) >= BEGV);
11786
11787 /* The function move_it_vertically_backward may move over more
11788 than the specified y-distance. If it->w is small, e.g. a
11789 mini-buffer window, we may end up in front of the window's
11790 display area. Start displaying at the start of the line
11791 containing PT in this case. */
11792 if (it.current_y <= 0)
11793 {
11794 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
11795 move_it_vertically (&it, 0);
11796 xassert (IT_CHARPOS (it) <= PT);
11797 it.current_y = 0;
0789adb2
RS
11798 }
11799
5f5c8ee5 11800 it.current_x = it.hpos = 0;
2311178e 11801
5f5c8ee5
GM
11802 /* Set startp here explicitly in case that helps avoid an infinite loop
11803 in case the window-scroll-functions functions get errors. */
11804 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
11805
11806 /* Run scroll hooks. */
11807 startp = run_window_scroll_functions (window, it.current.pos);
11808
11809 /* Redisplay the window. */
11810 if (!current_matrix_up_to_date_p
11811 || windows_or_buffers_changed
5fb96e96 11812 || cursor_type_changed
5f5c8ee5
GM
11813 /* Don't use try_window_reusing_current_matrix in this case
11814 because it can have changed the buffer. */
11815 || !NILP (Vwindow_scroll_functions)
11816 || !just_this_one_p
11817 || MINI_WINDOW_P (w)
11818 || !try_window_reusing_current_matrix (w))
11819 try_window (window, startp);
11820
11821 /* If new fonts have been loaded (due to fontsets), give up. We
11822 have to start a new redisplay since we need to re-adjust glyph
11823 matrices. */
11824 if (fonts_changed_p)
cb617e7c 11825 goto need_larger_matrices;
5f5c8ee5
GM
11826
11827 /* If cursor did not appear assume that the middle of the window is
11828 in the first line of the window. Do it again with the next line.
11829 (Imagine a window of height 100, displaying two lines of height
11830 60. Moving back 50 from it->last_visible_y will end in the first
11831 line.) */
11832 if (w->cursor.vpos < 0)
a2889657 11833 {
5f5c8ee5
GM
11834 if (!NILP (w->window_end_valid)
11835 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 11836 {
5f5c8ee5
GM
11837 clear_glyph_matrix (w->desired_matrix);
11838 move_it_by_lines (&it, 1, 0);
11839 try_window (window, it.current.pos);
a2889657 11840 }
5f5c8ee5 11841 else if (PT < IT_CHARPOS (it))
a2889657 11842 {
5f5c8ee5
GM
11843 clear_glyph_matrix (w->desired_matrix);
11844 move_it_by_lines (&it, -1, 0);
11845 try_window (window, it.current.pos);
11846 }
11847 else
11848 {
11849 /* Not much we can do about it. */
a2889657 11850 }
a2889657 11851 }
010494d0 11852
5f5c8ee5
GM
11853 /* Consider the following case: Window starts at BEGV, there is
11854 invisible, intangible text at BEGV, so that display starts at
11855 some point START > BEGV. It can happen that we are called with
11856 PT somewhere between BEGV and START. Try to handle that case. */
11857 if (w->cursor.vpos < 0)
835766b6 11858 {
5f5c8ee5
GM
11859 struct glyph_row *row = w->current_matrix->rows;
11860 if (row->mode_line_p)
11861 ++row;
11862 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 11863 }
2311178e 11864
cb617e7c 11865 if (!make_cursor_line_fully_visible (w))
ddf6b9a3 11866 {
932357b4
KS
11867 /* If vscroll is enabled, disable it and try again. */
11868 if (w->vscroll)
11869 {
11870 w->vscroll = 0;
11871 clear_glyph_matrix (w->desired_matrix);
11872 goto recenter;
11873 }
2a6d0874 11874
ddf6b9a3
RS
11875 /* If centering point failed to make the whole line visible,
11876 put point at the top instead. That has to make the whole line
11877 visible, if it can be done. */
11878 centering_position = 0;
11879 goto point_at_top;
11880 }
b5174a51 11881
74d481ac
GM
11882 done:
11883
5f5c8ee5
GM
11884 SET_TEXT_POS_FROM_MARKER (startp, w->start);
11885 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
11886 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
11887 ? Qt : Qnil);
a2889657 11888
5f5c8ee5 11889 /* Display the mode line, if we must. */
e481f960 11890 if ((update_mode_line
aa6d10fa 11891 /* If window not full width, must redo its mode line
2311178e 11892 if (a) the window to its side is being redone and
5f5c8ee5
GM
11893 (b) we do a frame-based redisplay. This is a consequence
11894 of how inverted lines are drawn in frame-based redisplay. */
2311178e 11895 || (!just_this_one_p
5f5c8ee5
GM
11896 && !FRAME_WINDOW_P (f)
11897 && !WINDOW_FULL_WIDTH_P (w))
11898 /* Line number to display. */
155ef550 11899 || INTEGERP (w->base_line_pos)
5f5c8ee5 11900 /* Column number is displayed and different from the one displayed. */
155ef550 11901 || (!NILP (w->column_number_displayed)
2311178e
TTN
11902 && (XFASTINT (w->column_number_displayed)
11903 != (int) current_column ()))) /* iftc */
5f5c8ee5
GM
11904 /* This means that the window has a mode line. */
11905 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 11906 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 11907 {
5f5c8ee5
GM
11908 display_mode_lines (w);
11909
11910 /* If mode line height has changed, arrange for a thorough
11911 immediate redisplay using the correct mode line height. */
11912 if (WINDOW_WANTS_MODELINE_P (w)
11913 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 11914 {
5f5c8ee5
GM
11915 fonts_changed_p = 1;
11916 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
11917 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 11918 }
2311178e 11919
5f5c8ee5
GM
11920 /* If top line height has changed, arrange for a thorough
11921 immediate redisplay using the correct mode line height. */
045dee35
GM
11922 if (WINDOW_WANTS_HEADER_LINE_P (w)
11923 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
11924 {
11925 fonts_changed_p = 1;
045dee35
GM
11926 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
11927 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
11928 }
11929
11930 if (fonts_changed_p)
cb617e7c 11931 goto need_larger_matrices;
5ba50c51 11932 }
5f5c8ee5
GM
11933
11934 if (!line_number_displayed
11935 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
11936 {
11937 w->base_line_pos = Qnil;
11938 w->base_line_number = Qnil;
11939 }
a2889657 11940
5f5c8ee5 11941 finish_menu_bars:
2311178e 11942
7ce2c095 11943 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 11944 if (update_mode_line
5f5c8ee5
GM
11945 && EQ (FRAME_SELECTED_WINDOW (f), window))
11946 {
11947 int redisplay_menu_p = 0;
488dd4c4 11948 int redisplay_tool_bar_p = 0;
5f5c8ee5
GM
11949
11950 if (FRAME_WINDOW_P (f))
11951 {
488dd4c4
JD
11952#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
11953 || defined (USE_GTK)
5f5c8ee5 11954 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 11955#else
5f5c8ee5 11956 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 11957#endif
5f5c8ee5
GM
11958 }
11959 else
11960 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
11961
11962 if (redisplay_menu_p)
11963 display_menu_bar (w);
11964
11965#ifdef HAVE_WINDOW_SYSTEM
488dd4c4
JD
11966#ifdef USE_GTK
11967 redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
11968#else
11969 redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
11970 && (FRAME_TOOL_BAR_LINES (f) > 0
11971 || auto_resize_tool_bars_p);
177c0ea7 11972
488dd4c4
JD
11973#endif
11974
11975 if (redisplay_tool_bar_p)
11976 redisplay_tool_bar (f);
5f5c8ee5
GM
11977#endif
11978 }
7ce2c095 11979
b60c9653
RS
11980 /* We go to this label, with fonts_changed_p nonzero,
11981 if it is necessary to try again using larger glyph matrices.
11982 We have to redeem the scroll bar even in this case,
11983 because the loop in redisplay_internal expects that. */
cb617e7c
GM
11984 need_larger_matrices:
11985 ;
88f22aff 11986 finish_scroll_bars:
5f5c8ee5 11987
da8b7f4f 11988 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
30c566e4 11989 {
9a08d928
SM
11990 /* Set the thumb's position and size. */
11991 set_vertical_scroll_bar (w);
30c566e4 11992
5f5c8ee5
GM
11993 /* Note that we actually used the scroll bar attached to this
11994 window, so it shouldn't be deleted at the end of redisplay. */
504454e8 11995 redeem_scroll_bar_hook (w);
30c566e4 11996 }
b1d1124b 11997
5f5c8ee5
GM
11998 /* Restore current_buffer and value of point in it. */
11999 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
6a93695f 12000 set_buffer_internal_1 (old);
5f5c8ee5 12001 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
12002
12003 unbind_to (count, Qnil);
a2889657 12004}
a2889657 12005
5f5c8ee5
GM
12006
12007/* Build the complete desired matrix of WINDOW with a window start
12008 buffer position POS. Value is non-zero if successful. It is zero
12009 if fonts were loaded during redisplay which makes re-adjusting
12010 glyph matrices necessary. */
12011
12012int
a2889657
JB
12013try_window (window, pos)
12014 Lisp_Object window;
5f5c8ee5
GM
12015 struct text_pos pos;
12016{
12017 struct window *w = XWINDOW (window);
12018 struct it it;
12019 struct glyph_row *last_text_row = NULL;
9cbab4ff 12020
5f5c8ee5
GM
12021 /* Make POS the new window start. */
12022 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 12023
5f5c8ee5
GM
12024 /* Mark cursor position as unknown. No overlay arrow seen. */
12025 w->cursor.vpos = -1;
a2889657 12026 overlay_arrow_seen = 0;
642eefc6 12027
5f5c8ee5
GM
12028 /* Initialize iterator and info to start at POS. */
12029 start_display (&it, w, pos);
a2889657 12030
5f5c8ee5
GM
12031 /* Display all lines of W. */
12032 while (it.current_y < it.last_visible_y)
12033 {
12034 if (display_line (&it))
12035 last_text_row = it.glyph_row - 1;
12036 if (fonts_changed_p)
12037 return 0;
12038 }
a2889657 12039
5f5c8ee5
GM
12040 /* If bottom moved off end of frame, change mode line percentage. */
12041 if (XFASTINT (w->window_end_pos) <= 0
12042 && Z != IT_CHARPOS (it))
a2889657
JB
12043 w->update_mode_line = Qt;
12044
5f5c8ee5
GM
12045 /* Set window_end_pos to the offset of the last character displayed
12046 on the window from the end of current_buffer. Set
12047 window_end_vpos to its row number. */
12048 if (last_text_row)
12049 {
12050 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
12051 w->window_end_bytepos
12052 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12053 w->window_end_pos
12054 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12055 w->window_end_vpos
12056 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12057 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
12058 ->displays_text_p);
12059 }
12060 else
12061 {
86bf3faa
RS
12062 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
12063 w->window_end_pos = make_number (Z - ZV);
12064 w->window_end_vpos = make_number (0);
5f5c8ee5 12065 }
2311178e 12066
a2889657
JB
12067 /* But that is not valid info until redisplay finishes. */
12068 w->window_end_valid = Qnil;
5f5c8ee5 12069 return 1;
a2889657 12070}
5f5c8ee5
GM
12071
12072
a2889657 12073\f
5f5c8ee5
GM
12074/************************************************************************
12075 Window redisplay reusing current matrix when buffer has not changed
12076 ************************************************************************/
12077
12078/* Try redisplay of window W showing an unchanged buffer with a
12079 different window start than the last time it was displayed by
12080 reusing its current matrix. Value is non-zero if successful.
12081 W->start is the new window start. */
a2889657
JB
12082
12083static int
5f5c8ee5
GM
12084try_window_reusing_current_matrix (w)
12085 struct window *w;
a2889657 12086{
5f5c8ee5
GM
12087 struct frame *f = XFRAME (w->frame);
12088 struct glyph_row *row, *bottom_row;
12089 struct it it;
12090 struct run run;
12091 struct text_pos start, new_start;
12092 int nrows_scrolled, i;
12093 struct glyph_row *last_text_row;
12094 struct glyph_row *last_reused_text_row;
12095 struct glyph_row *start_row;
12096 int start_vpos, min_y, max_y;
75c5350a 12097
69d1f7c9 12098#if GLYPH_DEBUG
76cb5e06
GM
12099 if (inhibit_try_window_reusing)
12100 return 0;
12101#endif
12102
d18354b6
GM
12103 if (/* This function doesn't handle terminal frames. */
12104 !FRAME_WINDOW_P (f)
12105 /* Don't try to reuse the display if windows have been split
12106 or such. */
5fb96e96
RS
12107 || windows_or_buffers_changed
12108 || cursor_type_changed)
5f5c8ee5 12109 return 0;
a2889657 12110
5f5c8ee5
GM
12111 /* Can't do this if region may have changed. */
12112 if ((!NILP (Vtransient_mark_mode)
12113 && !NILP (current_buffer->mark_active))
8f897821
GM
12114 || !NILP (w->region_showing)
12115 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 12116 return 0;
a2889657 12117
5f5c8ee5 12118 /* If top-line visibility has changed, give up. */
045dee35
GM
12119 if (WINDOW_WANTS_HEADER_LINE_P (w)
12120 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
12121 return 0;
12122
12123 /* Give up if old or new display is scrolled vertically. We could
12124 make this function handle this, but right now it doesn't. */
12125 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
12126 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
12127 return 0;
12128
12129 /* The variable new_start now holds the new window start. The old
12130 start `start' can be determined from the current matrix. */
12131 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
12132 start = start_row->start.pos;
12133 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 12134
5f5c8ee5
GM
12135 /* Clear the desired matrix for the display below. */
12136 clear_glyph_matrix (w->desired_matrix);
2311178e 12137
5f5c8ee5
GM
12138 if (CHARPOS (new_start) <= CHARPOS (start))
12139 {
12140 int first_row_y;
2311178e 12141
607ec83c
GM
12142 /* Don't use this method if the display starts with an ellipsis
12143 displayed for invisible text. It's not easy to handle that case
12144 below, and it's certainly not worth the effort since this is
12145 not a frequent case. */
12146 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
12147 return 0;
12148
5f5c8ee5 12149 IF_DEBUG (debug_method_add (w, "twu1"));
2311178e 12150
5f5c8ee5
GM
12151 /* Display up to a row that can be reused. The variable
12152 last_text_row is set to the last row displayed that displays
b48f74cb
GM
12153 text. Note that it.vpos == 0 if or if not there is a
12154 header-line; it's not the same as the MATRIX_ROW_VPOS! */
5f5c8ee5
GM
12155 start_display (&it, w, new_start);
12156 first_row_y = it.current_y;
12157 w->cursor.vpos = -1;
12158 last_text_row = last_reused_text_row = NULL;
2311178e 12159
5f5c8ee5
GM
12160 while (it.current_y < it.last_visible_y
12161 && IT_CHARPOS (it) < CHARPOS (start)
12162 && !fonts_changed_p)
12163 if (display_line (&it))
12164 last_text_row = it.glyph_row - 1;
12165
12166 /* A value of current_y < last_visible_y means that we stopped
12167 at the previous window start, which in turn means that we
12168 have at least one reusable row. */
12169 if (it.current_y < it.last_visible_y)
a2889657 12170 {
b48f74cb 12171 /* IT.vpos always starts from 0; it counts text lines. */
5f5c8ee5 12172 nrows_scrolled = it.vpos;
2311178e 12173
5f5c8ee5
GM
12174 /* Find PT if not already found in the lines displayed. */
12175 if (w->cursor.vpos < 0)
a2889657 12176 {
5f5c8ee5 12177 int dy = it.current_y - first_row_y;
2311178e 12178
5f5c8ee5 12179 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
0df56f4d
GM
12180 row = row_containing_pos (w, PT, row, NULL, dy);
12181 if (row)
12182 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
12183 dy, nrows_scrolled);
12184 else
5f5c8ee5
GM
12185 {
12186 clear_glyph_matrix (w->desired_matrix);
12187 return 0;
12188 }
a2889657 12189 }
5f5c8ee5
GM
12190
12191 /* Scroll the display. Do it before the current matrix is
12192 changed. The problem here is that update has not yet
12193 run, i.e. part of the current matrix is not up to date.
12194 scroll_run_hook will clear the cursor, and use the
12195 current matrix to get the height of the row the cursor is
12196 in. */
12197 run.current_y = first_row_y;
12198 run.desired_y = it.current_y;
12199 run.height = it.last_visible_y - it.current_y;
b48f74cb
GM
12200
12201 if (run.height > 0 && run.current_y != run.desired_y)
a2889657 12202 {
5f5c8ee5
GM
12203 update_begin (f);
12204 rif->update_window_begin_hook (w);
fa3c6b4d 12205 rif->clear_window_mouse_face (w);
5f5c8ee5 12206 rif->scroll_run_hook (w, &run);
64d1e7d3 12207 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5 12208 update_end (f);
a2889657 12209 }
5f5c8ee5
GM
12210
12211 /* Shift current matrix down by nrows_scrolled lines. */
12212 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
12213 rotate_matrix (w->current_matrix,
12214 start_vpos,
12215 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
12216 nrows_scrolled);
2311178e 12217
9c8b8382 12218 /* Disable lines that must be updated. */
5f5c8ee5 12219 for (i = 0; i < it.vpos; ++i)
b48f74cb 12220 (start_row + i)->enabled_p = 0;
9c8b8382 12221
5f5c8ee5 12222 /* Re-compute Y positions. */
da8b7f4f 12223 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12224 max_y = it.last_visible_y;
b48f74cb
GM
12225 for (row = start_row + nrows_scrolled;
12226 row < bottom_row;
12227 ++row)
d2f84654 12228 {
5f5c8ee5 12229 row->y = it.current_y;
75c5350a 12230 row->visible_height = row->height;
5f5c8ee5
GM
12231
12232 if (row->y < min_y)
75c5350a
GM
12233 row->visible_height -= min_y - row->y;
12234 if (row->y + row->height > max_y)
12235 row->visible_height -= row->y + row->height - max_y;
2311178e 12236
5f5c8ee5 12237 it.current_y += row->height;
5f5c8ee5
GM
12238
12239 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
12240 last_reused_text_row = row;
12241 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
12242 break;
d2f84654 12243 }
2311178e 12244
9c8b8382
GM
12245 /* Disable lines in the current matrix which are now
12246 below the window. */
bafb434c 12247 for (++row; row < bottom_row; ++row)
9c8b8382 12248 row->enabled_p = 0;
a2889657 12249 }
5f5c8ee5
GM
12250
12251 /* Update window_end_pos etc.; last_reused_text_row is the last
12252 reused row from the current matrix containing text, if any.
12253 The value of last_text_row is the last displayed line
12254 containing text. */
12255 if (last_reused_text_row)
a2889657 12256 {
5f5c8ee5
GM
12257 w->window_end_bytepos
12258 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
ac90c44f
GM
12259 w->window_end_pos
12260 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
12261 w->window_end_vpos
12262 = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
12263 w->current_matrix));
a2889657 12264 }
5f5c8ee5
GM
12265 else if (last_text_row)
12266 {
12267 w->window_end_bytepos
12268 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12269 w->window_end_pos
12270 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12271 w->window_end_vpos
12272 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12273 }
12274 else
12275 {
12276 /* This window must be completely empty. */
86bf3faa
RS
12277 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
12278 w->window_end_pos = make_number (Z - ZV);
12279 w->window_end_vpos = make_number (0);
5f5c8ee5
GM
12280 }
12281 w->window_end_valid = Qnil;
a2889657 12282
5f5c8ee5
GM
12283 /* Update hint: don't try scrolling again in update_window. */
12284 w->desired_matrix->no_scrolling_p = 1;
2311178e 12285
5f5c8ee5
GM
12286#if GLYPH_DEBUG
12287 debug_method_add (w, "try_window_reusing_current_matrix 1");
12288#endif
12289 return 1;
a2889657 12290 }
5f5c8ee5
GM
12291 else if (CHARPOS (new_start) > CHARPOS (start))
12292 {
12293 struct glyph_row *pt_row, *row;
12294 struct glyph_row *first_reusable_row;
12295 struct glyph_row *first_row_to_display;
12296 int dy;
12297 int yb = window_text_bottom_y (w);
12298
5f5c8ee5
GM
12299 /* Find the row starting at new_start, if there is one. Don't
12300 reuse a partially visible line at the end. */
b48f74cb 12301 first_reusable_row = start_row;
5f5c8ee5
GM
12302 while (first_reusable_row->enabled_p
12303 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
12304 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
12305 < CHARPOS (new_start)))
12306 ++first_reusable_row;
12307
12308 /* Give up if there is no row to reuse. */
12309 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
12310 || !first_reusable_row->enabled_p
12311 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
12312 != CHARPOS (new_start)))
5f5c8ee5
GM
12313 return 0;
12314
5f5c8ee5
GM
12315 /* We can reuse fully visible rows beginning with
12316 first_reusable_row to the end of the window. Set
12317 first_row_to_display to the first row that cannot be reused.
12318 Set pt_row to the row containing point, if there is any. */
5f5c8ee5 12319 pt_row = NULL;
ac90c44f
GM
12320 for (first_row_to_display = first_reusable_row;
12321 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
12322 ++first_row_to_display)
5f5c8ee5 12323 {
4bde0ebb
GM
12324 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
12325 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
5f5c8ee5 12326 pt_row = first_row_to_display;
5f5c8ee5 12327 }
a2889657 12328
5f5c8ee5
GM
12329 /* Start displaying at the start of first_row_to_display. */
12330 xassert (first_row_to_display->y < yb);
12331 init_to_row_start (&it, w, first_row_to_display);
607ec83c 12332
b48f74cb
GM
12333 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
12334 - start_vpos);
5f5c8ee5
GM
12335 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
12336 - nrows_scrolled);
b48f74cb 12337 it.current_y = (first_row_to_display->y - first_reusable_row->y
da8b7f4f 12338 + WINDOW_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
12339
12340 /* Display lines beginning with first_row_to_display in the
12341 desired matrix. Set last_text_row to the last row displayed
12342 that displays text. */
12343 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
12344 if (pt_row == NULL)
12345 w->cursor.vpos = -1;
12346 last_text_row = NULL;
12347 while (it.current_y < it.last_visible_y && !fonts_changed_p)
12348 if (display_line (&it))
12349 last_text_row = it.glyph_row - 1;
12350
12351 /* Give up If point isn't in a row displayed or reused. */
12352 if (w->cursor.vpos < 0)
12353 {
12354 clear_glyph_matrix (w->desired_matrix);
12355 return 0;
12356 }
12adba34 12357
5f5c8ee5
GM
12358 /* If point is in a reused row, adjust y and vpos of the cursor
12359 position. */
12360 if (pt_row)
12361 {
12362 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
12363 w->current_matrix);
12364 w->cursor.y -= first_reusable_row->y;
a2889657
JB
12365 }
12366
5f5c8ee5
GM
12367 /* Scroll the display. */
12368 run.current_y = first_reusable_row->y;
da8b7f4f 12369 run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12370 run.height = it.last_visible_y - run.current_y;
4da61803 12371 dy = run.current_y - run.desired_y;
2311178e 12372
5f5c8ee5
GM
12373 if (run.height)
12374 {
12375 struct frame *f = XFRAME (WINDOW_FRAME (w));
12376 update_begin (f);
12377 rif->update_window_begin_hook (w);
fa3c6b4d 12378 rif->clear_window_mouse_face (w);
5f5c8ee5 12379 rif->scroll_run_hook (w, &run);
64d1e7d3 12380 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
12381 update_end (f);
12382 }
a2889657 12383
5f5c8ee5
GM
12384 /* Adjust Y positions of reused rows. */
12385 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
da8b7f4f 12386 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12387 max_y = it.last_visible_y;
b48f74cb 12388 for (row = first_reusable_row; row < first_row_to_display; ++row)
5f5c8ee5
GM
12389 {
12390 row->y -= dy;
75c5350a 12391 row->visible_height = row->height;
5f5c8ee5 12392 if (row->y < min_y)
75c5350a
GM
12393 row->visible_height -= min_y - row->y;
12394 if (row->y + row->height > max_y)
12395 row->visible_height -= row->y + row->height - max_y;
5f5c8ee5 12396 }
a2889657 12397
5f5c8ee5
GM
12398 /* Scroll the current matrix. */
12399 xassert (nrows_scrolled > 0);
12400 rotate_matrix (w->current_matrix,
12401 start_vpos,
12402 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
12403 -nrows_scrolled);
12404
ac90c44f
GM
12405 /* Disable rows not reused. */
12406 for (row -= nrows_scrolled; row < bottom_row; ++row)
12407 row->enabled_p = 0;
12408
5f5c8ee5
GM
12409 /* Adjust window end. A null value of last_text_row means that
12410 the window end is in reused rows which in turn means that
12411 only its vpos can have changed. */
12412 if (last_text_row)
12413 {
12414 w->window_end_bytepos
12415 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12416 w->window_end_pos
12417 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12418 w->window_end_vpos
12419 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12420 }
12421 else
a2889657 12422 {
ac90c44f
GM
12423 w->window_end_vpos
12424 = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 12425 }
2311178e 12426
5f5c8ee5
GM
12427 w->window_end_valid = Qnil;
12428 w->desired_matrix->no_scrolling_p = 1;
12429
12430#if GLYPH_DEBUG
12431 debug_method_add (w, "try_window_reusing_current_matrix 2");
12432#endif
12433 return 1;
a2889657 12434 }
2311178e 12435
5f5c8ee5
GM
12436 return 0;
12437}
a2889657 12438
a2889657 12439
5f5c8ee5
GM
12440\f
12441/************************************************************************
12442 Window redisplay reusing current matrix when buffer has changed
12443 ************************************************************************/
12444
1ec185cb
GM
12445static struct glyph_row *find_last_unchanged_at_beg_row P_ ((struct window *));
12446static struct glyph_row *find_first_unchanged_at_end_row P_ ((struct window *,
5f5c8ee5
GM
12447 int *, int *));
12448static struct glyph_row *
12449find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
12450 struct glyph_row *));
12451
12452
12453/* Return the last row in MATRIX displaying text. If row START is
12454 non-null, start searching with that row. IT gives the dimensions
12455 of the display. Value is null if matrix is empty; otherwise it is
12456 a pointer to the row found. */
12457
12458static struct glyph_row *
12459find_last_row_displaying_text (matrix, it, start)
12460 struct glyph_matrix *matrix;
12461 struct it *it;
12462 struct glyph_row *start;
12463{
12464 struct glyph_row *row, *row_found;
12465
12466 /* Set row_found to the last row in IT->w's current matrix
12467 displaying text. The loop looks funny but think of partially
12468 visible lines. */
12469 row_found = NULL;
12470 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
12471 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
12472 {
12473 xassert (row->enabled_p);
12474 row_found = row;
12475 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
12476 break;
12477 ++row;
a2889657 12478 }
2311178e 12479
5f5c8ee5
GM
12480 return row_found;
12481}
12482
a2889657 12483
5f5c8ee5 12484/* Return the last row in the current matrix of W that is not affected
d43fbe9d
GM
12485 by changes at the start of current_buffer that occurred since W's
12486 current matrix was built. Value is null if no such row exists.
a2889657 12487
d43fbe9d
GM
12488 BEG_UNCHANGED us the number of characters unchanged at the start of
12489 current_buffer. BEG + BEG_UNCHANGED is the buffer position of the
12490 first changed character in current_buffer. Characters at positions <
12491 BEG + BEG_UNCHANGED are at the same buffer positions as they were
12492 when the current matrix was built. */
5f5c8ee5
GM
12493
12494static struct glyph_row *
1ec185cb 12495find_last_unchanged_at_beg_row (w)
5f5c8ee5
GM
12496 struct window *w;
12497{
9142dd5b 12498 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
12499 struct glyph_row *row;
12500 struct glyph_row *row_found = NULL;
12501 int yb = window_text_bottom_y (w);
12502
12503 /* Find the last row displaying unchanged text. */
12504 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
12505 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
12506 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 12507 {
5f5c8ee5
GM
12508 if (/* If row ends before first_changed_pos, it is unchanged,
12509 except in some case. */
12510 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
12511 /* When row ends in ZV and we write at ZV it is not
12512 unchanged. */
12513 && !row->ends_at_zv_p
12514 /* When first_changed_pos is the end of a continued line,
12515 row is not unchanged because it may be no longer
12516 continued. */
12517 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
12518 && row->continued_p))
12519 row_found = row;
12520
12521 /* Stop if last visible row. */
12522 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
12523 break;
2311178e 12524
5f5c8ee5 12525 ++row;
a2889657
JB
12526 }
12527
5f5c8ee5 12528 return row_found;
a2889657 12529}
5f5c8ee5
GM
12530
12531
12532/* Find the first glyph row in the current matrix of W that is not
2311178e 12533 affected by changes at the end of current_buffer since the
d43fbe9d
GM
12534 time W's current matrix was built.
12535
12536 Return in *DELTA the number of chars by which buffer positions in
12537 unchanged text at the end of current_buffer must be adjusted.
2311178e 12538
d43fbe9d
GM
12539 Return in *DELTA_BYTES the corresponding number of bytes.
12540
12541 Value is null if no such row exists, i.e. all rows are affected by
12542 changes. */
2311178e 12543
5f5c8ee5 12544static struct glyph_row *
1ec185cb 12545find_first_unchanged_at_end_row (w, delta, delta_bytes)
5f5c8ee5
GM
12546 struct window *w;
12547 int *delta, *delta_bytes;
a2889657 12548{
5f5c8ee5
GM
12549 struct glyph_row *row;
12550 struct glyph_row *row_found = NULL;
c581d710 12551
5f5c8ee5 12552 *delta = *delta_bytes = 0;
b2a76982 12553
1ec185cb
GM
12554 /* Display must not have been paused, otherwise the current matrix
12555 is not up to date. */
12556 if (NILP (w->window_end_valid))
12557 abort ();
2311178e 12558
1ec185cb 12559 /* A value of window_end_pos >= END_UNCHANGED means that the window
5f5c8ee5
GM
12560 end is in the range of changed text. If so, there is no
12561 unchanged row at the end of W's current matrix. */
9142dd5b 12562 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
12563 return NULL;
12564
12565 /* Set row to the last row in W's current matrix displaying text. */
12566 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
2311178e
TTN
12567
12568 /* If matrix is entirely empty, no unchanged row exists. */
5f5c8ee5
GM
12569 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
12570 {
12571 /* The value of row is the last glyph row in the matrix having a
12572 meaningful buffer position in it. The end position of row
12573 corresponds to window_end_pos. This allows us to translate
12574 buffer positions in the current matrix to current buffer
12575 positions for characters not in changed text. */
12576 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
12577 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
12578 int last_unchanged_pos, last_unchanged_pos_old;
12579 struct glyph_row *first_text_row
12580 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
12581
12582 *delta = Z - Z_old;
12583 *delta_bytes = Z_BYTE - Z_BYTE_old;
12584
12585 /* Set last_unchanged_pos to the buffer position of the last
12586 character in the buffer that has not been changed. Z is the
d43fbe9d
GM
12587 index + 1 of the last character in current_buffer, i.e. by
12588 subtracting END_UNCHANGED we get the index of the last
5f5c8ee5
GM
12589 unchanged character, and we have to add BEG to get its buffer
12590 position. */
9142dd5b 12591 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5 12592 last_unchanged_pos_old = last_unchanged_pos - *delta;
2311178e 12593
5f5c8ee5
GM
12594 /* Search backward from ROW for a row displaying a line that
12595 starts at a minimum position >= last_unchanged_pos_old. */
1ec185cb 12596 for (; row > first_text_row; --row)
5f5c8ee5 12597 {
1ec185cb
GM
12598 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
12599 abort ();
2311178e 12600
5f5c8ee5
GM
12601 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
12602 row_found = row;
5f5c8ee5
GM
12603 }
12604 }
12605
1ec185cb
GM
12606 if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
12607 abort ();
2311178e 12608
5f5c8ee5 12609 return row_found;
c581d710
RS
12610}
12611
c581d710 12612
5f5c8ee5
GM
12613/* Make sure that glyph rows in the current matrix of window W
12614 reference the same glyph memory as corresponding rows in the
12615 frame's frame matrix. This function is called after scrolling W's
12616 current matrix on a terminal frame in try_window_id and
12617 try_window_reusing_current_matrix. */
12618
12619static void
12620sync_frame_with_window_matrix_rows (w)
12621 struct window *w;
c581d710 12622{
5f5c8ee5
GM
12623 struct frame *f = XFRAME (w->frame);
12624 struct glyph_row *window_row, *window_row_end, *frame_row;
12625
12626 /* Preconditions: W must be a leaf window and full-width. Its frame
12627 must have a frame matrix. */
12628 xassert (NILP (w->hchild) && NILP (w->vchild));
12629 xassert (WINDOW_FULL_WIDTH_P (w));
12630 xassert (!FRAME_WINDOW_P (f));
12631
12632 /* If W is a full-width window, glyph pointers in W's current matrix
12633 have, by definition, to be the same as glyph pointers in the
7d4cc828
GM
12634 corresponding frame matrix. Note that frame matrices have no
12635 marginal areas (see build_frame_matrix). */
5f5c8ee5
GM
12636 window_row = w->current_matrix->rows;
12637 window_row_end = window_row + w->current_matrix->nrows;
da8b7f4f 12638 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
5f5c8ee5 12639 while (window_row < window_row_end)
659a218f 12640 {
7d4cc828
GM
12641 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
12642 struct glyph *end = window_row->glyphs[LAST_AREA];
12643
12644 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
12645 frame_row->glyphs[TEXT_AREA] = start;
12646 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
12647 frame_row->glyphs[LAST_AREA] = end;
f002db93
GM
12648
12649 /* Disable frame rows whose corresponding window rows have
12650 been disabled in try_window_id. */
12651 if (!window_row->enabled_p)
12652 frame_row->enabled_p = 0;
2311178e 12653
5f5c8ee5 12654 ++window_row, ++frame_row;
659a218f 12655 }
a2889657 12656}
5f5c8ee5
GM
12657
12658
e037b9ec
GM
12659/* Find the glyph row in window W containing CHARPOS. Consider all
12660 rows between START and END (not inclusive). END null means search
12661 all rows to the end of the display area of W. Value is the row
12662 containing CHARPOS or null. */
12663
0bef35bc 12664struct glyph_row *
0df56f4d 12665row_containing_pos (w, charpos, start, end, dy)
e037b9ec
GM
12666 struct window *w;
12667 int charpos;
12668 struct glyph_row *start, *end;
0df56f4d 12669 int dy;
e037b9ec
GM
12670{
12671 struct glyph_row *row = start;
12672 int last_y;
12673
12674 /* If we happen to start on a header-line, skip that. */
12675 if (row->mode_line_p)
12676 ++row;
2311178e 12677
e037b9ec
GM
12678 if ((end && row >= end) || !row->enabled_p)
12679 return NULL;
2311178e 12680
0df56f4d 12681 last_y = window_text_bottom_y (w) - dy;
2311178e 12682
5cce13dd
RS
12683 while (1)
12684 {
12685 /* Give up if we have gone too far. */
12686 if (end && row >= end)
12687 return NULL;
40a301b3
RS
12688 /* This formerly returned if they were equal.
12689 I think that both quantities are of a "last plus one" type;
12690 if so, when they are equal, the row is within the screen. -- rms. */
12691 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
5cce13dd
RS
12692 return NULL;
12693
12694 /* If it is in this row, return this row. */
12695 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
e037b9ec 12696 || (MATRIX_ROW_END_CHARPOS (row) == charpos
0df56f4d
GM
12697 /* The end position of a row equals the start
12698 position of the next row. If CHARPOS is there, we
12699 would rather display it in the next line, except
12700 when this line ends in ZV. */
12701 && !row->ends_at_zv_p
5cce13dd
RS
12702 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
12703 && charpos >= MATRIX_ROW_START_CHARPOS (row))
12704 return row;
12705 ++row;
12706 }
e037b9ec
GM
12707}
12708
12709
5f5c8ee5
GM
12710/* Try to redisplay window W by reusing its existing display. W's
12711 current matrix must be up to date when this function is called,
12712 i.e. window_end_valid must not be nil.
12713
12714 Value is
12715
12716 1 if display has been updated
12717 0 if otherwise unsuccessful
12718 -1 if redisplay with same window start is known not to succeed
12719
12720 The following steps are performed:
12721
12722 1. Find the last row in the current matrix of W that is not
12723 affected by changes at the start of current_buffer. If no such row
12724 is found, give up.
12725
12726 2. Find the first row in W's current matrix that is not affected by
12727 changes at the end of current_buffer. Maybe there is no such row.
12728
12729 3. Display lines beginning with the row + 1 found in step 1 to the
12730 row found in step 2 or, if step 2 didn't find a row, to the end of
12731 the window.
12732
12733 4. If cursor is not known to appear on the window, give up.
12734
12735 5. If display stopped at the row found in step 2, scroll the
12736 display and current matrix as needed.
12737
12738 6. Maybe display some lines at the end of W, if we must. This can
12739 happen under various circumstances, like a partially visible line
12740 becoming fully visible, or because newly displayed lines are displayed
12741 in smaller font sizes.
12742
12743 7. Update W's window end information. */
12744
12adba34 12745static int
5f5c8ee5 12746try_window_id (w)
12adba34 12747 struct window *w;
12adba34 12748{
5f5c8ee5
GM
12749 struct frame *f = XFRAME (w->frame);
12750 struct glyph_matrix *current_matrix = w->current_matrix;
12751 struct glyph_matrix *desired_matrix = w->desired_matrix;
12752 struct glyph_row *last_unchanged_at_beg_row;
12753 struct glyph_row *first_unchanged_at_end_row;
12754 struct glyph_row *row;
12755 struct glyph_row *bottom_row;
12756 int bottom_vpos;
12757 struct it it;
12758 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
12759 struct text_pos start_pos;
12760 struct run run;
12761 int first_unchanged_at_end_vpos = 0;
12762 struct glyph_row *last_text_row, *last_text_row_at_end;
12763 struct text_pos start;
27d16f05 12764 int first_changed_charpos, last_changed_charpos;
5f5c8ee5 12765
69d1f7c9 12766#if GLYPH_DEBUG
76cb5e06
GM
12767 if (inhibit_try_window_id)
12768 return 0;
12769#endif
12770
27d16f05
GM
12771 /* This is handy for debugging. */
12772#if 0
12773#define GIVE_UP(X) \
12774 do { \
12775 fprintf (stderr, "try_window_id give up %d\n", (X)); \
12776 return 0; \
12777 } while (0)
12778#else
62397849 12779#define GIVE_UP(X) return 0
27d16f05 12780#endif
2311178e 12781
5f5c8ee5
GM
12782 SET_TEXT_POS_FROM_MARKER (start, w->start);
12783
27d16f05
GM
12784 /* Don't use this for mini-windows because these can show
12785 messages and mini-buffers, and we don't handle that here. */
12786 if (MINI_WINDOW_P (w))
12787 GIVE_UP (1);
2311178e 12788
27d16f05 12789 /* This flag is used to prevent redisplay optimizations. */
5fb96e96 12790 if (windows_or_buffers_changed || cursor_type_changed)
27d16f05 12791 GIVE_UP (2);
2311178e 12792
c62c1bb5
RS
12793 /* Verify that narrowing has not changed.
12794 Also verify that we were not told to prevent redisplay optimizations.
12795 It would be nice to further
27d16f05 12796 reduce the number of cases where this prevents try_window_id. */
c62c1bb5
RS
12797 if (current_buffer->clip_changed
12798 || current_buffer->prevent_redisplay_optimizations_p)
27d16f05
GM
12799 GIVE_UP (3);
12800
12801 /* Window must either use window-based redisplay or be full width. */
12802 if (!FRAME_WINDOW_P (f)
12803 && (!line_ins_del_ok
12804 || !WINDOW_FULL_WIDTH_P (w)))
12805 GIVE_UP (4);
5f5c8ee5 12806
f5376658 12807 /* Give up if point is not known NOT to appear in W. */
27d16f05
GM
12808 if (PT < CHARPOS (start))
12809 GIVE_UP (5);
12810
12811 /* Another way to prevent redisplay optimizations. */
12812 if (XFASTINT (w->last_modified) == 0)
12813 GIVE_UP (6);
2311178e 12814
f5376658 12815 /* Verify that window is not hscrolled. */
27d16f05
GM
12816 if (XFASTINT (w->hscroll) != 0)
12817 GIVE_UP (7);
2311178e 12818
f5376658 12819 /* Verify that display wasn't paused. */
27d16f05
GM
12820 if (NILP (w->window_end_valid))
12821 GIVE_UP (8);
2311178e 12822
27d16f05
GM
12823 /* Can't use this if highlighting a region because a cursor movement
12824 will do more than just set the cursor. */
12825 if (!NILP (Vtransient_mark_mode)
12826 && !NILP (current_buffer->mark_active))
12827 GIVE_UP (9);
12828
12829 /* Likewise if highlighting trailing whitespace. */
12830 if (!NILP (Vshow_trailing_whitespace))
12831 GIVE_UP (11);
2311178e 12832
27d16f05
GM
12833 /* Likewise if showing a region. */
12834 if (!NILP (w->region_showing))
12835 GIVE_UP (10);
2311178e 12836
27d16f05
GM
12837 /* Can use this if overlay arrow position and or string have changed. */
12838 if (!EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
12839 || !EQ (last_arrow_string, Voverlay_arrow_string))
12840 GIVE_UP (12);
12841
2311178e 12842
5f5c8ee5
GM
12843 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
12844 only if buffer has really changed. The reason is that the gap is
12845 initially at Z for freshly visited files. The code below would
12846 set end_unchanged to 0 in that case. */
28ee91c0
GM
12847 if (MODIFF > SAVE_MODIFF
12848 /* This seems to happen sometimes after saving a buffer. */
12849 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
5f5c8ee5 12850 {
9142dd5b
GM
12851 if (GPT - BEG < BEG_UNCHANGED)
12852 BEG_UNCHANGED = GPT - BEG;
12853 if (Z - GPT < END_UNCHANGED)
12854 END_UNCHANGED = Z - GPT;
5f5c8ee5 12855 }
bf9249e3 12856
27d16f05
GM
12857 /* The position of the first and last character that has been changed. */
12858 first_changed_charpos = BEG + BEG_UNCHANGED;
12859 last_changed_charpos = Z - END_UNCHANGED;
12860
5f5c8ee5
GM
12861 /* If window starts after a line end, and the last change is in
12862 front of that newline, then changes don't affect the display.
f2d86d7a
GM
12863 This case happens with stealth-fontification. Note that although
12864 the display is unchanged, glyph positions in the matrix have to
12865 be adjusted, of course. */
5f5c8ee5 12866 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
27d16f05 12867 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
e60f4527 12868 && ((last_changed_charpos < CHARPOS (start)
27d16f05 12869 && CHARPOS (start) == BEGV)
e60f4527 12870 || (last_changed_charpos < CHARPOS (start) - 1
27d16f05
GM
12871 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
12872 {
12873 int Z_old, delta, Z_BYTE_old, delta_bytes;
12874 struct glyph_row *r0;
12875
12876 /* Compute how many chars/bytes have been added to or removed
12877 from the buffer. */
12878 Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
12879 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
12880 delta = Z - Z_old;
12881 delta_bytes = Z_BYTE - Z_BYTE_old;
2311178e 12882
27d16f05
GM
12883 /* Give up if PT is not in the window. Note that it already has
12884 been checked at the start of try_window_id that PT is not in
12885 front of the window start. */
12886 if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
12887 GIVE_UP (13);
12888
12889 /* If window start is unchanged, we can reuse the whole matrix
12890 as is, after adjusting glyph positions. No need to compute
12891 the window end again, since its offset from Z hasn't changed. */
12892 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
12893 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
2d031b89
AS
12894 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes
12895 /* PT must not be in a partially visible line. */
12896 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + delta
12897 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
27d16f05
GM
12898 {
12899 /* Adjust positions in the glyph matrix. */
12900 if (delta || delta_bytes)
12901 {
12902 struct glyph_row *r1
12903 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
12904 increment_matrix_positions (w->current_matrix,
12905 MATRIX_ROW_VPOS (r0, current_matrix),
12906 MATRIX_ROW_VPOS (r1, current_matrix),
12907 delta, delta_bytes);
12908 }
2311178e 12909
27d16f05 12910 /* Set the cursor. */
0df56f4d 12911 row = row_containing_pos (w, PT, r0, NULL, 0);
59adf8e8
KS
12912 if (row)
12913 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
40a301b3
RS
12914 else
12915 abort ();
27d16f05
GM
12916 return 1;
12917 }
5f5c8ee5
GM
12918 }
12919
27d16f05 12920 /* Handle the case that changes are all below what is displayed in
33ea6c4d 12921 the window, and that PT is in the window. This shortcut cannot
2b9c25e0
GM
12922 be taken if ZV is visible in the window, and text has been added
12923 there that is visible in the window. */
12924 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
33ea6c4d
GM
12925 /* ZV is not visible in the window, or there are no
12926 changes at ZV, actually. */
12927 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
12928 || first_changed_charpos == last_changed_charpos))
5f5c8ee5 12929 {
27d16f05 12930 struct glyph_row *r0;
ef121659 12931
27d16f05
GM
12932 /* Give up if PT is not in the window. Note that it already has
12933 been checked at the start of try_window_id that PT is not in
12934 front of the window start. */
12935 if (PT >= MATRIX_ROW_END_CHARPOS (row))
12936 GIVE_UP (14);
12937
12938 /* If window start is unchanged, we can reuse the whole matrix
12939 as is, without changing glyph positions since no text has
12940 been added/removed in front of the window end. */
12941 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
2d031b89
AS
12942 if (TEXT_POS_EQUAL_P (start, r0->start.pos)
12943 /* PT must not be in a partially visible line. */
12944 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
12945 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
27d16f05
GM
12946 {
12947 /* We have to compute the window end anew since text
12948 can have been added/removed after it. */
12949 w->window_end_pos
12950 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
12951 w->window_end_bytepos
12952 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
12953
12954 /* Set the cursor. */
0df56f4d 12955 row = row_containing_pos (w, PT, r0, NULL, 0);
59adf8e8
KS
12956 if (row)
12957 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
40a301b3
RS
12958 else
12959 abort ();
27d16f05
GM
12960 return 2;
12961 }
5f5c8ee5
GM
12962 }
12963
2b9c25e0 12964 /* Give up if window start is in the changed area.
2311178e 12965
2b9c25e0
GM
12966 The condition used to read
12967
12968 (BEG_UNCHANGED + END_UNCHANGED != Z - BEG && ...)
12969
12970 but why that was tested escapes me at the moment. */
12971 if (CHARPOS (start) >= first_changed_charpos
27d16f05
GM
12972 && CHARPOS (start) <= last_changed_charpos)
12973 GIVE_UP (15);
2311178e 12974
f5376658
RS
12975 /* Check that window start agrees with the start of the first glyph
12976 row in its current matrix. Check this after we know the window
12977 start is not in changed text, otherwise positions would not be
12978 comparable. */
27d16f05 12979 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
5f5c8ee5 12980 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
27d16f05 12981 GIVE_UP (16);
5f5c8ee5 12982
23e8bd86
GM
12983 /* Give up if the window ends in strings. Overlay strings
12984 at the end are difficult to handle, so don't try. */
12985 row = MATRIX_ROW (current_matrix, XFASTINT (w->window_end_vpos));
12986 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
12987 GIVE_UP (20);
12988
5f5c8ee5
GM
12989 /* Compute the position at which we have to start displaying new
12990 lines. Some of the lines at the top of the window might be
12991 reusable because they are not displaying changed text. Find the
12992 last row in W's current matrix not affected by changes at the
12993 start of current_buffer. Value is null if changes start in the
12994 first line of window. */
1ec185cb 12995 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
5f5c8ee5
GM
12996 if (last_unchanged_at_beg_row)
12997 {
67f1cf4c
GM
12998 /* Avoid starting to display in the moddle of a character, a TAB
12999 for instance. This is easier than to set up the iterator
13000 exactly, and it's not a frequent case, so the additional
13001 effort wouldn't really pay off. */
e74fb0f7
GM
13002 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
13003 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
67f1cf4c
GM
13004 && last_unchanged_at_beg_row > w->current_matrix->rows)
13005 --last_unchanged_at_beg_row;
13006
13007 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
27d16f05 13008 GIVE_UP (17);
47d57b22
GM
13009
13010 if (init_to_row_end (&it, w, last_unchanged_at_beg_row) == 0)
13011 GIVE_UP (18);
5f5c8ee5 13012 start_pos = it.current.pos;
2311178e 13013
5f5c8ee5
GM
13014 /* Start displaying new lines in the desired matrix at the same
13015 vpos we would use in the current matrix, i.e. below
13016 last_unchanged_at_beg_row. */
13017 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
13018 current_matrix);
13019 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
13020 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
13021
13022 xassert (it.hpos == 0 && it.current_x == 0);
13023 }
13024 else
13025 {
13026 /* There are no reusable lines at the start of the window.
13027 Start displaying in the first line. */
13028 start_display (&it, w, start);
13029 start_pos = it.current.pos;
13030 }
13031
5f5c8ee5
GM
13032 /* Find the first row that is not affected by changes at the end of
13033 the buffer. Value will be null if there is no unchanged row, in
13034 which case we must redisplay to the end of the window. delta
13035 will be set to the value by which buffer positions beginning with
13036 first_unchanged_at_end_row have to be adjusted due to text
13037 changes. */
13038 first_unchanged_at_end_row
1ec185cb 13039 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
5f5c8ee5
GM
13040 IF_DEBUG (debug_delta = delta);
13041 IF_DEBUG (debug_delta_bytes = delta_bytes);
2311178e 13042
5f5c8ee5
GM
13043 /* Set stop_pos to the buffer position up to which we will have to
13044 display new lines. If first_unchanged_at_end_row != NULL, this
13045 is the buffer position of the start of the line displayed in that
13046 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
13047 that we don't stop at a buffer position. */
13048 stop_pos = 0;
13049 if (first_unchanged_at_end_row)
13050 {
13051 xassert (last_unchanged_at_beg_row == NULL
13052 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
2311178e 13053
5f5c8ee5
GM
13054 /* If this is a continuation line, move forward to the next one
13055 that isn't. Changes in lines above affect this line.
13056 Caution: this may move first_unchanged_at_end_row to a row
13057 not displaying text. */
13058 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
13059 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
13060 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
13061 < it.last_visible_y))
13062 ++first_unchanged_at_end_row;
13063
13064 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
13065 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
13066 >= it.last_visible_y))
13067 first_unchanged_at_end_row = NULL;
13068 else
13069 {
13070 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
13071 + delta);
13072 first_unchanged_at_end_vpos
13073 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 13074 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
13075 }
13076 }
13077 else if (last_unchanged_at_beg_row == NULL)
23e8bd86 13078 GIVE_UP (19);
5f5c8ee5
GM
13079
13080
13081#if GLYPH_DEBUG
2311178e 13082
5f5c8ee5
GM
13083 /* Either there is no unchanged row at the end, or the one we have
13084 now displays text. This is a necessary condition for the window
13085 end pos calculation at the end of this function. */
13086 xassert (first_unchanged_at_end_row == NULL
13087 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
2311178e 13088
5f5c8ee5
GM
13089 debug_last_unchanged_at_beg_vpos
13090 = (last_unchanged_at_beg_row
13091 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
13092 : -1);
13093 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
2311178e 13094
5f5c8ee5
GM
13095#endif /* GLYPH_DEBUG != 0 */
13096
2311178e 13097
5f5c8ee5
GM
13098 /* Display new lines. Set last_text_row to the last new line
13099 displayed which has text on it, i.e. might end up as being the
13100 line where the window_end_vpos is. */
13101 w->cursor.vpos = -1;
13102 last_text_row = NULL;
13103 overlay_arrow_seen = 0;
13104 while (it.current_y < it.last_visible_y
13105 && !fonts_changed_p
13106 && (first_unchanged_at_end_row == NULL
13107 || IT_CHARPOS (it) < stop_pos))
13108 {
13109 if (display_line (&it))
13110 last_text_row = it.glyph_row - 1;
13111 }
13112
13113 if (fonts_changed_p)
13114 return -1;
13115
13116
13117 /* Compute differences in buffer positions, y-positions etc. for
13118 lines reused at the bottom of the window. Compute what we can
13119 scroll. */
ca42b2e8
GM
13120 if (first_unchanged_at_end_row
13121 /* No lines reused because we displayed everything up to the
13122 bottom of the window. */
13123 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
13124 {
13125 dvpos = (it.vpos
13126 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
13127 current_matrix));
13128 dy = it.current_y - first_unchanged_at_end_row->y;
13129 run.current_y = first_unchanged_at_end_row->y;
13130 run.desired_y = run.current_y + dy;
13131 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
13132 }
13133 else
ca42b2e8
GM
13134 {
13135 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
13136 first_unchanged_at_end_row = NULL;
13137 }
5f5c8ee5
GM
13138 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
13139
8f8ba186 13140
5f5c8ee5
GM
13141 /* Find the cursor if not already found. We have to decide whether
13142 PT will appear on this window (it sometimes doesn't, but this is
13143 not a very frequent case.) This decision has to be made before
13144 the current matrix is altered. A value of cursor.vpos < 0 means
13145 that PT is either in one of the lines beginning at
13146 first_unchanged_at_end_row or below the window. Don't care for
13147 lines that might be displayed later at the window end; as
13148 mentioned, this is not a frequent case. */
13149 if (w->cursor.vpos < 0)
13150 {
5f5c8ee5
GM
13151 /* Cursor in unchanged rows at the top? */
13152 if (PT < CHARPOS (start_pos)
13153 && last_unchanged_at_beg_row)
13154 {
e037b9ec
GM
13155 row = row_containing_pos (w, PT,
13156 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
0df56f4d 13157 last_unchanged_at_beg_row + 1, 0);
bfe0ee88
GM
13158 if (row)
13159 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
13160 }
13161
13162 /* Start from first_unchanged_at_end_row looking for PT. */
13163 else if (first_unchanged_at_end_row)
13164 {
e037b9ec 13165 row = row_containing_pos (w, PT - delta,
0df56f4d 13166 first_unchanged_at_end_row, NULL, 0);
e037b9ec 13167 if (row)
468155d7
GM
13168 set_cursor_from_row (w, row, w->current_matrix, delta,
13169 delta_bytes, dy, dvpos);
5f5c8ee5
GM
13170 }
13171
13172 /* Give up if cursor was not found. */
13173 if (w->cursor.vpos < 0)
13174 {
13175 clear_glyph_matrix (w->desired_matrix);
13176 return -1;
13177 }
13178 }
2311178e 13179
5f5c8ee5
GM
13180 /* Don't let the cursor end in the scroll margins. */
13181 {
13182 int this_scroll_margin, cursor_height;
2311178e 13183
5f5c8ee5 13184 this_scroll_margin = max (0, scroll_margin);
da8b7f4f
KS
13185 this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
13186 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5f5c8ee5 13187 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
2311178e 13188
5f5c8ee5
GM
13189 if ((w->cursor.y < this_scroll_margin
13190 && CHARPOS (start) > BEGV)
13191 /* Don't take scroll margin into account at the bottom because
13192 old redisplay didn't do it either. */
13193 || w->cursor.y + cursor_height > it.last_visible_y)
13194 {
13195 w->cursor.vpos = -1;
13196 clear_glyph_matrix (w->desired_matrix);
13197 return -1;
13198 }
13199 }
13200
13201 /* Scroll the display. Do it before changing the current matrix so
13202 that xterm.c doesn't get confused about where the cursor glyph is
13203 found. */
fa77249f 13204 if (dy && run.height)
5f5c8ee5
GM
13205 {
13206 update_begin (f);
2311178e 13207
5f5c8ee5
GM
13208 if (FRAME_WINDOW_P (f))
13209 {
13210 rif->update_window_begin_hook (w);
fa3c6b4d 13211 rif->clear_window_mouse_face (w);
5f5c8ee5 13212 rif->scroll_run_hook (w, &run);
64d1e7d3 13213 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
13214 }
13215 else
13216 {
13217 /* Terminal frame. In this case, dvpos gives the number of
13218 lines to scroll by; dvpos < 0 means scroll up. */
13219 int first_unchanged_at_end_vpos
13220 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
da8b7f4f
KS
13221 int from = WINDOW_TOP_EDGE_LINE (w) + first_unchanged_at_end_vpos;
13222 int end = (WINDOW_TOP_EDGE_LINE (w)
522ed7fb
GM
13223 + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
13224 + window_internal_height (w));
2311178e 13225
5f5c8ee5
GM
13226 /* Perform the operation on the screen. */
13227 if (dvpos > 0)
13228 {
13229 /* Scroll last_unchanged_at_beg_row to the end of the
13230 window down dvpos lines. */
13231 set_terminal_window (end);
13232
13233 /* On dumb terminals delete dvpos lines at the end
13234 before inserting dvpos empty lines. */
13235 if (!scroll_region_ok)
13236 ins_del_lines (end - dvpos, -dvpos);
13237
13238 /* Insert dvpos empty lines in front of
13239 last_unchanged_at_beg_row. */
13240 ins_del_lines (from, dvpos);
13241 }
13242 else if (dvpos < 0)
13243 {
13244 /* Scroll up last_unchanged_at_beg_vpos to the end of
13245 the window to last_unchanged_at_beg_vpos - |dvpos|. */
13246 set_terminal_window (end);
13247
13248 /* Delete dvpos lines in front of
13249 last_unchanged_at_beg_vpos. ins_del_lines will set
13250 the cursor to the given vpos and emit |dvpos| delete
13251 line sequences. */
13252 ins_del_lines (from + dvpos, dvpos);
13253
13254 /* On a dumb terminal insert dvpos empty lines at the
13255 end. */
13256 if (!scroll_region_ok)
13257 ins_del_lines (end + dvpos, -dvpos);
13258 }
2311178e 13259
5f5c8ee5
GM
13260 set_terminal_window (0);
13261 }
2311178e 13262
5f5c8ee5
GM
13263 update_end (f);
13264 }
13265
ca42b2e8
GM
13266 /* Shift reused rows of the current matrix to the right position.
13267 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
13268 text. */
13269 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
13270 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
13271 if (dvpos < 0)
13272 {
13273 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
13274 bottom_vpos, dvpos);
13275 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
13276 bottom_vpos, 0);
13277 }
13278 else if (dvpos > 0)
13279 {
13280 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
13281 bottom_vpos, dvpos);
13282 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
13283 first_unchanged_at_end_vpos + dvpos, 0);
13284 }
13285
13286 /* For frame-based redisplay, make sure that current frame and window
13287 matrix are in sync with respect to glyph memory. */
13288 if (!FRAME_WINDOW_P (f))
13289 sync_frame_with_window_matrix_rows (w);
13290
13291 /* Adjust buffer positions in reused rows. */
13292 if (delta)
f2d86d7a
GM
13293 increment_matrix_positions (current_matrix,
13294 first_unchanged_at_end_vpos + dvpos,
13295 bottom_vpos, delta, delta_bytes);
5f5c8ee5
GM
13296
13297 /* Adjust Y positions. */
13298 if (dy)
13299 shift_glyph_matrix (w, current_matrix,
13300 first_unchanged_at_end_vpos + dvpos,
13301 bottom_vpos, dy);
13302
13303 if (first_unchanged_at_end_row)
13304 first_unchanged_at_end_row += dvpos;
13305
13306 /* If scrolling up, there may be some lines to display at the end of
13307 the window. */
13308 last_text_row_at_end = NULL;
13309 if (dy < 0)
13310 {
9c6ba6d1
GM
13311 /* Scrolling up can leave for example a partially visible line
13312 at the end of the window to be redisplayed. */
5f5c8ee5
GM
13313 /* Set last_row to the glyph row in the current matrix where the
13314 window end line is found. It has been moved up or down in
13315 the matrix by dvpos. */
13316 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
13317 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
13318
13319 /* If last_row is the window end line, it should display text. */
13320 xassert (last_row->displays_text_p);
13321
13322 /* If window end line was partially visible before, begin
13323 displaying at that line. Otherwise begin displaying with the
13324 line following it. */
13325 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
13326 {
13327 init_to_row_start (&it, w, last_row);
13328 it.vpos = last_vpos;
13329 it.current_y = last_row->y;
13330 }
13331 else
13332 {
13333 init_to_row_end (&it, w, last_row);
13334 it.vpos = 1 + last_vpos;
13335 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
13336 ++last_row;
13337 }
12adba34 13338
23e8bd86
GM
13339 /* We may start in a continuation line. If so, we have to
13340 get the right continuation_lines_width and current_x. */
13341 it.continuation_lines_width = last_row->continuation_lines_width;
13342 it.hpos = it.current_x = 0;
2311178e 13343
23e8bd86
GM
13344 /* Display the rest of the lines at the window end. */
13345 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
13346 while (it.current_y < it.last_visible_y
13347 && !fonts_changed_p)
5f5c8ee5 13348 {
23e8bd86
GM
13349 /* Is it always sure that the display agrees with lines in
13350 the current matrix? I don't think so, so we mark rows
13351 displayed invalid in the current matrix by setting their
13352 enabled_p flag to zero. */
13353 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
13354 if (display_line (&it))
13355 last_text_row_at_end = it.glyph_row - 1;
5f5c8ee5
GM
13356 }
13357 }
12adba34 13358
5f5c8ee5
GM
13359 /* Update window_end_pos and window_end_vpos. */
13360 if (first_unchanged_at_end_row
13361 && first_unchanged_at_end_row->y < it.last_visible_y
13362 && !last_text_row_at_end)
13363 {
13364 /* Window end line if one of the preserved rows from the current
13365 matrix. Set row to the last row displaying text in current
13366 matrix starting at first_unchanged_at_end_row, after
13367 scrolling. */
13368 xassert (first_unchanged_at_end_row->displays_text_p);
13369 row = find_last_row_displaying_text (w->current_matrix, &it,
13370 first_unchanged_at_end_row);
13371 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
2311178e 13372
ac90c44f 13373 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
5f5c8ee5 13374 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
ac90c44f
GM
13375 w->window_end_vpos
13376 = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
23fca891 13377 xassert (w->window_end_bytepos >= 0);
0416532f 13378 IF_DEBUG (debug_method_add (w, "A"));
5f5c8ee5
GM
13379 }
13380 else if (last_text_row_at_end)
13381 {
ac90c44f
GM
13382 w->window_end_pos
13383 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
5f5c8ee5
GM
13384 w->window_end_bytepos
13385 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
ac90c44f
GM
13386 w->window_end_vpos
13387 = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
23fca891 13388 xassert (w->window_end_bytepos >= 0);
0416532f 13389 IF_DEBUG (debug_method_add (w, "B"));
5f5c8ee5
GM
13390 }
13391 else if (last_text_row)
13392 {
13393 /* We have displayed either to the end of the window or at the
13394 end of the window, i.e. the last row with text is to be found
13395 in the desired matrix. */
ac90c44f
GM
13396 w->window_end_pos
13397 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
5f5c8ee5
GM
13398 w->window_end_bytepos
13399 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
13400 w->window_end_vpos
13401 = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
23fca891 13402 xassert (w->window_end_bytepos >= 0);
5f5c8ee5
GM
13403 }
13404 else if (first_unchanged_at_end_row == NULL
13405 && last_text_row == NULL
13406 && last_text_row_at_end == NULL)
13407 {
13408 /* Displayed to end of window, but no line containing text was
13409 displayed. Lines were deleted at the end of the window. */
0416532f
GM
13410 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
13411 int vpos = XFASTINT (w->window_end_vpos);
13412 struct glyph_row *current_row = current_matrix->rows + vpos;
13413 struct glyph_row *desired_row = desired_matrix->rows + vpos;
13414
13415 for (row = NULL;
13416 row == NULL && vpos >= first_vpos;
13417 --vpos, --current_row, --desired_row)
13418 {
13419 if (desired_row->enabled_p)
13420 {
13421 if (desired_row->displays_text_p)
13422 row = desired_row;
13423 }
13424 else if (current_row->displays_text_p)
13425 row = current_row;
13426 }
12adba34 13427
0416532f 13428 xassert (row != NULL);
d88a79d4 13429 w->window_end_vpos = make_number (vpos + 1);
8c56a983
GM
13430 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
13431 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
23fca891 13432 xassert (w->window_end_bytepos >= 0);
0416532f 13433 IF_DEBUG (debug_method_add (w, "C"));
5f5c8ee5
GM
13434 }
13435 else
13436 abort ();
ac90c44f 13437
8cdb267e
GM
13438#if 0 /* This leads to problems, for instance when the cursor is
13439 at ZV, and the cursor line displays no text. */
ac90c44f
GM
13440 /* Disable rows below what's displayed in the window. This makes
13441 debugging easier. */
13442 enable_glyph_matrix_rows (current_matrix,
13443 XFASTINT (w->window_end_vpos) + 1,
13444 bottom_vpos, 0);
8cdb267e 13445#endif
23e8bd86 13446
5f5c8ee5
GM
13447 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
13448 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 13449
5f5c8ee5
GM
13450 /* Record that display has not been completed. */
13451 w->window_end_valid = Qnil;
13452 w->desired_matrix->no_scrolling_p = 1;
ef121659 13453 return 3;
27d16f05
GM
13454
13455#undef GIVE_UP
12adba34 13456}
0f9c0ff0 13457
a2889657 13458
5f5c8ee5
GM
13459\f
13460/***********************************************************************
13461 More debugging support
13462 ***********************************************************************/
a2889657 13463
5f5c8ee5 13464#if GLYPH_DEBUG
a2889657 13465
eaaa65b0 13466void dump_glyph_row P_ ((struct glyph_row *, int, int));
9ab436b9 13467void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
e187cf71 13468void dump_glyph P_ ((struct glyph_row *, struct glyph *, int));
1c9241f5 13469
31b24551 13470
9ab436b9 13471/* Dump the contents of glyph matrix MATRIX on stderr.
ca26e1c8 13472
9ab436b9
GM
13473 GLYPHS 0 means don't show glyph contents.
13474 GLYPHS 1 means show glyphs in short form
13475 GLYPHS > 1 means show glyphs in long form. */
13476
13477void
13478dump_glyph_matrix (matrix, glyphs)
5f5c8ee5 13479 struct glyph_matrix *matrix;
9ab436b9 13480 int glyphs;
5f5c8ee5 13481{
efc63ef0 13482 int i;
5f5c8ee5 13483 for (i = 0; i < matrix->nrows; ++i)
eaaa65b0 13484 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
5f5c8ee5 13485}
31b24551 13486
68a37fa8 13487
e187cf71
GM
13488/* Dump contents of glyph GLYPH to stderr. ROW and AREA are
13489 the glyph row and area where the glyph comes from. */
13490
13491void
13492dump_glyph (row, glyph, area)
13493 struct glyph_row *row;
13494 struct glyph *glyph;
13495 int area;
13496{
13497 if (glyph->type == CHAR_GLYPH)
13498 {
13499 fprintf (stderr,
13500 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
13501 glyph - row->glyphs[TEXT_AREA],
13502 'C',
13503 glyph->charpos,
13504 (BUFFERP (glyph->object)
13505 ? 'B'
13506 : (STRINGP (glyph->object)
13507 ? 'S'
13508 : '-')),
13509 glyph->pixel_width,
13510 glyph->u.ch,
13511 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
13512 ? glyph->u.ch
13513 : '.'),
13514 glyph->face_id,
13515 glyph->left_box_line_p,
13516 glyph->right_box_line_p);
13517 }
13518 else if (glyph->type == STRETCH_GLYPH)
13519 {
13520 fprintf (stderr,
13521 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
13522 glyph - row->glyphs[TEXT_AREA],
13523 'S',
13524 glyph->charpos,
13525 (BUFFERP (glyph->object)
13526 ? 'B'
13527 : (STRINGP (glyph->object)
13528 ? 'S'
13529 : '-')),
13530 glyph->pixel_width,
13531 0,
13532 '.',
13533 glyph->face_id,
13534 glyph->left_box_line_p,
13535 glyph->right_box_line_p);
13536 }
13537 else if (glyph->type == IMAGE_GLYPH)
13538 {
13539 fprintf (stderr,
13540 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
13541 glyph - row->glyphs[TEXT_AREA],
13542 'I',
13543 glyph->charpos,
13544 (BUFFERP (glyph->object)
13545 ? 'B'
13546 : (STRINGP (glyph->object)
13547 ? 'S'
13548 : '-')),
13549 glyph->pixel_width,
13550 glyph->u.img_id,
13551 '.',
13552 glyph->face_id,
13553 glyph->left_box_line_p,
13554 glyph->right_box_line_p);
13555 }
13556}
13557
13558
5f5c8ee5 13559/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
9ab436b9
GM
13560 GLYPHS 0 means don't show glyph contents.
13561 GLYPHS 1 means show glyphs in short form
13562 GLYPHS > 1 means show glyphs in long form. */
a2889657 13563
5f5c8ee5 13564void
eaaa65b0
GM
13565dump_glyph_row (row, vpos, glyphs)
13566 struct glyph_row *row;
9ab436b9 13567 int vpos, glyphs;
5f5c8ee5 13568{
9ab436b9
GM
13569 if (glyphs != 1)
13570 {
b94c0d9c 13571 fprintf (stderr, "Row Start End Used oEI><O\\CTZFesm X Y W H V A P\n");
9ab436b9 13572 fprintf (stderr, "=======================================================================\n");
2311178e 13573
0ad38729 13574 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d\
33ea6c4d 13575%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
eaaa65b0 13576 vpos,
9ab436b9
GM
13577 MATRIX_ROW_START_CHARPOS (row),
13578 MATRIX_ROW_END_CHARPOS (row),
13579 row->used[TEXT_AREA],
13580 row->contains_overlapping_glyphs_p,
13581 row->enabled_p,
9ab436b9
GM
13582 row->truncated_on_left_p,
13583 row->truncated_on_right_p,
13584 row->overlay_arrow_p,
13585 row->continued_p,
13586 MATRIX_ROW_CONTINUATION_LINE_P (row),
13587 row->displays_text_p,
13588 row->ends_at_zv_p,
13589 row->fill_line_p,
13590 row->ends_in_middle_of_char_p,
13591 row->starts_in_middle_of_char_p,
b94c0d9c 13592 row->mouse_face_p,
9ab436b9
GM
13593 row->x,
13594 row->y,
13595 row->pixel_width,
13596 row->height,
13597 row->visible_height,
13598 row->ascent,
13599 row->phys_ascent);
33ea6c4d
GM
13600 fprintf (stderr, "%9d %5d\t%5d\n", row->start.overlay_string_index,
13601 row->end.overlay_string_index,
13602 row->continuation_lines_width);
9ab436b9
GM
13603 fprintf (stderr, "%9d %5d\n",
13604 CHARPOS (row->start.string_pos),
13605 CHARPOS (row->end.string_pos));
13606 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
13607 row->end.dpvec_index);
13608 }
2311178e 13609
9ab436b9 13610 if (glyphs > 1)
bd66d1ba 13611 {
e187cf71
GM
13612 int area;
13613
13614 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
13615 {
091f8878
GM
13616 struct glyph *glyph = row->glyphs[area];
13617 struct glyph *glyph_end = glyph + row->used[area];
2311178e 13618
e187cf71 13619 /* Glyph for a line end in text. */
091f8878 13620 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
e187cf71 13621 ++glyph_end;
2311178e 13622
e187cf71
GM
13623 if (glyph < glyph_end)
13624 fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
2311178e 13625
e187cf71
GM
13626 for (; glyph < glyph_end; ++glyph)
13627 dump_glyph (row, glyph, area);
f7b4b63a 13628 }
f4faa47c 13629 }
9ab436b9
GM
13630 else if (glyphs == 1)
13631 {
e187cf71 13632 int area;
9ab436b9 13633
e187cf71 13634 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
9ab436b9 13635 {
e187cf71
GM
13636 char *s = (char *) alloca (row->used[area] + 1);
13637 int i;
13638
13639 for (i = 0; i < row->used[area]; ++i)
13640 {
13641 struct glyph *glyph = row->glyphs[area] + i;
13642 if (glyph->type == CHAR_GLYPH
13643 && glyph->u.ch < 0x80
13644 && glyph->u.ch >= ' ')
13645 s[i] = glyph->u.ch;
13646 else
13647 s[i] = '.';
13648 }
2311178e 13649
e187cf71
GM
13650 s[i] = '\0';
13651 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
13652 }
9ab436b9 13653 }
5f5c8ee5 13654}
f4faa47c 13655
a2889657 13656
5f5c8ee5
GM
13657DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
13658 Sdump_glyph_matrix, 0, 1, "p",
7ee72033 13659 doc: /* Dump the current matrix of the selected window to stderr.
228299fa
GM
13660Shows contents of glyph row structures. With non-nil
13661parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show
7ee72033
MB
13662glyphs in short form, otherwise show glyphs in long form. */)
13663 (glyphs)
9ab436b9 13664 Lisp_Object glyphs;
5f5c8ee5
GM
13665{
13666 struct window *w = XWINDOW (selected_window);
13667 struct buffer *buffer = XBUFFER (w->buffer);
13668
13669 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
13670 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
13671 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
13672 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
13673 fprintf (stderr, "=============================================\n");
9ab436b9
GM
13674 dump_glyph_matrix (w->current_matrix,
13675 NILP (glyphs) ? 0 : XINT (glyphs));
5f5c8ee5
GM
13676 return Qnil;
13677}
1c2250c2 13678
1fca3fae 13679
7d4cc828
GM
13680DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
13681 Sdump_frame_glyph_matrix, 0, 0, "", doc: /* */)
13682 ()
13683{
13684 struct frame *f = XFRAME (selected_frame);
13685 dump_glyph_matrix (f->current_matrix, 1);
13686 return Qnil;
13687}
13688
13689
e9abc296 13690DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "",
7ee72033 13691 doc: /* Dump glyph row ROW to stderr.
228299fa
GM
13692GLYPH 0 means don't dump glyphs.
13693GLYPH 1 means dump glyphs in short form.
7ee72033
MB
13694GLYPH > 1 or omitted means dump glyphs in long form. */)
13695 (row, glyphs)
e9abc296 13696 Lisp_Object row, glyphs;
5f5c8ee5 13697{
eaaa65b0
GM
13698 struct glyph_matrix *matrix;
13699 int vpos;
2311178e 13700
b7826503 13701 CHECK_NUMBER (row);
eaaa65b0
GM
13702 matrix = XWINDOW (selected_window)->current_matrix;
13703 vpos = XINT (row);
13704 if (vpos >= 0 && vpos < matrix->nrows)
13705 dump_glyph_row (MATRIX_ROW (matrix, vpos),
13706 vpos,
13707 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
13708 return Qnil;
13709}
1fca3fae 13710
67481ae5 13711
b94c0d9c 13712DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "",
c2552f79 13713 doc: /* Dump glyph row ROW of the tool-bar of the current frame to stderr.
228299fa
GM
13714GLYPH 0 means don't dump glyphs.
13715GLYPH 1 means dump glyphs in short form.
7ee72033
MB
13716GLYPH > 1 or omitted means dump glyphs in long form. */)
13717 (row, glyphs)
b94c0d9c 13718 Lisp_Object row, glyphs;
5f5c8ee5 13719{
886bd6f2 13720 struct frame *sf = SELECTED_FRAME ();
eaaa65b0
GM
13721 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
13722 int vpos;
2311178e 13723
b7826503 13724 CHECK_NUMBER (row);
eaaa65b0
GM
13725 vpos = XINT (row);
13726 if (vpos >= 0 && vpos < m->nrows)
13727 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
13728 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
13729 return Qnil;
13730}
ca26e1c8 13731
0f9c0ff0 13732
62397849 13733DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
7ee72033
MB
13734 doc: /* Toggle tracing of redisplay.
13735With ARG, turn tracing on if and only if ARG is positive. */)
13736 (arg)
62397849 13737 Lisp_Object arg;
5f5c8ee5 13738{
62397849
GM
13739 if (NILP (arg))
13740 trace_redisplay_p = !trace_redisplay_p;
13741 else
13742 {
13743 arg = Fprefix_numeric_value (arg);
13744 trace_redisplay_p = XINT (arg) > 0;
13745 }
2311178e 13746
5f5c8ee5
GM
13747 return Qnil;
13748}
bf9249e3
GM
13749
13750
f4a374a1 13751DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
e9757d41
SM
13752 doc: /* Like `format', but print result to stderr.
13753usage: (trace-to-stderr STRING &rest OBJECTS) */)
7ee72033 13754 (nargs, args)
f4a374a1
GM
13755 int nargs;
13756 Lisp_Object *args;
bf9249e3 13757{
f4a374a1 13758 Lisp_Object s = Fformat (nargs, args);
2051c264 13759 fprintf (stderr, "%s", SDATA (s));
bf9249e3
GM
13760 return Qnil;
13761}
2311178e 13762
5f5c8ee5 13763#endif /* GLYPH_DEBUG */
ca26e1c8 13764
ca26e1c8 13765
5f5c8ee5
GM
13766\f
13767/***********************************************************************
13768 Building Desired Matrix Rows
13769 ***********************************************************************/
a2889657 13770
5f5c8ee5
GM
13771/* Return a temporary glyph row holding the glyphs of an overlay
13772 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 13773
5f5c8ee5
GM
13774static struct glyph_row *
13775get_overlay_arrow_glyph_row (w)
13776 struct window *w;
13777{
13778 struct frame *f = XFRAME (WINDOW_FRAME (w));
13779 struct buffer *buffer = XBUFFER (w->buffer);
13780 struct buffer *old = current_buffer;
50f80c2f 13781 const unsigned char *arrow_string = SDATA (Voverlay_arrow_string);
2051c264 13782 int arrow_len = SCHARS (Voverlay_arrow_string);
50f80c2f
KR
13783 const unsigned char *arrow_end = arrow_string + arrow_len;
13784 const unsigned char *p;
5f5c8ee5
GM
13785 struct it it;
13786 int multibyte_p;
13787 int n_glyphs_before;
13788
13789 set_buffer_temp (buffer);
13790 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
13791 it.glyph_row->used[TEXT_AREA] = 0;
13792 SET_TEXT_POS (it.position, 0, 0);
13793
13794 multibyte_p = !NILP (buffer->enable_multibyte_characters);
13795 p = arrow_string;
13796 while (p < arrow_end)
13797 {
13798 Lisp_Object face, ilisp;
2311178e 13799
5f5c8ee5
GM
13800 /* Get the next character. */
13801 if (multibyte_p)
4fdb80f2 13802 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
13803 else
13804 it.c = *p, it.len = 1;
13805 p += it.len;
2311178e 13806
5f5c8ee5 13807 /* Get its face. */
ac90c44f 13808 ilisp = make_number (p - arrow_string);
5f5c8ee5
GM
13809 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
13810 it.face_id = compute_char_face (f, it.c, face);
13811
13812 /* Compute its width, get its glyphs. */
13813 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 13814 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
13815 PRODUCE_GLYPHS (&it);
13816
13817 /* If this character doesn't fit any more in the line, we have
13818 to remove some glyphs. */
13819 if (it.current_x > it.last_visible_x)
13820 {
13821 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
13822 break;
13823 }
13824 }
2311178e 13825
5f5c8ee5
GM
13826 set_buffer_temp (old);
13827 return it.glyph_row;
13828}
ca26e1c8 13829
b0a0fbda 13830
5f5c8ee5
GM
13831/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
13832 glyphs are only inserted for terminal frames since we can't really
13833 win with truncation glyphs when partially visible glyphs are
13834 involved. Which glyphs to insert is determined by
13835 produce_special_glyphs. */
67481ae5 13836
5f5c8ee5
GM
13837static void
13838insert_left_trunc_glyphs (it)
13839 struct it *it;
13840{
13841 struct it truncate_it;
13842 struct glyph *from, *end, *to, *toend;
13843
13844 xassert (!FRAME_WINDOW_P (it->f));
13845
13846 /* Get the truncation glyphs. */
13847 truncate_it = *it;
5f5c8ee5
GM
13848 truncate_it.current_x = 0;
13849 truncate_it.face_id = DEFAULT_FACE_ID;
13850 truncate_it.glyph_row = &scratch_glyph_row;
13851 truncate_it.glyph_row->used[TEXT_AREA] = 0;
13852 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
6fc556fd 13853 truncate_it.object = make_number (0);
5f5c8ee5 13854 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
2311178e 13855
5f5c8ee5
GM
13856 /* Overwrite glyphs from IT with truncation glyphs. */
13857 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
13858 end = from + truncate_it.glyph_row->used[TEXT_AREA];
13859 to = it->glyph_row->glyphs[TEXT_AREA];
13860 toend = to + it->glyph_row->used[TEXT_AREA];
13861
13862 while (from < end)
13863 *to++ = *from++;
13864
37be86f2
KH
13865 /* There may be padding glyphs left over. Overwrite them too. */
13866 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
13867 {
13868 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
13869 while (from < end)
13870 *to++ = *from++;
13871 }
5f5c8ee5 13872
37be86f2
KH
13873 if (to > toend)
13874 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
5f5c8ee5 13875}
e0bfbde6 13876
e0bfbde6 13877
5f5c8ee5 13878/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 13879
5f5c8ee5
GM
13880 Most of the time, ascent and height of a display line will be equal
13881 to the max_ascent and max_height values of the display iterator
13882 structure. This is not the case if
67481ae5 13883
5f5c8ee5
GM
13884 1. We hit ZV without displaying anything. In this case, max_ascent
13885 and max_height will be zero.
1c9241f5 13886
5f5c8ee5
GM
13887 2. We have some glyphs that don't contribute to the line height.
13888 (The glyph row flag contributes_to_line_height_p is for future
13889 pixmap extensions).
f6fd109b 13890
5f5c8ee5
GM
13891 The first case is easily covered by using default values because in
13892 these cases, the line height does not really matter, except that it
13893 must not be zero. */
67481ae5 13894
5f5c8ee5
GM
13895static void
13896compute_line_metrics (it)
13897 struct it *it;
13898{
13899 struct glyph_row *row = it->glyph_row;
13900 int area, i;
1c2250c2 13901
5f5c8ee5
GM
13902 if (FRAME_WINDOW_P (it->f))
13903 {
75c5350a 13904 int i, min_y, max_y;
1c2250c2 13905
5f5c8ee5
GM
13906 /* The line may consist of one space only, that was added to
13907 place the cursor on it. If so, the row's height hasn't been
13908 computed yet. */
13909 if (row->height == 0)
13910 {
13911 if (it->max_ascent + it->max_descent == 0)
da8b7f4f 13912 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
5f5c8ee5
GM
13913 row->ascent = it->max_ascent;
13914 row->height = it->max_ascent + it->max_descent;
312246d1
GM
13915 row->phys_ascent = it->max_phys_ascent;
13916 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5 13917 }
2311178e 13918
5f5c8ee5
GM
13919 /* Compute the width of this line. */
13920 row->pixel_width = row->x;
13921 for (i = 0; i < row->used[TEXT_AREA]; ++i)
13922 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
13923
13924 xassert (row->pixel_width >= 0);
13925 xassert (row->ascent >= 0 && row->height > 0);
13926
312246d1
GM
13927 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
13928 || MATRIX_ROW_OVERLAPS_PRED_P (row));
13929
13930 /* If first line's physical ascent is larger than its logical
13931 ascent, use the physical ascent, and make the row taller.
13932 This makes accented characters fully visible. */
b28cb6ed 13933 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
312246d1
GM
13934 && row->phys_ascent > row->ascent)
13935 {
13936 row->height += row->phys_ascent - row->ascent;
13937 row->ascent = row->phys_ascent;
13938 }
13939
5f5c8ee5
GM
13940 /* Compute how much of the line is visible. */
13941 row->visible_height = row->height;
2311178e 13942
da8b7f4f
KS
13943 min_y = WINDOW_HEADER_LINE_HEIGHT (it->w);
13944 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
75c5350a
GM
13945
13946 if (row->y < min_y)
13947 row->visible_height -= min_y - row->y;
13948 if (row->y + row->height > max_y)
13949 row->visible_height -= row->y + row->height - max_y;
5f5c8ee5
GM
13950 }
13951 else
13952 {
13953 row->pixel_width = row->used[TEXT_AREA];
33ea6c4d
GM
13954 if (row->continued_p)
13955 row->pixel_width -= it->continuation_pixel_width;
13956 else if (row->truncated_on_right_p)
13957 row->pixel_width -= it->truncation_pixel_width;
312246d1
GM
13958 row->ascent = row->phys_ascent = 0;
13959 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 13960 }
67481ae5 13961
5f5c8ee5
GM
13962 /* Compute a hash code for this row. */
13963 row->hash = 0;
13964 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
13965 for (i = 0; i < row->used[area]; ++i)
13966 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
13967 + row->glyphs[area][i].u.val
43d120d8
KH
13968 + row->glyphs[area][i].face_id
13969 + row->glyphs[area][i].padding_p
5f5c8ee5 13970 + (row->glyphs[area][i].type << 2));
a2889657 13971
5f5c8ee5 13972 it->max_ascent = it->max_descent = 0;
312246d1 13973 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 13974}
12adba34 13975
ca26e1c8 13976
5f5c8ee5
GM
13977/* Append one space to the glyph row of iterator IT if doing a
13978 window-based redisplay. DEFAULT_FACE_P non-zero means let the
13979 space have the default face, otherwise let it have the same face as
80c6cb1f 13980 IT->face_id. Value is non-zero if a space was added.
c6e89d6c
GM
13981
13982 This function is called to make sure that there is always one glyph
13983 at the end of a glyph row that the cursor can be set on under
13984 window-systems. (If there weren't such a glyph we would not know
13985 how wide and tall a box cursor should be displayed).
13986
13987 At the same time this space let's a nicely handle clearing to the
13988 end of the line if the row ends in italic text. */
ca26e1c8 13989
80c6cb1f 13990static int
5f5c8ee5
GM
13991append_space (it, default_face_p)
13992 struct it *it;
13993 int default_face_p;
13994{
13995 if (FRAME_WINDOW_P (it->f))
13996 {
13997 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 13998
5f5c8ee5
GM
13999 if (it->glyph_row->glyphs[TEXT_AREA] + n
14000 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 14001 {
cafafe0b
GM
14002 /* Save some values that must not be changed.
14003 Must save IT->c and IT->len because otherwise
14004 ITERATOR_AT_END_P wouldn't work anymore after
14005 append_space has been called. */
478d746b 14006 enum display_element_type saved_what = it->what;
cafafe0b
GM
14007 int saved_c = it->c, saved_len = it->len;
14008 int saved_x = it->current_x;
5f5c8ee5 14009 int saved_face_id = it->face_id;
cafafe0b 14010 struct text_pos saved_pos;
5f5c8ee5 14011 Lisp_Object saved_object;
980806b6 14012 struct face *face;
5f5c8ee5
GM
14013
14014 saved_object = it->object;
14015 saved_pos = it->position;
2311178e 14016
5f5c8ee5
GM
14017 it->what = IT_CHARACTER;
14018 bzero (&it->position, sizeof it->position);
6fc556fd 14019 it->object = make_number (0);
5f5c8ee5
GM
14020 it->c = ' ';
14021 it->len = 1;
5f5c8ee5
GM
14022
14023 if (default_face_p)
14024 it->face_id = DEFAULT_FACE_ID;
4aad61f8
GM
14025 else if (it->face_before_selective_p)
14026 it->face_id = it->saved_face_id;
980806b6
KH
14027 face = FACE_FROM_ID (it->f, it->face_id);
14028 it->face_id = FACE_FOR_CHAR (it->f, face, 0);
1842fc1a 14029
5f5c8ee5 14030 PRODUCE_GLYPHS (it);
2311178e 14031
5f5c8ee5
GM
14032 it->current_x = saved_x;
14033 it->object = saved_object;
14034 it->position = saved_pos;
14035 it->what = saved_what;
14036 it->face_id = saved_face_id;
cafafe0b
GM
14037 it->len = saved_len;
14038 it->c = saved_c;
80c6cb1f 14039 return 1;
5f5c8ee5
GM
14040 }
14041 }
80c6cb1f
GM
14042
14043 return 0;
5f5c8ee5 14044}
12adba34 14045
1842fc1a 14046
5f5c8ee5
GM
14047/* Extend the face of the last glyph in the text area of IT->glyph_row
14048 to the end of the display line. Called from display_line.
14049 If the glyph row is empty, add a space glyph to it so that we
14050 know the face to draw. Set the glyph row flag fill_line_p. */
2311178e 14051
5f5c8ee5
GM
14052static void
14053extend_face_to_end_of_line (it)
14054 struct it *it;
14055{
14056 struct face *face;
14057 struct frame *f = it->f;
1842fc1a 14058
5f5c8ee5
GM
14059 /* If line is already filled, do nothing. */
14060 if (it->current_x >= it->last_visible_x)
14061 return;
2311178e 14062
5f5c8ee5
GM
14063 /* Face extension extends the background and box of IT->face_id
14064 to the end of the line. If the background equals the background
4aad61f8
GM
14065 of the frame, we don't have to do anything. */
14066 if (it->face_before_selective_p)
14067 face = FACE_FROM_ID (it->f, it->saved_face_id);
14068 else
14069 face = FACE_FROM_ID (f, it->face_id);
2311178e 14070
5f5c8ee5
GM
14071 if (FRAME_WINDOW_P (f)
14072 && face->box == FACE_NO_BOX
14073 && face->background == FRAME_BACKGROUND_PIXEL (f)
14074 && !face->stipple)
14075 return;
1842fc1a 14076
5f5c8ee5
GM
14077 /* Set the glyph row flag indicating that the face of the last glyph
14078 in the text area has to be drawn to the end of the text area. */
14079 it->glyph_row->fill_line_p = 1;
545e04f6 14080
980806b6
KH
14081 /* If current character of IT is not ASCII, make sure we have the
14082 ASCII face. This will be automatically undone the next time
14083 get_next_display_element returns a multibyte character. Note
14084 that the character will always be single byte in unibyte text. */
14085 if (!SINGLE_BYTE_CHAR_P (it->c))
5f5c8ee5 14086 {
980806b6 14087 it->face_id = FACE_FOR_CHAR (f, face, 0);
5f5c8ee5 14088 }
545e04f6 14089
5f5c8ee5
GM
14090 if (FRAME_WINDOW_P (f))
14091 {
14092 /* If the row is empty, add a space with the current face of IT,
14093 so that we know which face to draw. */
14094 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 14095 {
5f5c8ee5 14096 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
43d120d8 14097 it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
5f5c8ee5 14098 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 14099 }
5f5c8ee5
GM
14100 }
14101 else
14102 {
14103 /* Save some values that must not be changed. */
14104 int saved_x = it->current_x;
14105 struct text_pos saved_pos;
14106 Lisp_Object saved_object;
478d746b 14107 enum display_element_type saved_what = it->what;
4aad61f8 14108 int saved_face_id = it->face_id;
5f5c8ee5
GM
14109
14110 saved_object = it->object;
14111 saved_pos = it->position;
2311178e 14112
5f5c8ee5
GM
14113 it->what = IT_CHARACTER;
14114 bzero (&it->position, sizeof it->position);
6fc556fd 14115 it->object = make_number (0);
5f5c8ee5
GM
14116 it->c = ' ';
14117 it->len = 1;
4aad61f8 14118 it->face_id = face->id;
2311178e 14119
5f5c8ee5 14120 PRODUCE_GLYPHS (it);
2311178e 14121
5f5c8ee5
GM
14122 while (it->current_x <= it->last_visible_x)
14123 PRODUCE_GLYPHS (it);
2311178e 14124
5f5c8ee5
GM
14125 /* Don't count these blanks really. It would let us insert a left
14126 truncation glyph below and make us set the cursor on them, maybe. */
14127 it->current_x = saved_x;
14128 it->object = saved_object;
14129 it->position = saved_pos;
14130 it->what = saved_what;
4aad61f8 14131 it->face_id = saved_face_id;
5f5c8ee5
GM
14132 }
14133}
12adba34 14134
545e04f6 14135
5f5c8ee5
GM
14136/* Value is non-zero if text starting at CHARPOS in current_buffer is
14137 trailing whitespace. */
1c9241f5 14138
5f5c8ee5
GM
14139static int
14140trailing_whitespace_p (charpos)
14141 int charpos;
14142{
14143 int bytepos = CHAR_TO_BYTE (charpos);
14144 int c = 0;
7bbe686f 14145
5f5c8ee5
GM
14146 while (bytepos < ZV_BYTE
14147 && (c = FETCH_CHAR (bytepos),
14148 c == ' ' || c == '\t'))
14149 ++bytepos;
0d09d1e6 14150
8f897821
GM
14151 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
14152 {
14153 if (bytepos != PT_BYTE)
14154 return 1;
14155 }
14156 return 0;
5f5c8ee5 14157}
31b24551 14158
545e04f6 14159
5f5c8ee5 14160/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 14161
5f5c8ee5
GM
14162void
14163highlight_trailing_whitespace (f, row)
14164 struct frame *f;
14165 struct glyph_row *row;
14166{
14167 int used = row->used[TEXT_AREA];
2311178e 14168
5f5c8ee5
GM
14169 if (used)
14170 {
14171 struct glyph *start = row->glyphs[TEXT_AREA];
14172 struct glyph *glyph = start + used - 1;
14173
ade0bee1
GM
14174 /* Skip over glyphs inserted to display the cursor at the
14175 end of a line, for extending the face of the last glyph
14176 to the end of the line on terminals, and for truncation
14177 and continuation glyphs. */
65008712
GM
14178 while (glyph >= start
14179 && glyph->type == CHAR_GLYPH
65008712 14180 && INTEGERP (glyph->object))
5f5c8ee5
GM
14181 --glyph;
14182
14183 /* If last glyph is a space or stretch, and it's trailing
14184 whitespace, set the face of all trailing whitespace glyphs in
14185 IT->glyph_row to `trailing-whitespace'. */
14186 if (glyph >= start
14187 && BUFFERP (glyph->object)
14188 && (glyph->type == STRETCH_GLYPH
14189 || (glyph->type == CHAR_GLYPH
43d120d8 14190 && glyph->u.ch == ' '))
5f5c8ee5 14191 && trailing_whitespace_p (glyph->charpos))
545e04f6 14192 {
980806b6 14193 int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
2311178e 14194
5f5c8ee5
GM
14195 while (glyph >= start
14196 && BUFFERP (glyph->object)
14197 && (glyph->type == STRETCH_GLYPH
14198 || (glyph->type == CHAR_GLYPH
43d120d8
KH
14199 && glyph->u.ch == ' ')))
14200 (glyph--)->face_id = face_id;
545e04f6 14201 }
a2889657 14202 }
5f5c8ee5 14203}
a2889657 14204
5fcbb24d 14205
cafafe0b 14206/* Value is non-zero if glyph row ROW in window W should be
0fd37545 14207 used to hold the cursor. */
cafafe0b
GM
14208
14209static int
14210cursor_row_p (w, row)
14211 struct window *w;
14212 struct glyph_row *row;
14213{
9a038881 14214 int cursor_row_p = 1;
2311178e 14215
cafafe0b
GM
14216 if (PT == MATRIX_ROW_END_CHARPOS (row))
14217 {
9a038881
GM
14218 /* If the row ends with a newline from a string, we don't want
14219 the cursor there (if the row is continued it doesn't end in a
14220 newline). */
14221 if (CHARPOS (row->end.string_pos) >= 0
14222 || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
14223 cursor_row_p = row->continued_p;
14224
14225 /* If the row ends at ZV, display the cursor at the end of that
14226 row instead of at the start of the row below. */
14227 else if (row->ends_at_zv_p)
14228 cursor_row_p = 1;
14229 else
14230 cursor_row_p = 0;
cafafe0b
GM
14231 }
14232
9a038881 14233 return cursor_row_p;
cafafe0b
GM
14234}
14235
14236
5f5c8ee5
GM
14237/* Construct the glyph row IT->glyph_row in the desired matrix of
14238 IT->w from text at the current position of IT. See dispextern.h
14239 for an overview of struct it. Value is non-zero if
14240 IT->glyph_row displays text, as opposed to a line displaying ZV
14241 only. */
2311178e 14242
5f5c8ee5
GM
14243static int
14244display_line (it)
14245 struct it *it;
14246{
14247 struct glyph_row *row = it->glyph_row;
14248
14249 /* We always start displaying at hpos zero even if hscrolled. */
14250 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 14251
5f5c8ee5
GM
14252 /* We must not display in a row that's not a text row. */
14253 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
14254 < it->w->desired_matrix->nrows);
12adba34 14255
5f5c8ee5
GM
14256 /* Is IT->w showing the region? */
14257 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 14258
5f5c8ee5
GM
14259 /* Clear the result glyph row and enable it. */
14260 prepare_desired_row (row);
12adba34 14261
5f5c8ee5
GM
14262 row->y = it->current_y;
14263 row->start = it->current;
14264 row->continuation_lines_width = it->continuation_lines_width;
14265 row->displays_text_p = 1;
91004049
GM
14266 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
14267 it->starts_in_middle_of_char_p = 0;
5f5c8ee5
GM
14268
14269 /* Arrange the overlays nicely for our purposes. Usually, we call
14270 display_line on only one line at a time, in which case this
14271 can't really hurt too much, or we call it on lines which appear
14272 one after another in the buffer, in which case all calls to
14273 recenter_overlay_lists but the first will be pretty cheap. */
14274 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
14275
5f5c8ee5
GM
14276 /* Move over display elements that are not visible because we are
14277 hscrolled. This may stop at an x-position < IT->first_visible_x
14278 if the first glyph is partially visible or if we hit a line end. */
14279 if (it->current_x < it->first_visible_x)
14280 move_it_in_display_line_to (it, ZV, it->first_visible_x,
14281 MOVE_TO_POS | MOVE_TO_X);
14282
14283 /* Get the initial row height. This is either the height of the
14284 text hscrolled, if there is any, or zero. */
14285 row->ascent = it->max_ascent;
14286 row->height = it->max_ascent + it->max_descent;
312246d1
GM
14287 row->phys_ascent = it->max_phys_ascent;
14288 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
14289
14290 /* Loop generating characters. The loop is left with IT on the next
14291 character to display. */
14292 while (1)
14293 {
14294 int n_glyphs_before, hpos_before, x_before;
14295 int x, i, nglyphs;
ae26e27d 14296 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
b28cb6ed 14297
5f5c8ee5
GM
14298 /* Retrieve the next thing to display. Value is zero if end of
14299 buffer reached. */
14300 if (!get_next_display_element (it))
14301 {
14302 /* Maybe add a space at the end of this line that is used to
1b335865
GM
14303 display the cursor there under X. Set the charpos of the
14304 first glyph of blank lines not corresponding to any text
14305 to -1. */
14306 if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
14307 || row->used[TEXT_AREA] == 0)
a2889657 14308 {
5f5c8ee5
GM
14309 row->glyphs[TEXT_AREA]->charpos = -1;
14310 row->displays_text_p = 0;
14311
2ad551af 14312 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines)
e6b70fd8
GM
14313 && (!MINI_WINDOW_P (it->w)
14314 || (minibuf_level && EQ (it->window, minibuf_window))))
5f5c8ee5 14315 row->indicate_empty_line_p = 1;
a2889657 14316 }
2311178e 14317
5f5c8ee5
GM
14318 it->continuation_lines_width = 0;
14319 row->ends_at_zv_p = 1;
14320 break;
a2889657 14321 }
a2889657 14322
5f5c8ee5
GM
14323 /* Now, get the metrics of what we want to display. This also
14324 generates glyphs in `row' (which is IT->glyph_row). */
14325 n_glyphs_before = row->used[TEXT_AREA];
14326 x = it->current_x;
e6819faf
GM
14327
14328 /* Remember the line height so far in case the next element doesn't
14329 fit on the line. */
14330 if (!it->truncate_lines_p)
14331 {
14332 ascent = it->max_ascent;
14333 descent = it->max_descent;
14334 phys_ascent = it->max_phys_ascent;
14335 phys_descent = it->max_phys_descent;
14336 }
2311178e 14337
5f5c8ee5 14338 PRODUCE_GLYPHS (it);
a2889657 14339
5f5c8ee5
GM
14340 /* If this display element was in marginal areas, continue with
14341 the next one. */
14342 if (it->area != TEXT_AREA)
a2889657 14343 {
5f5c8ee5
GM
14344 row->ascent = max (row->ascent, it->max_ascent);
14345 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14346 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14347 row->phys_height = max (row->phys_height,
14348 it->max_phys_ascent + it->max_phys_descent);
cafafe0b 14349 set_iterator_to_next (it, 1);
5f5c8ee5
GM
14350 continue;
14351 }
5936754e 14352
5f5c8ee5
GM
14353 /* Does the display element fit on the line? If we truncate
14354 lines, we should draw past the right edge of the window. If
14355 we don't truncate, we want to stop so that we can display the
14356 continuation glyph before the right margin. If lines are
14357 continued, there are two possible strategies for characters
14358 resulting in more than 1 glyph (e.g. tabs): Display as many
14359 glyphs as possible in this line and leave the rest for the
14360 continuation line, or display the whole element in the next
14361 line. Original redisplay did the former, so we do it also. */
14362 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14363 hpos_before = it->hpos;
14364 x_before = x;
4dcd74e6 14365
4b41cebb 14366 if (/* Not a newline. */
4dcd74e6 14367 nglyphs > 0
202c1b5b 14368 /* Glyphs produced fit entirely in the line. */
4dcd74e6
GM
14369 && it->current_x < it->last_visible_x)
14370 {
37be86f2 14371 it->hpos += nglyphs;
5f5c8ee5
GM
14372 row->ascent = max (row->ascent, it->max_ascent);
14373 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14374 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14375 row->phys_height = max (row->phys_height,
14376 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
14377 if (it->current_x - it->pixel_width < it->first_visible_x)
14378 row->x = x - it->first_visible_x;
14379 }
14380 else
14381 {
14382 int new_x;
14383 struct glyph *glyph;
2311178e 14384
5f5c8ee5 14385 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 14386 {
5f5c8ee5
GM
14387 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14388 new_x = x + glyph->pixel_width;
14389
14390 if (/* Lines are continued. */
14391 !it->truncate_lines_p
14392 && (/* Glyph doesn't fit on the line. */
14393 new_x > it->last_visible_x
14394 /* Or it fits exactly on a window system frame. */
14395 || (new_x == it->last_visible_x
14396 && FRAME_WINDOW_P (it->f))))
a2889657 14397 {
5f5c8ee5 14398 /* End of a continued line. */
2311178e 14399
5f5c8ee5
GM
14400 if (it->hpos == 0
14401 || (new_x == it->last_visible_x
14402 && FRAME_WINDOW_P (it->f)))
14403 {
e6819faf
GM
14404 /* Current glyph is the only one on the line or
14405 fits exactly on the line. We must continue
14406 the line because we can't draw the cursor
14407 after the glyph. */
5f5c8ee5
GM
14408 row->continued_p = 1;
14409 it->current_x = new_x;
14410 it->continuation_lines_width += new_x;
14411 ++it->hpos;
14412 if (i == nglyphs - 1)
cafafe0b 14413 set_iterator_to_next (it, 1);
5f5c8ee5 14414 }
3b3c4bf0
GM
14415 else if (CHAR_GLYPH_PADDING_P (*glyph)
14416 && !FRAME_WINDOW_P (it->f))
14417 {
14418 /* A padding glyph that doesn't fit on this line.
14419 This means the whole character doesn't fit
14420 on the line. */
14421 row->used[TEXT_AREA] = n_glyphs_before;
2311178e 14422
3b3c4bf0
GM
14423 /* Fill the rest of the row with continuation
14424 glyphs like in 20.x. */
14425 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
14426 < row->glyphs[1 + TEXT_AREA])
14427 produce_special_glyphs (it, IT_CONTINUATION);
2311178e 14428
3b3c4bf0
GM
14429 row->continued_p = 1;
14430 it->current_x = x_before;
14431 it->continuation_lines_width += x_before;
2311178e 14432
3b3c4bf0
GM
14433 /* Restore the height to what it was before the
14434 element not fitting on the line. */
14435 it->max_ascent = ascent;
14436 it->max_descent = descent;
14437 it->max_phys_ascent = phys_ascent;
14438 it->max_phys_descent = phys_descent;
14439 }
0df56f4d
GM
14440 else if (it->c == '\t' && FRAME_WINDOW_P (it->f))
14441 {
14442 /* A TAB that extends past the right edge of the
14443 window. This produces a single glyph on
14444 window system frames. We leave the glyph in
14445 this row and let it fill the row, but don't
14446 consume the TAB. */
14447 it->continuation_lines_width += it->last_visible_x;
14448 row->ends_in_middle_of_char_p = 1;
14449 row->continued_p = 1;
14450 glyph->pixel_width = it->last_visible_x - x;
14451 it->starts_in_middle_of_char_p = 1;
14452 }
5f5c8ee5 14453 else
5936754e 14454 {
0df56f4d
GM
14455 /* Something other than a TAB that draws past
14456 the right edge of the window. Restore
14457 positions to values before the element. */
5f5c8ee5 14458 row->used[TEXT_AREA] = n_glyphs_before + i;
2311178e 14459
5f5c8ee5
GM
14460 /* Display continuation glyphs. */
14461 if (!FRAME_WINDOW_P (it->f))
14462 produce_special_glyphs (it, IT_CONTINUATION);
14463 row->continued_p = 1;
653c329b 14464
0df56f4d 14465 it->continuation_lines_width += x;
2311178e 14466
91004049
GM
14467 if (nglyphs > 1 && i > 0)
14468 {
14469 row->ends_in_middle_of_char_p = 1;
14470 it->starts_in_middle_of_char_p = 1;
14471 }
2311178e 14472
e6819faf
GM
14473 /* Restore the height to what it was before the
14474 element not fitting on the line. */
14475 it->max_ascent = ascent;
14476 it->max_descent = descent;
14477 it->max_phys_ascent = phys_ascent;
14478 it->max_phys_descent = phys_descent;
5936754e 14479 }
e6819faf 14480
5f5c8ee5
GM
14481 break;
14482 }
14483 else if (new_x > it->first_visible_x)
14484 {
14485 /* Increment number of glyphs actually displayed. */
14486 ++it->hpos;
2311178e 14487
5f5c8ee5
GM
14488 if (x < it->first_visible_x)
14489 /* Glyph is partially visible, i.e. row starts at
14490 negative X position. */
14491 row->x = x - it->first_visible_x;
14492 }
14493 else
14494 {
14495 /* Glyph is completely off the left margin of the
14496 window. This should not happen because of the
72b8c434
RS
14497 move_it_in_display_line at the start of this
14498 function, unless the text display area of the
14499 window is empty. */
14500 xassert (it->first_visible_x <= it->last_visible_x);
a2889657 14501 }
a2889657 14502 }
2311178e 14503
5f5c8ee5
GM
14504 row->ascent = max (row->ascent, it->max_ascent);
14505 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14506 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14507 row->phys_height = max (row->phys_height,
14508 it->max_phys_ascent + it->max_phys_descent);
2311178e 14509
5f5c8ee5
GM
14510 /* End of this display line if row is continued. */
14511 if (row->continued_p)
14512 break;
a2889657 14513 }
a2889657 14514
5f5c8ee5
GM
14515 /* Is this a line end? If yes, we're also done, after making
14516 sure that a non-default face is extended up to the right
14517 margin of the window. */
14518 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 14519 {
5f5c8ee5
GM
14520 int used_before = row->used[TEXT_AREA];
14521
e74fb0f7
GM
14522 row->ends_in_newline_from_string_p = STRINGP (it->object);
14523
5f5c8ee5
GM
14524 /* Add a space at the end of the line that is used to
14525 display the cursor there. */
14526 append_space (it, 0);
2311178e 14527
5f5c8ee5
GM
14528 /* Extend the face to the end of the line. */
14529 extend_face_to_end_of_line (it);
14530
14531 /* Make sure we have the position. */
14532 if (used_before == 0)
14533 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
2311178e 14534
5f5c8ee5 14535 /* Consume the line end. This skips over invisible lines. */
cafafe0b 14536 set_iterator_to_next (it, 1);
5f5c8ee5
GM
14537 it->continuation_lines_width = 0;
14538 break;
1c9241f5 14539 }
a2889657 14540
2311178e 14541 /* Proceed with next display element. Note that this skips
5f5c8ee5 14542 over lines invisible because of selective display. */
cafafe0b 14543 set_iterator_to_next (it, 1);
b1d1124b 14544
5f5c8ee5
GM
14545 /* If we truncate lines, we are done when the last displayed
14546 glyphs reach past the right margin of the window. */
14547 if (it->truncate_lines_p
14548 && (FRAME_WINDOW_P (it->f)
14549 ? (it->current_x >= it->last_visible_x)
14550 : (it->current_x > it->last_visible_x)))
75d13c64 14551 {
5f5c8ee5
GM
14552 /* Maybe add truncation glyphs. */
14553 if (!FRAME_WINDOW_P (it->f))
14554 {
a98b5ed9 14555 int i, n;
2311178e 14556
a98b5ed9
GM
14557 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
14558 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
14559 break;
14560
14561 for (n = row->used[TEXT_AREA]; i < n; ++i)
14562 {
14563 row->used[TEXT_AREA] = i;
14564 produce_special_glyphs (it, IT_TRUNCATION);
14565 }
5f5c8ee5 14566 }
2311178e 14567
5f5c8ee5
GM
14568 row->truncated_on_right_p = 1;
14569 it->continuation_lines_width = 0;
312246d1 14570 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
14571 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
14572 it->hpos = hpos_before;
14573 it->current_x = x_before;
14574 break;
75d13c64 14575 }
a2889657 14576 }
a2889657 14577
5f5c8ee5
GM
14578 /* If line is not empty and hscrolled, maybe insert truncation glyphs
14579 at the left window margin. */
14580 if (it->first_visible_x
14581 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
14582 {
14583 if (!FRAME_WINDOW_P (it->f))
14584 insert_left_trunc_glyphs (it);
14585 row->truncated_on_left_p = 1;
14586 }
a2889657 14587
5f5c8ee5
GM
14588 /* If the start of this line is the overlay arrow-position, then
14589 mark this glyph row as the one containing the overlay arrow.
14590 This is clearly a mess with variable size fonts. It would be
14591 better to let it be displayed like cursors under X. */
e24c997d 14592 if (MARKERP (Voverlay_arrow_position)
a2889657 14593 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
14594 && (MATRIX_ROW_START_CHARPOS (row)
14595 == marker_position (Voverlay_arrow_position))
e24c997d 14596 && STRINGP (Voverlay_arrow_string)
a2889657
JB
14597 && ! overlay_arrow_seen)
14598 {
b46952ae 14599 /* Overlay arrow in window redisplay is a fringe bitmap. */
5f5c8ee5 14600 if (!FRAME_WINDOW_P (it->f))
c4628384 14601 {
5f5c8ee5
GM
14602 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
14603 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
14604 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
14605 struct glyph *p = row->glyphs[TEXT_AREA];
14606 struct glyph *p2, *end;
14607
14608 /* Copy the arrow glyphs. */
14609 while (glyph < arrow_end)
14610 *p++ = *glyph++;
14611
14612 /* Throw away padding glyphs. */
14613 p2 = p;
14614 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
14615 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
14616 ++p2;
14617 if (p2 > p)
212e4f87 14618 {
5f5c8ee5
GM
14619 while (p2 < end)
14620 *p++ = *p2++;
14621 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 14622 }
c4628384 14623 }
2311178e 14624
a2889657 14625 overlay_arrow_seen = 1;
5f5c8ee5 14626 row->overlay_arrow_p = 1;
a2889657
JB
14627 }
14628
5f5c8ee5
GM
14629 /* Compute pixel dimensions of this line. */
14630 compute_line_metrics (it);
14631
14632 /* Remember the position at which this line ends. */
14633 row->end = it->current;
14634
173cbca8 14635 /* Maybe set the cursor. */
5f5c8ee5
GM
14636 if (it->w->cursor.vpos < 0
14637 && PT >= MATRIX_ROW_START_CHARPOS (row)
cafafe0b
GM
14638 && PT <= MATRIX_ROW_END_CHARPOS (row)
14639 && cursor_row_p (it->w, row))
14640 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
14641
14642 /* Highlight trailing whitespace. */
8f897821 14643 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
14644 highlight_trailing_whitespace (it->f, it->glyph_row);
14645
14646 /* Prepare for the next line. This line starts horizontally at (X
14647 HPOS) = (0 0). Vertical positions are incremented. As a
14648 convenience for the caller, IT->glyph_row is set to the next
14649 row to be used. */
14650 it->current_x = it->hpos = 0;
14651 it->current_y += row->height;
14652 ++it->vpos;
14653 ++it->glyph_row;
14654 return row->displays_text_p;
a2889657 14655}
5f5c8ee5
GM
14656
14657
a2889657 14658\f
5f5c8ee5
GM
14659/***********************************************************************
14660 Menu Bar
14661 ***********************************************************************/
14662
14663/* Redisplay the menu bar in the frame for window W.
14664
14665 The menu bar of X frames that don't have X toolkit support is
14666 displayed in a special window W->frame->menu_bar_window.
2311178e 14667
5f5c8ee5
GM
14668 The menu bar of terminal frames is treated specially as far as
14669 glyph matrices are concerned. Menu bar lines are not part of
14670 windows, so the update is done directly on the frame matrix rows
14671 for the menu bar. */
7ce2c095
RS
14672
14673static void
14674display_menu_bar (w)
14675 struct window *w;
14676{
5f5c8ee5
GM
14677 struct frame *f = XFRAME (WINDOW_FRAME (w));
14678 struct it it;
14679 Lisp_Object items;
8351baf2 14680 int i;
7ce2c095 14681
5f5c8ee5 14682 /* Don't do all this for graphical frames. */
dc937613 14683#ifdef HAVE_NTGUI
d129c4c2
KH
14684 if (!NILP (Vwindow_system))
14685 return;
dc937613 14686#endif
488dd4c4 14687#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
d3413a53 14688 if (FRAME_X_P (f))
7ce2c095 14689 return;
5f5c8ee5 14690#endif
e0f712ba 14691#ifdef MAC_OS
1a578e9b
AC
14692 if (FRAME_MAC_P (f))
14693 return;
14694#endif
5f5c8ee5
GM
14695
14696#ifdef USE_X_TOOLKIT
14697 xassert (!FRAME_WINDOW_P (f));
52377a47 14698 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5 14699 it.first_visible_x = 0;
da8b7f4f 14700 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5
GM
14701#else /* not USE_X_TOOLKIT */
14702 if (FRAME_WINDOW_P (f))
14703 {
14704 /* Menu bar lines are displayed in the desired matrix of the
14705 dummy window menu_bar_window. */
14706 struct window *menu_w;
14707 xassert (WINDOWP (f->menu_bar_window));
14708 menu_w = XWINDOW (f->menu_bar_window);
14709 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 14710 MENU_FACE_ID);
5f5c8ee5 14711 it.first_visible_x = 0;
da8b7f4f 14712 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5
GM
14713 }
14714 else
14715 {
14716 /* This is a TTY frame, i.e. character hpos/vpos are used as
14717 pixel x/y. */
14718 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 14719 MENU_FACE_ID);
5f5c8ee5 14720 it.first_visible_x = 0;
da8b7f4f 14721 it.last_visible_x = FRAME_COLS (f);
5f5c8ee5
GM
14722 }
14723#endif /* not USE_X_TOOLKIT */
14724
1862a24e
MB
14725 if (! mode_line_inverse_video)
14726 /* Force the menu-bar to be displayed in the default face. */
14727 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
14728
5f5c8ee5
GM
14729 /* Clear all rows of the menu bar. */
14730 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
14731 {
14732 struct glyph_row *row = it.glyph_row + i;
14733 clear_glyph_row (row);
14734 row->enabled_p = 1;
14735 row->full_width_p = 1;
14736 }
7ce2c095 14737
5f5c8ee5
GM
14738 /* Display all items of the menu bar. */
14739 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 14740 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 14741 {
5f5c8ee5
GM
14742 Lisp_Object string;
14743
14744 /* Stop at nil string. */
a61b7058 14745 string = AREF (items, i + 1);
8351baf2
RS
14746 if (NILP (string))
14747 break;
2d66ad19 14748
5f5c8ee5 14749 /* Remember where item was displayed. */
a61b7058 14750 AREF (items, i + 3) = make_number (it.hpos);
7ce2c095 14751
5f5c8ee5
GM
14752 /* Display the item, pad with one space. */
14753 if (it.current_x < it.last_visible_x)
14754 display_string (NULL, string, Qnil, 0, 0, &it,
2051c264 14755 SCHARS (string) + 1, 0, 0, -1);
7ce2c095
RS
14756 }
14757
2d66ad19 14758 /* Fill out the line with spaces. */
5f5c8ee5
GM
14759 if (it.current_x < it.last_visible_x)
14760 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 14761
5f5c8ee5
GM
14762 /* Compute the total height of the lines. */
14763 compute_line_metrics (&it);
7ce2c095 14764}
5f5c8ee5
GM
14765
14766
7ce2c095 14767\f
5f5c8ee5
GM
14768/***********************************************************************
14769 Mode Line
14770 ***********************************************************************/
14771
715e84c9
GM
14772/* Redisplay mode lines in the window tree whose root is WINDOW. If
14773 FORCE is non-zero, redisplay mode lines unconditionally.
14774 Otherwise, redisplay only mode lines that are garbaged. Value is
14775 the number of windows whose mode lines were redisplayed. */
a2889657 14776
715e84c9
GM
14777static int
14778redisplay_mode_lines (window, force)
14779 Lisp_Object window;
14780 int force;
14781{
14782 int nwindows = 0;
2311178e 14783
715e84c9
GM
14784 while (!NILP (window))
14785 {
14786 struct window *w = XWINDOW (window);
2311178e 14787
715e84c9
GM
14788 if (WINDOWP (w->hchild))
14789 nwindows += redisplay_mode_lines (w->hchild, force);
14790 else if (WINDOWP (w->vchild))
14791 nwindows += redisplay_mode_lines (w->vchild, force);
14792 else if (force
14793 || FRAME_GARBAGED_P (XFRAME (w->frame))
14794 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
14795 {
715e84c9
GM
14796 struct text_pos lpoint;
14797 struct buffer *old = current_buffer;
14798
14799 /* Set the window's buffer for the mode line display. */
14800 SET_TEXT_POS (lpoint, PT, PT_BYTE);
14801 set_buffer_internal_1 (XBUFFER (w->buffer));
2311178e 14802
715e84c9
GM
14803 /* Point refers normally to the selected window. For any
14804 other window, set up appropriate value. */
14805 if (!EQ (window, selected_window))
14806 {
14807 struct text_pos pt;
2311178e 14808
715e84c9
GM
14809 SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
14810 if (CHARPOS (pt) < BEGV)
14811 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
14812 else if (CHARPOS (pt) > (ZV - 1))
14813 TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
14814 else
14815 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
14816 }
14817
715e84c9
GM
14818 /* Display mode lines. */
14819 clear_glyph_matrix (w->desired_matrix);
14820 if (display_mode_lines (w))
14821 {
14822 ++nwindows;
14823 w->must_be_updated_p = 1;
14824 }
14825
14826 /* Restore old settings. */
715e84c9
GM
14827 set_buffer_internal_1 (old);
14828 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
14829 }
14830
14831 window = w->next;
14832 }
14833
14834 return nwindows;
14835}
14836
14837
14838/* Display the mode and/or top line of window W. Value is the number
14839 of mode lines displayed. */
14840
14841static int
5f5c8ee5 14842display_mode_lines (w)
a2889657
JB
14843 struct window *w;
14844{
edd1e654 14845 Lisp_Object old_selected_window, old_selected_frame;
715e84c9 14846 int n = 0;
edd1e654
GM
14847
14848 old_selected_frame = selected_frame;
14849 selected_frame = w->frame;
14850 old_selected_window = selected_window;
14851 XSETWINDOW (selected_window, w);
2311178e 14852
5f5c8ee5 14853 /* These will be set while the mode line specs are processed. */
aa6d10fa 14854 line_number_displayed = 0;
155ef550 14855 w->column_number_displayed = Qnil;
aa6d10fa 14856
5f5c8ee5 14857 if (WINDOW_WANTS_MODELINE_P (w))
715e84c9 14858 {
c96e83bf 14859 struct window *sel_w = XWINDOW (old_selected_window);
f87c0a98 14860
96d2320f 14861 /* Select mode line face based on the real selected window. */
c96e83bf 14862 display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w),
715e84c9
GM
14863 current_buffer->mode_line_format);
14864 ++n;
14865 }
2311178e 14866
045dee35 14867 if (WINDOW_WANTS_HEADER_LINE_P (w))
715e84c9
GM
14868 {
14869 display_mode_line (w, HEADER_LINE_FACE_ID,
14870 current_buffer->header_line_format);
14871 ++n;
14872 }
14873
edd1e654
GM
14874 selected_frame = old_selected_frame;
14875 selected_window = old_selected_window;
715e84c9 14876 return n;
5f5c8ee5 14877}
03b294dc 14878
03b294dc 14879
5f5c8ee5 14880/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 14881 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
04612a64
GM
14882 FORMAT is the mode line format to display. Value is the pixel
14883 height of the mode line displayed. */
03b294dc 14884
04612a64 14885static int
5f5c8ee5
GM
14886display_mode_line (w, face_id, format)
14887 struct window *w;
14888 enum face_id face_id;
14889 Lisp_Object format;
14890{
14891 struct it it;
14892 struct face *face;
03b294dc 14893
5f5c8ee5
GM
14894 init_iterator (&it, w, -1, -1, NULL, face_id);
14895 prepare_desired_row (it.glyph_row);
14896
1862a24e
MB
14897 if (! mode_line_inverse_video)
14898 /* Force the mode-line to be displayed in the default face. */
14899 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
14900
5f5c8ee5
GM
14901 /* Temporarily make frame's keyboard the current kboard so that
14902 kboard-local variables in the mode_line_format will get the right
14903 values. */
14904 push_frame_kboard (it.f);
c53a1624 14905 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
5f5c8ee5 14906 pop_frame_kboard ();
a2889657 14907
5f5c8ee5
GM
14908 /* Fill up with spaces. */
14909 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
2311178e 14910
5f5c8ee5
GM
14911 compute_line_metrics (&it);
14912 it.glyph_row->full_width_p = 1;
14913 it.glyph_row->mode_line_p = 1;
5f5c8ee5
GM
14914 it.glyph_row->continued_p = 0;
14915 it.glyph_row->truncated_on_left_p = 0;
14916 it.glyph_row->truncated_on_right_p = 0;
14917
14918 /* Make a 3D mode-line have a shadow at its right end. */
14919 face = FACE_FROM_ID (it.f, face_id);
14920 extend_face_to_end_of_line (&it);
14921 if (face->box != FACE_NO_BOX)
d7eb09a0 14922 {
5f5c8ee5
GM
14923 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
14924 + it.glyph_row->used[TEXT_AREA] - 1);
14925 last->right_box_line_p = 1;
d7eb09a0 14926 }
04612a64
GM
14927
14928 return it.glyph_row->height;
a2889657
JB
14929}
14930
0fcf414f
RS
14931/* Alist that caches the results of :propertize.
14932 Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */
14933Lisp_Object mode_line_proptrans_alist;
a2889657 14934
fec8f23e
KS
14935/* List of strings making up the mode-line. */
14936Lisp_Object mode_line_string_list;
14937
14938/* Base face property when building propertized mode line string. */
14939static Lisp_Object mode_line_string_face;
14940static Lisp_Object mode_line_string_face_prop;
14941
14942
5f5c8ee5
GM
14943/* Contribute ELT to the mode line for window IT->w. How it
14944 translates into text depends on its data type.
a2889657 14945
5f5c8ee5 14946 IT describes the display environment in which we display, as usual.
a2889657
JB
14947
14948 DEPTH is the depth in recursion. It is used to prevent
14949 infinite recursion here.
14950
5f5c8ee5
GM
14951 FIELD_WIDTH is the number of characters the display of ELT should
14952 occupy in the mode line, and PRECISION is the maximum number of
14953 characters to display from ELT's representation. See
b8523839 14954 display_string for details.
a2889657 14955
c53a1624
RS
14956 Returns the hpos of the end of the text generated by ELT.
14957
14958 PROPS is a property list to add to any string we encounter.
14959
7d0393cf 14960 If RISKY is nonzero, remove (disregard) any properties in any string
93da8435
SM
14961 we encounter, and ignore :eval and :propertize.
14962
14963 If the global variable `frame_title_ptr' is non-NULL, then the output
14964 is passed to `store_frame_title' instead of `display_string'. */
a2889657
JB
14965
14966static int
c53a1624 14967display_mode_element (it, depth, field_width, precision, elt, props, risky)
5f5c8ee5 14968 struct it *it;
a2889657 14969 int depth;
5f5c8ee5 14970 int field_width, precision;
0fcf414f 14971 Lisp_Object elt, props;
c53a1624 14972 int risky;
a2889657 14973{
5f5c8ee5 14974 int n = 0, field, prec;
0fcf414f 14975 int literal = 0;
5f5c8ee5 14976
a2889657 14977 tail_recurse:
1a89be1e
SM
14978 if (depth > 100)
14979 elt = build_string ("*too-deep*");
a2889657
JB
14980
14981 depth++;
14982
0220c518 14983 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
14984 {
14985 case Lisp_String:
14986 {
14987 /* A string: output it and check for %-constructs within it. */
5f5c8ee5 14988 unsigned char c;
50f80c2f 14989 const unsigned char *this, *lisp_string;
5f5c8ee5 14990
c53a1624 14991 if (!NILP (props) || risky)
0fcf414f
RS
14992 {
14993 Lisp_Object oprops, aelt;
14994 oprops = Ftext_properties_at (make_number (0), elt);
c53a1624
RS
14995
14996 if (NILP (Fequal (props, oprops)) || risky)
0fcf414f 14997 {
ae02e06a
RS
14998 /* If the starting string has properties,
14999 merge the specified ones onto the existing ones. */
c53a1624 15000 if (! NILP (oprops) && !risky)
ae02e06a
RS
15001 {
15002 Lisp_Object tem;
15003
15004 oprops = Fcopy_sequence (oprops);
15005 tem = props;
15006 while (CONSP (tem))
15007 {
15008 oprops = Fplist_put (oprops, XCAR (tem),
15009 XCAR (XCDR (tem)));
15010 tem = XCDR (XCDR (tem));
15011 }
15012 props = oprops;
15013 }
15014
0fcf414f
RS
15015 aelt = Fassoc (elt, mode_line_proptrans_alist);
15016 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
adb63af1
RS
15017 {
15018 mode_line_proptrans_alist
15019 = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist));
15020 elt = XCAR (aelt);
15021 }
0fcf414f
RS
15022 else
15023 {
adb63af1
RS
15024 Lisp_Object tem;
15025
0fcf414f 15026 elt = Fcopy_sequence (elt);
dc3b2c8b
SM
15027 Fset_text_properties (make_number (0), Flength (elt),
15028 props, elt);
adb63af1 15029 /* Add this item to mode_line_proptrans_alist. */
0fcf414f
RS
15030 mode_line_proptrans_alist
15031 = Fcons (Fcons (elt, props),
15032 mode_line_proptrans_alist);
adb63af1
RS
15033 /* Truncate mode_line_proptrans_alist
15034 to at most 50 elements. */
15035 tem = Fnthcdr (make_number (50),
15036 mode_line_proptrans_alist);
15037 if (! NILP (tem))
15038 XSETCDR (tem, Qnil);
0fcf414f
RS
15039 }
15040 }
15041 }
15042
2051c264 15043 this = SDATA (elt);
ae02e06a
RS
15044 lisp_string = this;
15045
0fcf414f
RS
15046 if (literal)
15047 {
15048 prec = precision - n;
15049 if (frame_title_ptr)
2051c264 15050 n += store_frame_title (SDATA (elt), -1, prec);
fec8f23e
KS
15051 else if (!NILP (mode_line_string_list))
15052 n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
0fcf414f
RS
15053 else
15054 n += display_string (NULL, elt, Qnil, 0, 0, it,
15055 0, prec, 0, STRING_MULTIBYTE (elt));
15056
15057 break;
15058 }
15059
5f5c8ee5
GM
15060 while ((precision <= 0 || n < precision)
15061 && *this
15062 && (frame_title_ptr
fec8f23e 15063 || !NILP (mode_line_string_list)
5f5c8ee5 15064 || it->current_x < it->last_visible_x))
a2889657 15065 {
50f80c2f 15066 const unsigned char *last = this;
5f5c8ee5
GM
15067
15068 /* Advance to end of string or next format specifier. */
a2889657
JB
15069 while ((c = *this++) != '\0' && c != '%')
15070 ;
2311178e 15071
a2889657
JB
15072 if (this - 1 != last)
15073 {
5f5c8ee5
GM
15074 /* Output to end of string or up to '%'. Field width
15075 is length of string. Don't output more than
15076 PRECISION allows us. */
d26b89b8 15077 --this;
eaaa65b0
GM
15078
15079 prec = chars_in_text (last, this - last);
5f5c8ee5
GM
15080 if (precision > 0 && prec > precision - n)
15081 prec = precision - n;
2311178e 15082
d39b6696 15083 if (frame_title_ptr)
d26b89b8 15084 n += store_frame_title (last, 0, prec);
fec8f23e
KS
15085 else if (!NILP (mode_line_string_list))
15086 {
15087 int bytepos = last - lisp_string;
15088 int charpos = string_byte_to_char (elt, bytepos);
15089 n += store_mode_line_string (NULL,
15090 Fsubstring (elt, make_number (charpos),
15091 make_number (charpos + prec)),
15092 0, 0, 0, Qnil);
15093 }
d39b6696 15094 else
eaaa65b0
GM
15095 {
15096 int bytepos = last - lisp_string;
15097 int charpos = string_byte_to_char (elt, bytepos);
15098 n += display_string (NULL, elt, Qnil, 0, charpos,
ca77144d
GM
15099 it, 0, prec, 0,
15100 STRING_MULTIBYTE (elt));
eaaa65b0 15101 }
a2889657
JB
15102 }
15103 else /* c == '%' */
15104 {
50f80c2f 15105 const unsigned char *percent_position = this;
2311178e 15106
5f5c8ee5
GM
15107 /* Get the specified minimum width. Zero means
15108 don't pad. */
15109 field = 0;
a2889657 15110 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 15111 field = field * 10 + c - '0';
a2889657 15112
5f5c8ee5
GM
15113 /* Don't pad beyond the total padding allowed. */
15114 if (field_width - n > 0 && field > field_width - n)
15115 field = field_width - n;
a2889657 15116
5f5c8ee5
GM
15117 /* Note that either PRECISION <= 0 or N < PRECISION. */
15118 prec = precision - n;
2311178e 15119
a2889657 15120 if (c == 'M')
5f5c8ee5 15121 n += display_mode_element (it, depth, field, prec,
c53a1624
RS
15122 Vglobal_mode_string, props,
15123 risky);
a2889657 15124 else if (c != 0)
d39b6696 15125 {
72f62cb5 15126 int multibyte;
ae02e06a
RS
15127 int bytepos, charpos;
15128 unsigned char *spec;
2311178e 15129
ae02e06a
RS
15130 bytepos = percent_position - lisp_string;
15131 charpos = (STRING_MULTIBYTE (elt)
15132 ? string_byte_to_char (elt, bytepos)
15133 : bytepos);
15134
15135 spec
72f62cb5
GM
15136 = decode_mode_spec (it->w, c, field, prec, &multibyte);
15137
d39b6696 15138 if (frame_title_ptr)
5f5c8ee5 15139 n += store_frame_title (spec, field, prec);
fec8f23e
KS
15140 else if (!NILP (mode_line_string_list))
15141 {
15142 int len = strlen (spec);
15143 Lisp_Object tem = make_string (spec, len);
15144 props = Ftext_properties_at (make_number (charpos), elt);
15145 /* Should only keep face property in props */
15146 n += store_mode_line_string (NULL, tem, 0, field, prec, props);
15147 }
d39b6696 15148 else
5f5c8ee5 15149 {
ae02e06a 15150 int nglyphs_before, nwritten;
2311178e 15151
72f62cb5 15152 nglyphs_before = it->glyph_row->used[TEXT_AREA];
72f62cb5
GM
15153 nwritten = display_string (spec, Qnil, elt,
15154 charpos, 0, it,
15155 field, prec, 0,
15156 multibyte);
5f5c8ee5
GM
15157
15158 /* Assign to the glyphs written above the
15159 string where the `%x' came from, position
15160 of the `%'. */
15161 if (nwritten > 0)
15162 {
15163 struct glyph *glyph
15164 = (it->glyph_row->glyphs[TEXT_AREA]
15165 + nglyphs_before);
15166 int i;
15167
15168 for (i = 0; i < nwritten; ++i)
15169 {
15170 glyph[i].object = elt;
15171 glyph[i].charpos = charpos;
15172 }
2311178e 15173
5f5c8ee5
GM
15174 n += nwritten;
15175 }
15176 }
d39b6696 15177 }
b8523839
AS
15178 else /* c == 0 */
15179 break;
a2889657
JB
15180 }
15181 }
15182 }
15183 break;
15184
15185 case Lisp_Symbol:
15186 /* A symbol: process the value of the symbol recursively
15187 as if it appeared here directly. Avoid error if symbol void.
15188 Special case: if value of symbol is a string, output the string
15189 literally. */
15190 {
15191 register Lisp_Object tem;
c53a1624
RS
15192
15193 /* If the variable is not marked as risky to set
15194 then its contents are risky to use. */
15195 if (NILP (Fget (elt, Qrisky_local_variable)))
15196 risky = 1;
15197
a2889657 15198 tem = Fboundp (elt);
265a9e55 15199 if (!NILP (tem))
a2889657
JB
15200 {
15201 tem = Fsymbol_value (elt);
15202 /* If value is a string, output that string literally:
15203 don't check for % within it. */
e24c997d 15204 if (STRINGP (tem))
0fcf414f
RS
15205 literal = 1;
15206
15207 if (!EQ (tem, elt))
5f5c8ee5
GM
15208 {
15209 /* Give up right away for nil or t. */
15210 elt = tem;
15211 goto tail_recurse;
15212 }
a2889657
JB
15213 }
15214 }
15215 break;
15216
15217 case Lisp_Cons:
15218 {
15219 register Lisp_Object car, tem;
15220
0fcf414f
RS
15221 /* A cons cell: five distinct cases.
15222 If first element is :eval or :propertize, do something special.
a2889657
JB
15223 If first element is a string or a cons, process all the elements
15224 and effectively concatenate them.
15225 If first element is a negative number, truncate displaying cdr to
15226 at most that many characters. If positive, pad (with spaces)
15227 to at least that many characters.
15228 If first element is a symbol, process the cadr or caddr recursively
15229 according to whether the symbol's value is non-nil or nil. */
9472f927 15230 car = XCAR (elt);
0fcf414f 15231 if (EQ (car, QCeval))
5f5c8ee5
GM
15232 {
15233 /* An element of the form (:eval FORM) means evaluate FORM
15234 and use the result as mode line elements. */
0fcf414f 15235
c53a1624
RS
15236 if (risky)
15237 break;
15238
0fcf414f
RS
15239 if (CONSP (XCDR (elt)))
15240 {
15241 Lisp_Object spec;
15242 spec = safe_eval (XCAR (XCDR (elt)));
15243 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
15244 precision - n, spec, props,
15245 risky);
0fcf414f
RS
15246 }
15247 }
15248 else if (EQ (car, QCpropertize))
15249 {
c53a1624
RS
15250 /* An element of the form (:propertize ELT PROPS...)
15251 means display ELT but applying properties PROPS. */
15252
15253 if (risky)
15254 break;
15255
0fcf414f 15256 if (CONSP (XCDR (elt)))
c53a1624
RS
15257 n += display_mode_element (it, depth, field_width - n,
15258 precision - n, XCAR (XCDR (elt)),
15259 XCDR (XCDR (elt)), risky);
5f5c8ee5
GM
15260 }
15261 else if (SYMBOLP (car))
a2889657
JB
15262 {
15263 tem = Fboundp (car);
9472f927 15264 elt = XCDR (elt);
e24c997d 15265 if (!CONSP (elt))
a2889657
JB
15266 goto invalid;
15267 /* elt is now the cdr, and we know it is a cons cell.
15268 Use its car if CAR has a non-nil value. */
265a9e55 15269 if (!NILP (tem))
a2889657
JB
15270 {
15271 tem = Fsymbol_value (car);
265a9e55 15272 if (!NILP (tem))
9472f927
GM
15273 {
15274 elt = XCAR (elt);
15275 goto tail_recurse;
15276 }
a2889657
JB
15277 }
15278 /* Symbol's value is nil (or symbol is unbound)
15279 Get the cddr of the original list
15280 and if possible find the caddr and use that. */
9472f927 15281 elt = XCDR (elt);
265a9e55 15282 if (NILP (elt))
a2889657 15283 break;
e24c997d 15284 else if (!CONSP (elt))
a2889657 15285 goto invalid;
9472f927 15286 elt = XCAR (elt);
a2889657
JB
15287 goto tail_recurse;
15288 }
e24c997d 15289 else if (INTEGERP (car))
a2889657
JB
15290 {
15291 register int lim = XINT (car);
9472f927 15292 elt = XCDR (elt);
a2889657 15293 if (lim < 0)
5f5c8ee5
GM
15294 {
15295 /* Negative int means reduce maximum width. */
15296 if (precision <= 0)
15297 precision = -lim;
15298 else
15299 precision = min (precision, -lim);
15300 }
a2889657
JB
15301 else if (lim > 0)
15302 {
15303 /* Padding specified. Don't let it be more than
15304 current maximum. */
5f5c8ee5
GM
15305 if (precision > 0)
15306 lim = min (precision, lim);
15307
a2889657
JB
15308 /* If that's more padding than already wanted, queue it.
15309 But don't reduce padding already specified even if
15310 that is beyond the current truncation point. */
5f5c8ee5 15311 field_width = max (lim, field_width);
a2889657
JB
15312 }
15313 goto tail_recurse;
15314 }
e24c997d 15315 else if (STRINGP (car) || CONSP (car))
a2889657
JB
15316 {
15317 register int limit = 50;
5f5c8ee5
GM
15318 /* Limit is to protect against circular lists. */
15319 while (CONSP (elt)
15320 && --limit > 0
15321 && (precision <= 0 || n < precision))
a2889657 15322 {
5f5c8ee5 15323 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
15324 precision - n, XCAR (elt),
15325 props, risky);
9472f927 15326 elt = XCDR (elt);
a2889657
JB
15327 }
15328 }
15329 }
15330 break;
15331
15332 default:
15333 invalid:
1a89be1e
SM
15334 elt = build_string ("*invalid*");
15335 goto tail_recurse;
a2889657
JB
15336 }
15337
5f5c8ee5
GM
15338 /* Pad to FIELD_WIDTH. */
15339 if (field_width > 0 && n < field_width)
15340 {
15341 if (frame_title_ptr)
15342 n += store_frame_title ("", field_width - n, 0);
fec8f23e
KS
15343 else if (!NILP (mode_line_string_list))
15344 n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
5f5c8ee5
GM
15345 else
15346 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
15347 0, 0, 0);
15348 }
2311178e 15349
5f5c8ee5 15350 return n;
a2889657 15351}
5f5c8ee5 15352
fec8f23e
KS
15353/* Store a mode-line string element in mode_line_string_list.
15354
15355 If STRING is non-null, display that C string. Otherwise, the Lisp
15356 string LISP_STRING is displayed.
15357
15358 FIELD_WIDTH is the minimum number of output glyphs to produce.
15359 If STRING has fewer characters than FIELD_WIDTH, pad to the right
15360 with spaces. FIELD_WIDTH <= 0 means don't pad.
15361
15362 PRECISION is the maximum number of characters to output from
15363 STRING. PRECISION <= 0 means don't truncate the string.
15364
15365 If COPY_STRING is non-zero, make a copy of LISP_STRING before adding
15366 properties to the string.
15367
7d0393cf 15368 PROPS are the properties to add to the string.
fec8f23e
KS
15369 The mode_line_string_face face property is always added to the string.
15370 */
15371
15372static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
15373 char *string;
15374 Lisp_Object lisp_string;
15375 int copy_string;
15376 int field_width;
15377 int precision;
15378 Lisp_Object props;
15379{
15380 int len;
15381 int n = 0;
15382
15383 if (string != NULL)
15384 {
15385 len = strlen (string);
15386 if (precision > 0 && len > precision)
15387 len = precision;
15388 lisp_string = make_string (string, len);
15389 if (NILP (props))
15390 props = mode_line_string_face_prop;
15391 else if (!NILP (mode_line_string_face))
15392 {
15393 Lisp_Object face = Fplist_get (props, Qface);
15394 props = Fcopy_sequence (props);
15395 if (NILP (face))
15396 face = mode_line_string_face;
15397 else
15398 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
15399 props = Fplist_put (props, Qface, face);
15400 }
15401 Fadd_text_properties (make_number (0), make_number (len),
15402 props, lisp_string);
15403 }
7d0393cf 15404 else
fec8f23e 15405 {
c8224325 15406 len = XFASTINT (Flength (lisp_string));
fec8f23e
KS
15407 if (precision > 0 && len > precision)
15408 {
15409 len = precision;
15410 lisp_string = Fsubstring (lisp_string, make_number (0), make_number (len));
15411 precision = -1;
15412 }
15413 if (!NILP (mode_line_string_face))
15414 {
15415 Lisp_Object face;
15416 if (NILP (props))
15417 props = Ftext_properties_at (make_number (0), lisp_string);
15418 face = Fplist_get (props, Qface);
15419 if (NILP (face))
15420 face = mode_line_string_face;
15421 else
15422 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
15423 props = Fcons (Qface, Fcons (face, Qnil));
15424 if (copy_string)
15425 lisp_string = Fcopy_sequence (lisp_string);
15426 }
15427 if (!NILP (props))
15428 Fadd_text_properties (make_number (0), make_number (len),
15429 props, lisp_string);
15430 }
15431
15432 if (len > 0)
15433 {
15434 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 15435 n += len;
fec8f23e
KS
15436 }
15437
15438 if (field_width > len)
15439 {
15440 field_width -= len;
15441 lisp_string = Fmake_string (make_number (field_width), make_number (' '));
15442 if (!NILP (props))
15443 Fadd_text_properties (make_number (0), make_number (field_width),
15444 props, lisp_string);
15445 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 15446 n += field_width;
fec8f23e
KS
15447 }
15448
15449 return n;
15450}
15451
5f5c8ee5 15452
8143e6ab 15453DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
fec8f23e 15454 0, 3, 0,
8143e6ab
KS
15455 doc: /* Return the mode-line of selected window as a string.
15456First optional arg FORMAT specifies a different format string (see
8b22c65a 15457`mode-line-format' for details) to use. If FORMAT is t, return
8143e6ab 15458the buffer's header-line. Second optional arg WINDOW specifies a
fec8f23e
KS
15459different window to use as the context for the formatting.
15460If third optional arg NO-PROPS is non-nil, string is not propertized. */)
15461 (format, window, no_props)
15462 Lisp_Object format, window, no_props;
8143e6ab
KS
15463{
15464 struct it it;
8143e6ab
KS
15465 int len;
15466 struct window *w;
15467 struct buffer *old_buffer = NULL;
fec8f23e 15468 enum face_id face_id = DEFAULT_FACE_ID;
8143e6ab
KS
15469
15470 if (NILP (window))
15471 window = selected_window;
15472 CHECK_WINDOW (window);
15473 w = XWINDOW (window);
15474 CHECK_BUFFER (w->buffer);
15475
15476 if (XBUFFER (w->buffer) != current_buffer)
15477 {
15478 old_buffer = current_buffer;
15479 set_buffer_internal_1 (XBUFFER (w->buffer));
15480 }
15481
15482 if (NILP (format) || EQ (format, Qt))
fec8f23e
KS
15483 {
15484 face_id = NILP (format)
15485 ? CURRENT_MODE_LINE_FACE_ID (w) :
15486 HEADER_LINE_FACE_ID;
15487 format = NILP (format)
15488 ? current_buffer->mode_line_format
15489 : current_buffer->header_line_format;
15490 }
15491
15492 init_iterator (&it, w, -1, -1, NULL, face_id);
8143e6ab 15493
fec8f23e
KS
15494 if (NILP (no_props))
15495 {
15496 mode_line_string_face =
15497 (face_id == MODE_LINE_FACE_ID ? Qmode_line :
15498 face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
15499 face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
8143e6ab 15500
fec8f23e
KS
15501 mode_line_string_face_prop =
15502 NILP (mode_line_string_face) ? Qnil :
15503 Fcons (Qface, Fcons (mode_line_string_face, Qnil));
15504
15505 /* We need a dummy last element in mode_line_string_list to
15506 indicate we are building the propertized mode-line string.
15507 Using mode_line_string_face_prop here GC protects it. */
7d0393cf 15508 mode_line_string_list =
fec8f23e
KS
15509 Fcons (mode_line_string_face_prop, Qnil);
15510 frame_title_ptr = NULL;
15511 }
15512 else
15513 {
15514 mode_line_string_face_prop = Qnil;
15515 mode_line_string_list = Qnil;
15516 frame_title_ptr = frame_title_buf;
15517 }
8143e6ab
KS
15518
15519 push_frame_kboard (it.f);
15520 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
15521 pop_frame_kboard ();
15522
15523 if (old_buffer)
15524 set_buffer_internal_1 (old_buffer);
15525
fec8f23e
KS
15526 if (NILP (no_props))
15527 {
15528 Lisp_Object str;
15529 mode_line_string_list = Fnreverse (mode_line_string_list);
15530 str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list),
15531 make_string ("", 0));
15532 mode_line_string_face_prop = Qnil;
15533 mode_line_string_list = Qnil;
15534 return str;
15535 }
15536
8143e6ab
KS
15537 len = frame_title_ptr - frame_title_buf;
15538 if (len > 0 && frame_title_ptr[-1] == '-')
15539 {
15540 /* Mode lines typically ends with numerous dashes; reduce to two dashes. */
15541 while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-')
15542 ;
15543 frame_title_ptr += 3; /* restore last non-dash + two dashes */
15544 if (len > frame_title_ptr - frame_title_buf)
15545 len = frame_title_ptr - frame_title_buf;
15546 }
15547
15548 frame_title_ptr = NULL;
15549 return make_string (frame_title_buf, len);
15550}
15551
766525bc
RS
15552/* Write a null-terminated, right justified decimal representation of
15553 the positive integer D to BUF using a minimal field width WIDTH. */
15554
15555static void
15556pint2str (buf, width, d)
15557 register char *buf;
15558 register int width;
15559 register int d;
15560{
15561 register char *p = buf;
2311178e 15562
766525bc 15563 if (d <= 0)
5f5c8ee5 15564 *p++ = '0';
766525bc 15565 else
5f5c8ee5 15566 {
766525bc 15567 while (d > 0)
5f5c8ee5 15568 {
766525bc
RS
15569 *p++ = d % 10 + '0';
15570 d /= 10;
5f5c8ee5
GM
15571 }
15572 }
2311178e 15573
5f5c8ee5
GM
15574 for (width -= (int) (p - buf); width > 0; --width)
15575 *p++ = ' ';
766525bc
RS
15576 *p-- = '\0';
15577 while (p > buf)
5f5c8ee5 15578 {
766525bc
RS
15579 d = *buf;
15580 *buf++ = *p;
15581 *p-- = d;
5f5c8ee5 15582 }
766525bc
RS
15583}
15584
5f5c8ee5 15585/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
15586 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
15587 type of CODING_SYSTEM. Return updated pointer into BUF. */
15588
6693a99a 15589static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 15590
1c9241f5
KH
15591static char *
15592decode_mode_spec_coding (coding_system, buf, eol_flag)
15593 Lisp_Object coding_system;
15594 register char *buf;
15595 int eol_flag;
15596{
1e1078d6 15597 Lisp_Object val;
916848d8 15598 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
50f80c2f 15599 const unsigned char *eol_str;
302f2b38
EZ
15600 int eol_str_len;
15601 /* The EOL conversion we are using. */
15602 Lisp_Object eoltype;
1e1078d6 15603
4a09dee0 15604 val = Fget (coding_system, Qcoding_system);
085536c2 15605 eoltype = Qnil;
1c9241f5 15606
4a09dee0 15607 if (!VECTORP (val)) /* Not yet decided. */
1c9241f5 15608 {
916848d8
RS
15609 if (multibyte)
15610 *buf++ = '-';
21e989e3 15611 if (eol_flag)
302f2b38 15612 eoltype = eol_mnemonic_undecided;
1e1078d6 15613 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
15614 }
15615 else
15616 {
1e1078d6
RS
15617 Lisp_Object eolvalue;
15618
15619 eolvalue = Fget (coding_system, Qeol_type);
15620
916848d8 15621 if (multibyte)
a61b7058 15622 *buf++ = XFASTINT (AREF (val, 1));
916848d8 15623
1c9241f5
KH
15624 if (eol_flag)
15625 {
1e1078d6
RS
15626 /* The EOL conversion that is normal on this system. */
15627
15628 if (NILP (eolvalue)) /* Not yet decided. */
15629 eoltype = eol_mnemonic_undecided;
15630 else if (VECTORP (eolvalue)) /* Not yet decided. */
15631 eoltype = eol_mnemonic_undecided;
15632 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
15633 eoltype = (XFASTINT (eolvalue) == 0
15634 ? eol_mnemonic_unix
15635 : (XFASTINT (eolvalue) == 1
15636 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
15637 }
15638 }
2311178e 15639
302f2b38
EZ
15640 if (eol_flag)
15641 {
15642 /* Mention the EOL conversion if it is not the usual one. */
15643 if (STRINGP (eoltype))
15644 {
2051c264
GM
15645 eol_str = SDATA (eoltype);
15646 eol_str_len = SBYTES (eoltype);
302f2b38 15647 }
f30b3499
KH
15648 else if (INTEGERP (eoltype)
15649 && CHAR_VALID_P (XINT (eoltype), 0))
15650 {
50f80c2f
KR
15651 unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
15652 eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
15653 eol_str = tmp;
f30b3499 15654 }
302f2b38
EZ
15655 else
15656 {
15657 eol_str = invalid_eol_type;
15658 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 15659 }
f30b3499 15660 bcopy (eol_str, buf, eol_str_len);
302f2b38 15661 buf += eol_str_len;
1c9241f5 15662 }
302f2b38 15663
1c9241f5
KH
15664 return buf;
15665}
15666
a2889657 15667/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
15668 generated by character C. PRECISION >= 0 means don't return a
15669 string longer than that value. FIELD_WIDTH > 0 means pad the
72f62cb5
GM
15670 string returned with spaces to that value. Return 1 in *MULTIBYTE
15671 if the result is multibyte text. */
a2889657 15672
11e82b76
JB
15673static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
15674
a2889657 15675static char *
72f62cb5 15676decode_mode_spec (w, c, field_width, precision, multibyte)
a2889657 15677 struct window *w;
68c45bf0 15678 register int c;
5f5c8ee5 15679 int field_width, precision;
72f62cb5 15680 int *multibyte;
a2889657 15681{
0b67772d 15682 Lisp_Object obj;
5f5c8ee5
GM
15683 struct frame *f = XFRAME (WINDOW_FRAME (w));
15684 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 15685 struct buffer *b = XBUFFER (w->buffer);
a2889657 15686
0b67772d 15687 obj = Qnil;
72f62cb5 15688 *multibyte = 0;
a2889657
JB
15689
15690 switch (c)
15691 {
1af9f229
RS
15692 case '*':
15693 if (!NILP (b->read_only))
15694 return "%";
15695 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
15696 return "*";
15697 return "-";
15698
15699 case '+':
15700 /* This differs from %* only for a modified read-only buffer. */
15701 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
15702 return "*";
15703 if (!NILP (b->read_only))
15704 return "%";
15705 return "-";
15706
15707 case '&':
15708 /* This differs from %* in ignoring read-only-ness. */
15709 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
15710 return "*";
15711 return "-";
15712
15713 case '%':
15714 return "%";
15715
2311178e 15716 case '[':
1af9f229
RS
15717 {
15718 int i;
15719 char *p;
15720
15721 if (command_loop_level > 5)
15722 return "[[[... ";
15723 p = decode_mode_spec_buf;
15724 for (i = 0; i < command_loop_level; i++)
15725 *p++ = '[';
15726 *p = 0;
15727 return decode_mode_spec_buf;
15728 }
15729
2311178e 15730 case ']':
1af9f229
RS
15731 {
15732 int i;
15733 char *p;
15734
15735 if (command_loop_level > 5)
15736 return " ...]]]";
15737 p = decode_mode_spec_buf;
15738 for (i = 0; i < command_loop_level; i++)
15739 *p++ = ']';
15740 *p = 0;
15741 return decode_mode_spec_buf;
15742 }
15743
15744 case '-':
15745 {
1af9f229 15746 register int i;
5f5c8ee5
GM
15747
15748 /* Let lots_of_dashes be a string of infinite length. */
fec8f23e
KS
15749 if (!NILP (mode_line_string_list))
15750 return "--";
5f5c8ee5
GM
15751 if (field_width <= 0
15752 || field_width > sizeof (lots_of_dashes))
1af9f229 15753 {
5f5c8ee5
GM
15754 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
15755 decode_mode_spec_buf[i] = '-';
15756 decode_mode_spec_buf[i] = '\0';
15757 return decode_mode_spec_buf;
1af9f229 15758 }
5f5c8ee5
GM
15759 else
15760 return lots_of_dashes;
1af9f229
RS
15761 }
15762
2311178e 15763 case 'b':
d39b6696 15764 obj = b->name;
a2889657
JB
15765 break;
15766
1af9f229
RS
15767 case 'c':
15768 {
2311178e 15769 int col = (int) current_column (); /* iftc */
ac90c44f 15770 w->column_number_displayed = make_number (col);
5f5c8ee5 15771 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
15772 return decode_mode_spec_buf;
15773 }
15774
15775 case 'F':
15776 /* %F displays the frame name. */
5f5c8ee5 15777 if (!NILP (f->title))
2051c264 15778 return (char *) SDATA (f->title);
fd8ff63d 15779 if (f->explicit_name || ! FRAME_WINDOW_P (f))
2051c264 15780 return (char *) SDATA (f->name);
9c6da96f 15781 return "Emacs";
1af9f229 15782
2311178e 15783 case 'f':
d39b6696 15784 obj = b->filename;
a2889657
JB
15785 break;
15786
aa6d10fa
RS
15787 case 'l':
15788 {
12adba34
RS
15789 int startpos = XMARKER (w->start)->charpos;
15790 int startpos_byte = marker_byte_position (w->start);
15791 int line, linepos, linepos_byte, topline;
aa6d10fa 15792 int nlines, junk;
da8b7f4f 15793 int height = WINDOW_TOTAL_LINES (w);
aa6d10fa 15794
2311178e 15795 /* If we decided that this buffer isn't suitable for line numbers,
aa6d10fa
RS
15796 don't forget that too fast. */
15797 if (EQ (w->base_line_pos, w->buffer))
766525bc 15798 goto no_value;
5300fd39
RS
15799 /* But do forget it, if the window shows a different buffer now. */
15800 else if (BUFFERP (w->base_line_pos))
15801 w->base_line_pos = Qnil;
aa6d10fa
RS
15802
15803 /* If the buffer is very big, don't waste time. */
37d034d3 15804 if (INTEGERP (Vline_number_display_limit)
090703f4 15805 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
aa6d10fa
RS
15806 {
15807 w->base_line_pos = Qnil;
15808 w->base_line_number = Qnil;
766525bc 15809 goto no_value;
aa6d10fa
RS
15810 }
15811
15812 if (!NILP (w->base_line_number)
15813 && !NILP (w->base_line_pos)
12adba34 15814 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
15815 {
15816 line = XFASTINT (w->base_line_number);
15817 linepos = XFASTINT (w->base_line_pos);
12adba34 15818 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
15819 }
15820 else
15821 {
15822 line = 1;
d39b6696 15823 linepos = BUF_BEGV (b);
12adba34 15824 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
15825 }
15826
15827 /* Count lines from base line to window start position. */
12adba34
RS
15828 nlines = display_count_lines (linepos, linepos_byte,
15829 startpos_byte,
15830 startpos, &junk);
aa6d10fa
RS
15831
15832 topline = nlines + line;
15833
15834 /* Determine a new base line, if the old one is too close
15835 or too far away, or if we did not have one.
15836 "Too close" means it's plausible a scroll-down would
15837 go back past it. */
d39b6696 15838 if (startpos == BUF_BEGV (b))
aa6d10fa 15839 {
ac90c44f
GM
15840 w->base_line_number = make_number (topline);
15841 w->base_line_pos = make_number (BUF_BEGV (b));
aa6d10fa
RS
15842 }
15843 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 15844 || linepos == BUF_BEGV (b))
aa6d10fa 15845 {
d39b6696 15846 int limit = BUF_BEGV (b);
12adba34 15847 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 15848 int position;
5d121aec 15849 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
15850
15851 if (startpos - distance > limit)
12adba34
RS
15852 {
15853 limit = startpos - distance;
15854 limit_byte = CHAR_TO_BYTE (limit);
15855 }
aa6d10fa 15856
12adba34
RS
15857 nlines = display_count_lines (startpos, startpos_byte,
15858 limit_byte,
15859 - (height * 2 + 30),
aa6d10fa 15860 &position);
2311178e 15861 /* If we couldn't find the lines we wanted within
5d121aec 15862 line_number_display_limit_width chars per line,
aa6d10fa 15863 give up on line numbers for this window. */
12adba34 15864 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
15865 {
15866 w->base_line_pos = w->buffer;
15867 w->base_line_number = Qnil;
766525bc 15868 goto no_value;
aa6d10fa
RS
15869 }
15870
ac90c44f
GM
15871 w->base_line_number = make_number (topline - nlines);
15872 w->base_line_pos = make_number (BYTE_TO_CHAR (position));
aa6d10fa
RS
15873 }
15874
15875 /* Now count lines from the start pos to point. */
12adba34
RS
15876 nlines = display_count_lines (startpos, startpos_byte,
15877 PT_BYTE, PT, &junk);
aa6d10fa
RS
15878
15879 /* Record that we did display the line number. */
15880 line_number_displayed = 1;
15881
15882 /* Make the string to show. */
5f5c8ee5 15883 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 15884 return decode_mode_spec_buf;
766525bc
RS
15885 no_value:
15886 {
15887 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
15888 int pad = field_width - 2;
15889 while (pad-- > 0)
15890 *p++ = ' ';
15891 *p++ = '?';
b357b9d4
KR
15892 *p++ = '?';
15893 *p = '\0';
766525bc
RS
15894 return decode_mode_spec_buf;
15895 }
aa6d10fa
RS
15896 }
15897 break;
15898
2311178e 15899 case 'm':
d39b6696 15900 obj = b->mode_name;
a2889657
JB
15901 break;
15902
15903 case 'n':
d39b6696 15904 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
15905 return " Narrow";
15906 break;
15907
a2889657
JB
15908 case 'p':
15909 {
15910 int pos = marker_position (w->start);
d39b6696 15911 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 15912
d39b6696 15913 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 15914 {
d39b6696 15915 if (pos <= BUF_BEGV (b))
a2889657
JB
15916 return "All";
15917 else
15918 return "Bottom";
15919 }
d39b6696 15920 else if (pos <= BUF_BEGV (b))
a2889657
JB
15921 return "Top";
15922 else
15923 {
3c7d31b9
RS
15924 if (total > 1000000)
15925 /* Do it differently for a large value, to avoid overflow. */
15926 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
15927 else
15928 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
15929 /* We can't normally display a 3-digit number,
15930 so get us a 2-digit number that is close. */
15931 if (total == 100)
15932 total = 99;
15933 sprintf (decode_mode_spec_buf, "%2d%%", total);
15934 return decode_mode_spec_buf;
15935 }
15936 }
15937
8ffcb79f
RS
15938 /* Display percentage of size above the bottom of the screen. */
15939 case 'P':
15940 {
15941 int toppos = marker_position (w->start);
d39b6696
KH
15942 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
15943 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 15944
d39b6696 15945 if (botpos >= BUF_ZV (b))
8ffcb79f 15946 {
d39b6696 15947 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
15948 return "All";
15949 else
15950 return "Bottom";
15951 }
15952 else
15953 {
3c7d31b9
RS
15954 if (total > 1000000)
15955 /* Do it differently for a large value, to avoid overflow. */
15956 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
15957 else
15958 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
15959 /* We can't normally display a 3-digit number,
15960 so get us a 2-digit number that is close. */
15961 if (total == 100)
15962 total = 99;
d39b6696 15963 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
15964 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
15965 else
15966 sprintf (decode_mode_spec_buf, "%2d%%", total);
15967 return decode_mode_spec_buf;
15968 }
15969 }
15970
1af9f229
RS
15971 case 's':
15972 /* status of process */
15973 obj = Fget_buffer_process (w->buffer);
15974 if (NILP (obj))
15975 return "no process";
15976#ifdef subprocesses
15977 obj = Fsymbol_name (Fprocess_status (obj));
15978#endif
15979 break;
d39b6696 15980
1af9f229
RS
15981 case 't': /* indicate TEXT or BINARY */
15982#ifdef MODE_LINE_BINARY_TEXT
15983 return MODE_LINE_BINARY_TEXT (b);
15984#else
15985 return "T";
15986#endif
1c9241f5
KH
15987
15988 case 'z':
15989 /* coding-system (not including end-of-line format) */
15990 case 'Z':
15991 /* coding-system (including end-of-line type) */
15992 {
15993 int eol_flag = (c == 'Z');
539b4d41 15994 char *p = decode_mode_spec_buf;
1c9241f5 15995
d30e754b 15996 if (! FRAME_WINDOW_P (f))
1c9241f5 15997 {
11c52c4f
RS
15998 /* No need to mention EOL here--the terminal never needs
15999 to do EOL conversion. */
16000 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
16001 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 16002 }
f13c925f 16003 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 16004 p, eol_flag);
f13c925f 16005
11c52c4f 16006#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
16007#ifdef subprocesses
16008 obj = Fget_buffer_process (Fcurrent_buffer ());
16009 if (PROCESSP (obj))
16010 {
16011 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
16012 p, eol_flag);
16013 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
16014 p, eol_flag);
16015 }
16016#endif /* subprocesses */
11c52c4f 16017#endif /* 0 */
1c9241f5
KH
16018 *p = 0;
16019 return decode_mode_spec_buf;
16020 }
a2889657 16021 }
d39b6696 16022
e24c997d 16023 if (STRINGP (obj))
72f62cb5
GM
16024 {
16025 *multibyte = STRING_MULTIBYTE (obj);
2051c264 16026 return (char *) SDATA (obj);
72f62cb5 16027 }
a2889657
JB
16028 else
16029 return "";
16030}
5f5c8ee5
GM
16031
16032
12adba34
RS
16033/* Count up to COUNT lines starting from START / START_BYTE.
16034 But don't go beyond LIMIT_BYTE.
16035 Return the number of lines thus found (always nonnegative).
59b49f63 16036
12adba34 16037 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
16038
16039static int
12adba34
RS
16040display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
16041 int start, start_byte, limit_byte, count;
16042 int *byte_pos_ptr;
59b49f63 16043{
59b49f63
RS
16044 register unsigned char *cursor;
16045 unsigned char *base;
16046
16047 register int ceiling;
16048 register unsigned char *ceiling_addr;
12adba34 16049 int orig_count = count;
59b49f63
RS
16050
16051 /* If we are not in selective display mode,
16052 check only for newlines. */
12adba34
RS
16053 int selective_display = (!NILP (current_buffer->selective_display)
16054 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
16055
16056 if (count > 0)
12adba34
RS
16057 {
16058 while (start_byte < limit_byte)
16059 {
16060 ceiling = BUFFER_CEILING_OF (start_byte);
16061 ceiling = min (limit_byte - 1, ceiling);
16062 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
16063 base = (cursor = BYTE_POS_ADDR (start_byte));
16064 while (1)
16065 {
16066 if (selective_display)
16067 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
16068 ;
16069 else
16070 while (*cursor != '\n' && ++cursor != ceiling_addr)
16071 ;
16072
16073 if (cursor != ceiling_addr)
16074 {
16075 if (--count == 0)
16076 {
16077 start_byte += cursor - base + 1;
16078 *byte_pos_ptr = start_byte;
16079 return orig_count;
16080 }
16081 else
16082 if (++cursor == ceiling_addr)
16083 break;
16084 }
16085 else
16086 break;
16087 }
16088 start_byte += cursor - base;
16089 }
16090 }
59b49f63
RS
16091 else
16092 {
12adba34
RS
16093 while (start_byte > limit_byte)
16094 {
16095 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
16096 ceiling = max (limit_byte, ceiling);
16097 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
16098 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
16099 while (1)
16100 {
12adba34
RS
16101 if (selective_display)
16102 while (--cursor != ceiling_addr
16103 && *cursor != '\n' && *cursor != 015)
16104 ;
16105 else
16106 while (--cursor != ceiling_addr && *cursor != '\n')
16107 ;
16108
59b49f63
RS
16109 if (cursor != ceiling_addr)
16110 {
16111 if (++count == 0)
16112 {
12adba34
RS
16113 start_byte += cursor - base + 1;
16114 *byte_pos_ptr = start_byte;
16115 /* When scanning backwards, we should
16116 not count the newline posterior to which we stop. */
16117 return - orig_count - 1;
59b49f63
RS
16118 }
16119 }
16120 else
16121 break;
16122 }
12adba34
RS
16123 /* Here we add 1 to compensate for the last decrement
16124 of CURSOR, which took it past the valid range. */
16125 start_byte += cursor - base + 1;
59b49f63
RS
16126 }
16127 }
16128
12adba34 16129 *byte_pos_ptr = limit_byte;
aa6d10fa 16130
12adba34
RS
16131 if (count < 0)
16132 return - orig_count + count;
16133 return orig_count - count;
aa6d10fa 16134
12adba34 16135}
a2889657 16136
a2889657 16137
5f5c8ee5
GM
16138\f
16139/***********************************************************************
16140 Displaying strings
16141 ***********************************************************************/
278feba9 16142
5f5c8ee5 16143/* Display a NUL-terminated string, starting with index START.
a3788d53 16144
5f5c8ee5
GM
16145 If STRING is non-null, display that C string. Otherwise, the Lisp
16146 string LISP_STRING is displayed.
a2889657 16147
5f5c8ee5
GM
16148 If FACE_STRING is not nil, FACE_STRING_POS is a position in
16149 FACE_STRING. Display STRING or LISP_STRING with the face at
16150 FACE_STRING_POS in FACE_STRING:
a2889657 16151
5f5c8ee5
GM
16152 Display the string in the environment given by IT, but use the
16153 standard display table, temporarily.
a3788d53 16154
5f5c8ee5
GM
16155 FIELD_WIDTH is the minimum number of output glyphs to produce.
16156 If STRING has fewer characters than FIELD_WIDTH, pad to the right
16157 with spaces. If STRING has more characters, more than FIELD_WIDTH
16158 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
2311178e 16159
5f5c8ee5
GM
16160 PRECISION is the maximum number of characters to output from
16161 STRING. PRECISION < 0 means don't truncate the string.
a2889657 16162
5f5c8ee5 16163 This is roughly equivalent to printf format specifiers:
a2889657 16164
5f5c8ee5
GM
16165 FIELD_WIDTH PRECISION PRINTF
16166 ----------------------------------------
16167 -1 -1 %s
16168 -1 10 %.10s
16169 10 -1 %10s
16170 20 10 %20.10s
a2889657 16171
5f5c8ee5
GM
16172 MULTIBYTE zero means do not display multibyte chars, > 0 means do
16173 display them, and < 0 means obey the current buffer's value of
16174 enable_multibyte_characters.
278feba9 16175
5f5c8ee5 16176 Value is the number of glyphs produced. */
b1d1124b 16177
5f5c8ee5
GM
16178static int
16179display_string (string, lisp_string, face_string, face_string_pos,
16180 start, it, field_width, precision, max_x, multibyte)
16181 unsigned char *string;
16182 Lisp_Object lisp_string;
68c45bf0
PE
16183 Lisp_Object face_string;
16184 int face_string_pos;
5f5c8ee5
GM
16185 int start;
16186 struct it *it;
16187 int field_width, precision, max_x;
16188 int multibyte;
16189{
16190 int hpos_at_start = it->hpos;
16191 int saved_face_id = it->face_id;
16192 struct glyph_row *row = it->glyph_row;
16193
16194 /* Initialize the iterator IT for iteration over STRING beginning
e719f5ae 16195 with index START. */
5f5c8ee5
GM
16196 reseat_to_string (it, string, lisp_string, start,
16197 precision, field_width, multibyte);
16198
16199 /* If displaying STRING, set up the face of the iterator
16200 from LISP_STRING, if that's given. */
16201 if (STRINGP (face_string))
16202 {
16203 int endptr;
16204 struct face *face;
2311178e 16205
5f5c8ee5
GM
16206 it->face_id
16207 = face_at_string_position (it->w, face_string, face_string_pos,
16208 0, it->region_beg_charpos,
16209 it->region_end_charpos,
5de7c6f2 16210 &endptr, it->base_face_id, 0);
5f5c8ee5
GM
16211 face = FACE_FROM_ID (it->f, it->face_id);
16212 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 16213 }
a2889657 16214
5f5c8ee5
GM
16215 /* Set max_x to the maximum allowed X position. Don't let it go
16216 beyond the right edge of the window. */
16217 if (max_x <= 0)
16218 max_x = it->last_visible_x;
16219 else
16220 max_x = min (max_x, it->last_visible_x);
efc63ef0 16221
5f5c8ee5
GM
16222 /* Skip over display elements that are not visible. because IT->w is
16223 hscrolled. */
16224 if (it->current_x < it->first_visible_x)
16225 move_it_in_display_line_to (it, 100000, it->first_visible_x,
16226 MOVE_TO_POS | MOVE_TO_X);
a2889657 16227
5f5c8ee5
GM
16228 row->ascent = it->max_ascent;
16229 row->height = it->max_ascent + it->max_descent;
312246d1
GM
16230 row->phys_ascent = it->max_phys_ascent;
16231 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 16232
5f5c8ee5
GM
16233 /* This condition is for the case that we are called with current_x
16234 past last_visible_x. */
16235 while (it->current_x < max_x)
a2889657 16236 {
5f5c8ee5 16237 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 16238
5f5c8ee5
GM
16239 /* Get the next display element. */
16240 if (!get_next_display_element (it))
90adcf20 16241 break;
1c9241f5 16242
5f5c8ee5
GM
16243 /* Produce glyphs. */
16244 x_before = it->current_x;
16245 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
16246 PRODUCE_GLYPHS (it);
90adcf20 16247
5f5c8ee5
GM
16248 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
16249 i = 0;
16250 x = x_before;
16251 while (i < nglyphs)
a2889657 16252 {
5f5c8ee5 16253 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 16254
5f5c8ee5
GM
16255 if (!it->truncate_lines_p
16256 && x + glyph->pixel_width > max_x)
16257 {
16258 /* End of continued line or max_x reached. */
37be86f2
KH
16259 if (CHAR_GLYPH_PADDING_P (*glyph))
16260 {
16261 /* A wide character is unbreakable. */
16262 it->glyph_row->used[TEXT_AREA] = n_glyphs_before;
16263 it->current_x = x_before;
16264 }
16265 else
16266 {
16267 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
16268 it->current_x = x;
16269 }
5f5c8ee5
GM
16270 break;
16271 }
16272 else if (x + glyph->pixel_width > it->first_visible_x)
16273 {
16274 /* Glyph is at least partially visible. */
16275 ++it->hpos;
16276 if (x < it->first_visible_x)
16277 it->glyph_row->x = x - it->first_visible_x;
16278 }
16279 else
a2889657 16280 {
5f5c8ee5
GM
16281 /* Glyph is off the left margin of the display area.
16282 Should not happen. */
16283 abort ();
a2889657 16284 }
5f5c8ee5
GM
16285
16286 row->ascent = max (row->ascent, it->max_ascent);
16287 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
16288 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
16289 row->phys_height = max (row->phys_height,
16290 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
16291 x += glyph->pixel_width;
16292 ++i;
a2889657 16293 }
5f5c8ee5
GM
16294
16295 /* Stop if max_x reached. */
16296 if (i < nglyphs)
16297 break;
16298
16299 /* Stop at line ends. */
16300 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 16301 {
5f5c8ee5
GM
16302 it->continuation_lines_width = 0;
16303 break;
a2889657 16304 }
1c9241f5 16305
cafafe0b 16306 set_iterator_to_next (it, 1);
a688bb24 16307
5f5c8ee5
GM
16308 /* Stop if truncating at the right edge. */
16309 if (it->truncate_lines_p
16310 && it->current_x >= it->last_visible_x)
16311 {
16312 /* Add truncation mark, but don't do it if the line is
16313 truncated at a padding space. */
16314 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 16315 {
5f5c8ee5 16316 if (!FRAME_WINDOW_P (it->f))
37be86f2
KH
16317 {
16318 int i, n;
16319
9299cb15 16320 if (it->current_x > it->last_visible_x)
37be86f2 16321 {
9299cb15
KH
16322 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
16323 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
16324 break;
16325 for (n = row->used[TEXT_AREA]; i < n; ++i)
16326 {
16327 row->used[TEXT_AREA] = i;
16328 produce_special_glyphs (it, IT_TRUNCATION);
16329 }
37be86f2 16330 }
9299cb15 16331 produce_special_glyphs (it, IT_TRUNCATION);
37be86f2 16332 }
5f5c8ee5 16333 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 16334 }
5f5c8ee5 16335 break;
1c9241f5 16336 }
a2889657
JB
16337 }
16338
5f5c8ee5
GM
16339 /* Maybe insert a truncation at the left. */
16340 if (it->first_visible_x
16341 && IT_CHARPOS (*it) > 0)
a2889657 16342 {
5f5c8ee5
GM
16343 if (!FRAME_WINDOW_P (it->f))
16344 insert_left_trunc_glyphs (it);
16345 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
16346 }
16347
5f5c8ee5 16348 it->face_id = saved_face_id;
2311178e 16349
5f5c8ee5
GM
16350 /* Value is number of columns displayed. */
16351 return it->hpos - hpos_at_start;
16352}
a2889657 16353
a2889657 16354
a2889657 16355\f
3b6b6db7 16356/* This is like a combination of memq and assq. Return 1/2 if PROPVAL
5f5c8ee5
GM
16357 appears as an element of LIST or as the car of an element of LIST.
16358 If PROPVAL is a list, compare each element against LIST in that
3b6b6db7
SM
16359 way, and return 1/2 if any element of PROPVAL is found in LIST.
16360 Otherwise return 0. This function cannot quit.
16361 The return value is 2 if the text is invisible but with an ellipsis
16362 and 1 if it's invisible and without an ellipsis. */
642eefc6
RS
16363
16364int
16365invisible_p (propval, list)
16366 register Lisp_Object propval;
16367 Lisp_Object list;
16368{
3b6b6db7 16369 register Lisp_Object tail, proptail;
2311178e 16370
3b6b6db7
SM
16371 for (tail = list; CONSP (tail); tail = XCDR (tail))
16372 {
16373 register Lisp_Object tem;
16374 tem = XCAR (tail);
16375 if (EQ (propval, tem))
16376 return 1;
16377 if (CONSP (tem) && EQ (propval, XCAR (tem)))
16378 return NILP (XCDR (tem)) ? 1 : 2;
16379 }
2311178e 16380
3b6b6db7
SM
16381 if (CONSP (propval))
16382 {
16383 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
16384 {
16385 Lisp_Object propelt;
16386 propelt = XCAR (proptail);
16387 for (tail = list; CONSP (tail); tail = XCDR (tail))
16388 {
16389 register Lisp_Object tem;
16390 tem = XCAR (tail);
16391 if (EQ (propelt, tem))
16392 return 1;
16393 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
16394 return NILP (XCDR (tem)) ? 1 : 2;
16395 }
16396 }
16397 }
2311178e 16398
3b6b6db7 16399 return 0;
642eefc6 16400}
5f5c8ee5 16401
642eefc6 16402\f
133c764e
KS
16403/***********************************************************************
16404 Glyph Display
16405 ***********************************************************************/
16406
79fa9e0f
KS
16407#ifdef HAVE_WINDOW_SYSTEM
16408
133c764e
KS
16409#if GLYPH_DEBUG
16410
16411void
16412dump_glyph_string (s)
16413 struct glyph_string *s;
16414{
16415 fprintf (stderr, "glyph string\n");
16416 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
16417 s->x, s->y, s->width, s->height);
16418 fprintf (stderr, " ybase = %d\n", s->ybase);
16419 fprintf (stderr, " hl = %d\n", s->hl);
16420 fprintf (stderr, " left overhang = %d, right = %d\n",
16421 s->left_overhang, s->right_overhang);
16422 fprintf (stderr, " nchars = %d\n", s->nchars);
16423 fprintf (stderr, " extends to end of line = %d\n",
16424 s->extends_to_end_of_line_p);
16425 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
16426 fprintf (stderr, " bg width = %d\n", s->background_width);
16427}
16428
16429#endif /* GLYPH_DEBUG */
16430
16431/* Initialize glyph string S. CHAR2B is a suitably allocated vector
16432 of XChar2b structures for S; it can't be allocated in
16433 init_glyph_string because it must be allocated via `alloca'. W
16434 is the window on which S is drawn. ROW and AREA are the glyph row
16435 and area within the row from which S is constructed. START is the
16436 index of the first glyph structure covered by S. HL is a
16437 face-override for drawing S. */
16438
16439#ifdef HAVE_NTGUI
16440#define OPTIONAL_HDC(hdc) hdc,
16441#define DECLARE_HDC(hdc) HDC hdc;
16442#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
16443#define RELEASE_HDC(hdc, f) release_frame_dc ((f), (hdc))
16444#endif
16445
16446#ifndef OPTIONAL_HDC
16447#define OPTIONAL_HDC(hdc)
16448#define DECLARE_HDC(hdc)
16449#define ALLOCATE_HDC(hdc, f)
16450#define RELEASE_HDC(hdc, f)
16451#endif
16452
16453static void
16454init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
16455 struct glyph_string *s;
16456 DECLARE_HDC (hdc)
16457 XChar2b *char2b;
16458 struct window *w;
16459 struct glyph_row *row;
16460 enum glyph_row_area area;
16461 int start;
16462 enum draw_glyphs_face hl;
16463{
16464 bzero (s, sizeof *s);
16465 s->w = w;
16466 s->f = XFRAME (w->frame);
16467#ifdef HAVE_NTGUI
16468 s->hdc = hdc;
16469#endif
16470 s->display = FRAME_X_DISPLAY (s->f);
16471 s->window = FRAME_X_WINDOW (s->f);
16472 s->char2b = char2b;
16473 s->hl = hl;
16474 s->row = row;
16475 s->area = area;
16476 s->first_glyph = row->glyphs[area] + start;
16477 s->height = row->height;
16478 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
16479
16480 /* Display the internal border below the tool-bar window. */
16481 if (s->w == XWINDOW (s->f->tool_bar_window))
16482 s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
16483
16484 s->ybase = s->y + row->ascent;
16485}
16486
16487
16488/* Append the list of glyph strings with head H and tail T to the list
16489 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
16490
16491static INLINE void
16492append_glyph_string_lists (head, tail, h, t)
16493 struct glyph_string **head, **tail;
16494 struct glyph_string *h, *t;
16495{
16496 if (h)
16497 {
16498 if (*head)
16499 (*tail)->next = h;
16500 else
16501 *head = h;
16502 h->prev = *tail;
16503 *tail = t;
16504 }
16505}
16506
16507
16508/* Prepend the list of glyph strings with head H and tail T to the
16509 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
16510 result. */
16511
16512static INLINE void
16513prepend_glyph_string_lists (head, tail, h, t)
16514 struct glyph_string **head, **tail;
16515 struct glyph_string *h, *t;
16516{
16517 if (h)
16518 {
16519 if (*head)
16520 (*head)->prev = t;
16521 else
16522 *tail = t;
16523 t->next = *head;
16524 *head = h;
16525 }
16526}
16527
16528
16529/* Append glyph string S to the list with head *HEAD and tail *TAIL.
16530 Set *HEAD and *TAIL to the resulting list. */
16531
16532static INLINE void
16533append_glyph_string (head, tail, s)
16534 struct glyph_string **head, **tail;
16535 struct glyph_string *s;
16536{
16537 s->next = s->prev = NULL;
16538 append_glyph_string_lists (head, tail, s, s);
16539}
16540
16541
16542/* Get face and two-byte form of character glyph GLYPH on frame F.
16543 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
16544 a pointer to a realized face that is ready for display. */
16545
16546static INLINE struct face *
16547get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
16548 struct frame *f;
16549 struct glyph *glyph;
16550 XChar2b *char2b;
16551 int *two_byte_p;
16552{
16553 struct face *face;
16554
16555 xassert (glyph->type == CHAR_GLYPH);
16556 face = FACE_FROM_ID (f, glyph->face_id);
16557
16558 if (two_byte_p)
16559 *two_byte_p = 0;
16560
16561 if (!glyph->multibyte_p)
16562 {
16563 /* Unibyte case. We don't have to encode, but we have to make
16564 sure to use a face suitable for unibyte. */
16565 STORE_XCHAR2B (char2b, 0, glyph->u.ch);
16566 }
16567 else if (glyph->u.ch < 128
16568 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
16569 {
16570 /* Case of ASCII in a face known to fit ASCII. */
16571 STORE_XCHAR2B (char2b, 0, glyph->u.ch);
16572 }
16573 else
16574 {
16575 int c1, c2, charset;
16576
16577 /* Split characters into bytes. If c2 is -1 afterwards, C is
16578 really a one-byte character so that byte1 is zero. */
16579 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
16580 if (c2 > 0)
16581 STORE_XCHAR2B (char2b, c1, c2);
16582 else
16583 STORE_XCHAR2B (char2b, 0, c1);
16584
16585 /* Maybe encode the character in *CHAR2B. */
16586 if (charset != CHARSET_ASCII)
16587 {
16588 struct font_info *font_info
16589 = FONT_INFO_FROM_ID (f, face->font_info_id);
16590 if (font_info)
16591 glyph->font_type
16592 = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
16593 }
16594 }
16595
16596 /* Make sure X resources of the face are allocated. */
16597 xassert (face != NULL);
16598 PREPARE_FACE_FOR_DISPLAY (f, face);
16599 return face;
16600}
16601
16602
16603/* Fill glyph string S with composition components specified by S->cmp.
16604
16605 FACES is an array of faces for all components of this composition.
16606 S->gidx is the index of the first component for S.
16607 OVERLAPS_P non-zero means S should draw the foreground only, and
16608 use its physical height for clipping.
16609
16610 Value is the index of a component not in S. */
16611
16612static int
16613fill_composite_glyph_string (s, faces, overlaps_p)
16614 struct glyph_string *s;
16615 struct face **faces;
16616 int overlaps_p;
16617{
16618 int i;
16619
16620 xassert (s);
16621
16622 s->for_overlaps_p = overlaps_p;
16623
16624 s->face = faces[s->gidx];
16625 s->font = s->face->font;
16626 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
16627
16628 /* For all glyphs of this composition, starting at the offset
16629 S->gidx, until we reach the end of the definition or encounter a
16630 glyph that requires the different face, add it to S. */
16631 ++s->nchars;
16632 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
16633 ++s->nchars;
16634
16635 /* All glyph strings for the same composition has the same width,
16636 i.e. the width set for the first component of the composition. */
16637
16638 s->width = s->first_glyph->pixel_width;
16639
16640 /* If the specified font could not be loaded, use the frame's
16641 default font, but record the fact that we couldn't load it in
16642 the glyph string so that we can draw rectangles for the
16643 characters of the glyph string. */
16644 if (s->font == NULL)
16645 {
16646 s->font_not_found_p = 1;
16647 s->font = FRAME_FONT (s->f);
16648 }
16649
16650 /* Adjust base line for subscript/superscript text. */
16651 s->ybase += s->first_glyph->voffset;
16652
16653 xassert (s->face && s->face->gc);
16654
16655 /* This glyph string must always be drawn with 16-bit functions. */
16656 s->two_byte_p = 1;
16657
16658 return s->gidx + s->nchars;
16659}
16660
16661
16662/* Fill glyph string S from a sequence of character glyphs.
16663
16664 FACE_ID is the face id of the string. START is the index of the
16665 first glyph to consider, END is the index of the last + 1.
16666 OVERLAPS_P non-zero means S should draw the foreground only, and
16667 use its physical height for clipping.
16668
16669 Value is the index of the first glyph not in S. */
16670
16671static int
16672fill_glyph_string (s, face_id, start, end, overlaps_p)
16673 struct glyph_string *s;
16674 int face_id;
16675 int start, end, overlaps_p;
16676{
16677 struct glyph *glyph, *last;
16678 int voffset;
16679 int glyph_not_available_p;
16680
16681 xassert (s->f == XFRAME (s->w->frame));
16682 xassert (s->nchars == 0);
16683 xassert (start >= 0 && end > start);
16684
16685 s->for_overlaps_p = overlaps_p,
16686 glyph = s->row->glyphs[s->area] + start;
16687 last = s->row->glyphs[s->area] + end;
16688 voffset = glyph->voffset;
16689
16690 glyph_not_available_p = glyph->glyph_not_available_p;
16691
16692 while (glyph < last
16693 && glyph->type == CHAR_GLYPH
16694 && glyph->voffset == voffset
16695 /* Same face id implies same font, nowadays. */
16696 && glyph->face_id == face_id
16697 && glyph->glyph_not_available_p == glyph_not_available_p)
16698 {
16699 int two_byte_p;
16700
16701 s->face = get_glyph_face_and_encoding (s->f, glyph,
16702 s->char2b + s->nchars,
16703 &two_byte_p);
16704 s->two_byte_p = two_byte_p;
16705 ++s->nchars;
16706 xassert (s->nchars <= end - start);
16707 s->width += glyph->pixel_width;
16708 ++glyph;
16709 }
16710
16711 s->font = s->face->font;
16712 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
16713
16714 /* If the specified font could not be loaded, use the frame's font,
16715 but record the fact that we couldn't load it in
16716 S->font_not_found_p so that we can draw rectangles for the
16717 characters of the glyph string. */
16718 if (s->font == NULL || glyph_not_available_p)
16719 {
16720 s->font_not_found_p = 1;
16721 s->font = FRAME_FONT (s->f);
16722 }
16723
16724 /* Adjust base line for subscript/superscript text. */
16725 s->ybase += voffset;
16726
16727 xassert (s->face && s->face->gc);
16728 return glyph - s->row->glyphs[s->area];
16729}
16730
16731
16732/* Fill glyph string S from image glyph S->first_glyph. */
16733
16734static void
16735fill_image_glyph_string (s)
16736 struct glyph_string *s;
16737{
16738 xassert (s->first_glyph->type == IMAGE_GLYPH);
16739 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
16740 xassert (s->img);
16741 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
16742 s->font = s->face->font;
16743 s->width = s->first_glyph->pixel_width;
16744
16745 /* Adjust base line for subscript/superscript text. */
16746 s->ybase += s->first_glyph->voffset;
16747}
16748
16749
16750/* Fill glyph string S from a sequence of stretch glyphs.
16751
16752 ROW is the glyph row in which the glyphs are found, AREA is the
16753 area within the row. START is the index of the first glyph to
16754 consider, END is the index of the last + 1.
16755
16756 Value is the index of the first glyph not in S. */
16757
16758static int
16759fill_stretch_glyph_string (s, row, area, start, end)
16760 struct glyph_string *s;
16761 struct glyph_row *row;
16762 enum glyph_row_area area;
16763 int start, end;
16764{
16765 struct glyph *glyph, *last;
16766 int voffset, face_id;
16767
16768 xassert (s->first_glyph->type == STRETCH_GLYPH);
16769
16770 glyph = s->row->glyphs[s->area] + start;
16771 last = s->row->glyphs[s->area] + end;
16772 face_id = glyph->face_id;
16773 s->face = FACE_FROM_ID (s->f, face_id);
16774 s->font = s->face->font;
16775 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
16776 s->width = glyph->pixel_width;
16777 voffset = glyph->voffset;
16778
16779 for (++glyph;
16780 (glyph < last
16781 && glyph->type == STRETCH_GLYPH
16782 && glyph->voffset == voffset
16783 && glyph->face_id == face_id);
16784 ++glyph)
16785 s->width += glyph->pixel_width;
16786
16787 /* Adjust base line for subscript/superscript text. */
16788 s->ybase += voffset;
16789
16790 /* The case that face->gc == 0 is handled when drawing the glyph
16791 string by calling PREPARE_FACE_FOR_DISPLAY. */
16792 xassert (s->face);
16793 return glyph - s->row->glyphs[s->area];
16794}
16795
16796
16797/* EXPORT for RIF:
16798 Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
16799 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
16800 assumed to be zero. */
16801
16802void
16803x_get_glyph_overhangs (glyph, f, left, right)
16804 struct glyph *glyph;
16805 struct frame *f;
16806 int *left, *right;
16807{
16808 *left = *right = 0;
16809
16810 if (glyph->type == CHAR_GLYPH)
16811 {
16812 XFontStruct *font;
16813 struct face *face;
16814 struct font_info *font_info;
16815 XChar2b char2b;
16816 XCharStruct *pcm;
16817
16818 face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
16819 font = face->font;
16820 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
16821 if (font /* ++KFS: Should this be font_info ? */
16822 && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
16823 {
16824 if (pcm->rbearing > pcm->width)
16825 *right = pcm->rbearing - pcm->width;
16826 if (pcm->lbearing < 0)
16827 *left = -pcm->lbearing;
16828 }
16829 }
16830}
16831
16832
16833/* Return the index of the first glyph preceding glyph string S that
16834 is overwritten by S because of S's left overhang. Value is -1
16835 if no glyphs are overwritten. */
16836
16837static int
16838left_overwritten (s)
16839 struct glyph_string *s;
16840{
16841 int k;
16842
16843 if (s->left_overhang)
16844 {
16845 int x = 0, i;
16846 struct glyph *glyphs = s->row->glyphs[s->area];
16847 int first = s->first_glyph - glyphs;
16848
16849 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
16850 x -= glyphs[i].pixel_width;
16851
16852 k = i + 1;
16853 }
16854 else
16855 k = -1;
16856
16857 return k;
16858}
16859
16860
16861/* Return the index of the first glyph preceding glyph string S that
16862 is overwriting S because of its right overhang. Value is -1 if no
16863 glyph in front of S overwrites S. */
16864
16865static int
16866left_overwriting (s)
16867 struct glyph_string *s;
16868{
16869 int i, k, x;
16870 struct glyph *glyphs = s->row->glyphs[s->area];
16871 int first = s->first_glyph - glyphs;
16872
16873 k = -1;
16874 x = 0;
16875 for (i = first - 1; i >= 0; --i)
16876 {
16877 int left, right;
16878 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
16879 if (x + right > 0)
16880 k = i;
16881 x -= glyphs[i].pixel_width;
16882 }
16883
16884 return k;
16885}
16886
16887
16888/* Return the index of the last glyph following glyph string S that is
16889 not overwritten by S because of S's right overhang. Value is -1 if
16890 no such glyph is found. */
16891
16892static int
16893right_overwritten (s)
16894 struct glyph_string *s;
16895{
16896 int k = -1;
16897
16898 if (s->right_overhang)
16899 {
16900 int x = 0, i;
16901 struct glyph *glyphs = s->row->glyphs[s->area];
16902 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
16903 int end = s->row->used[s->area];
16904
16905 for (i = first; i < end && s->right_overhang > x; ++i)
16906 x += glyphs[i].pixel_width;
16907
16908 k = i;
16909 }
16910
16911 return k;
16912}
16913
16914
16915/* Return the index of the last glyph following glyph string S that
16916 overwrites S because of its left overhang. Value is negative
16917 if no such glyph is found. */
16918
16919static int
16920right_overwriting (s)
16921 struct glyph_string *s;
16922{
16923 int i, k, x;
16924 int end = s->row->used[s->area];
16925 struct glyph *glyphs = s->row->glyphs[s->area];
16926 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
16927
16928 k = -1;
16929 x = 0;
16930 for (i = first; i < end; ++i)
16931 {
16932 int left, right;
16933 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
16934 if (x - left < 0)
16935 k = i;
16936 x += glyphs[i].pixel_width;
16937 }
16938
16939 return k;
16940}
16941
16942
16943/* Get face and two-byte form of character C in face FACE_ID on frame
16944 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
16945 means we want to display multibyte text. DISPLAY_P non-zero means
16946 make sure that X resources for the face returned are allocated.
16947 Value is a pointer to a realized face that is ready for display if
16948 DISPLAY_P is non-zero. */
16949
16950static INLINE struct face *
16951get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
16952 struct frame *f;
16953 int c, face_id;
16954 XChar2b *char2b;
16955 int multibyte_p, display_p;
16956{
16957 struct face *face = FACE_FROM_ID (f, face_id);
16958
16959 if (!multibyte_p)
16960 {
16961 /* Unibyte case. We don't have to encode, but we have to make
16962 sure to use a face suitable for unibyte. */
16963 STORE_XCHAR2B (char2b, 0, c);
16964 face_id = FACE_FOR_CHAR (f, face, c);
16965 face = FACE_FROM_ID (f, face_id);
16966 }
16967 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
16968 {
16969 /* Case of ASCII in a face known to fit ASCII. */
16970 STORE_XCHAR2B (char2b, 0, c);
16971 }
16972 else
16973 {
16974 int c1, c2, charset;
16975
16976 /* Split characters into bytes. If c2 is -1 afterwards, C is
16977 really a one-byte character so that byte1 is zero. */
16978 SPLIT_CHAR (c, charset, c1, c2);
16979 if (c2 > 0)
16980 STORE_XCHAR2B (char2b, c1, c2);
16981 else
16982 STORE_XCHAR2B (char2b, 0, c1);
16983
16984 /* Maybe encode the character in *CHAR2B. */
16985 if (face->font != NULL)
16986 {
16987 struct font_info *font_info
16988 = FONT_INFO_FROM_ID (f, face->font_info_id);
16989 if (font_info)
16990 rif->encode_char (c, char2b, font_info, 0);
16991 }
16992 }
16993
16994 /* Make sure X resources of the face are allocated. */
16995#ifdef HAVE_X_WINDOWS
16996 if (display_p)
16997#endif
16998 {
16999 xassert (face != NULL);
17000 PREPARE_FACE_FOR_DISPLAY (f, face);
17001 }
17002
17003 return face;
17004}
17005
17006
17007/* Set background width of glyph string S. START is the index of the
17008 first glyph following S. LAST_X is the right-most x-position + 1
17009 in the drawing area. */
17010
17011static INLINE void
17012set_glyph_string_background_width (s, start, last_x)
17013 struct glyph_string *s;
17014 int start;
17015 int last_x;
17016{
17017 /* If the face of this glyph string has to be drawn to the end of
17018 the drawing area, set S->extends_to_end_of_line_p. */
17019 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
17020
17021 if (start == s->row->used[s->area]
17022 && s->area == TEXT_AREA
17023 && ((s->hl == DRAW_NORMAL_TEXT
17024 && (s->row->fill_line_p
17025 || s->face->background != default_face->background
17026 || s->face->stipple != default_face->stipple
17027 || s->row->mouse_face_p))
17028 || s->hl == DRAW_MOUSE_FACE
17029 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
17030 && s->row->fill_line_p)))
17031 s->extends_to_end_of_line_p = 1;
17032
17033 /* If S extends its face to the end of the line, set its
17034 background_width to the distance to the right edge of the drawing
17035 area. */
17036 if (s->extends_to_end_of_line_p)
17037 s->background_width = last_x - s->x + 1;
17038 else
17039 s->background_width = s->width;
17040}
17041
17042
17043/* Compute overhangs and x-positions for glyph string S and its
17044 predecessors, or successors. X is the starting x-position for S.
17045 BACKWARD_P non-zero means process predecessors. */
17046
17047static void
17048compute_overhangs_and_x (s, x, backward_p)
17049 struct glyph_string *s;
17050 int x;
17051 int backward_p;
17052{
17053 if (backward_p)
17054 {
17055 while (s)
17056 {
17057 if (rif->compute_glyph_string_overhangs)
17058 rif->compute_glyph_string_overhangs (s);
17059 x -= s->width;
17060 s->x = x;
17061 s = s->prev;
17062 }
17063 }
17064 else
17065 {
17066 while (s)
17067 {
17068 if (rif->compute_glyph_string_overhangs)
17069 rif->compute_glyph_string_overhangs (s);
17070 s->x = x;
17071 x += s->width;
17072 s = s->next;
17073 }
17074 }
17075}
17076
17077
17078
fa3c6b4d 17079/* The following macros are only called from draw_glyphs below.
133c764e
KS
17080 They reference the following parameters of that function directly:
17081 `w', `row', `area', and `overlap_p'
17082 as well as the following local variables:
17083 `s', `f', and `hdc' (in W32) */
17084
17085#ifdef HAVE_NTGUI
17086/* On W32, silently add local `hdc' variable to argument list of
17087 init_glyph_string. */
17088#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
17089 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
17090#else
17091#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
17092 init_glyph_string (s, char2b, w, row, area, start, hl)
17093#endif
17094
17095/* Add a glyph string for a stretch glyph to the list of strings
17096 between HEAD and TAIL. START is the index of the stretch glyph in
17097 row area AREA of glyph row ROW. END is the index of the last glyph
17098 in that glyph row area. X is the current output position assigned
17099 to the new glyph string constructed. HL overrides that face of the
17100 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
17101 is the right-most x-position of the drawing area. */
17102
17103/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
17104 and below -- keep them on one line. */
17105#define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17106 do \
17107 { \
17108 s = (struct glyph_string *) alloca (sizeof *s); \
17109 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
17110 START = fill_stretch_glyph_string (s, row, area, START, END); \
17111 append_glyph_string (&HEAD, &TAIL, s); \
17112 s->x = (X); \
17113 } \
17114 while (0)
17115
17116
17117/* Add a glyph string for an image glyph to the list of strings
17118 between HEAD and TAIL. START is the index of the image glyph in
17119 row area AREA of glyph row ROW. END is the index of the last glyph
17120 in that glyph row area. X is the current output position assigned
17121 to the new glyph string constructed. HL overrides that face of the
17122 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
17123 is the right-most x-position of the drawing area. */
17124
17125#define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17126 do \
17127 { \
17128 s = (struct glyph_string *) alloca (sizeof *s); \
17129 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
17130 fill_image_glyph_string (s); \
17131 append_glyph_string (&HEAD, &TAIL, s); \
17132 ++START; \
17133 s->x = (X); \
17134 } \
17135 while (0)
17136
17137
17138/* Add a glyph string for a sequence of character glyphs to the list
17139 of strings between HEAD and TAIL. START is the index of the first
17140 glyph in row area AREA of glyph row ROW that is part of the new
17141 glyph string. END is the index of the last glyph in that glyph row
17142 area. X is the current output position assigned to the new glyph
17143 string constructed. HL overrides that face of the glyph; e.g. it
17144 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
17145 right-most x-position of the drawing area. */
17146
17147#define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
17148 do \
17149 { \
17150 int c, face_id; \
17151 XChar2b *char2b; \
17152 \
17153 c = (row)->glyphs[area][START].u.ch; \
17154 face_id = (row)->glyphs[area][START].face_id; \
17155 \
17156 s = (struct glyph_string *) alloca (sizeof *s); \
17157 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
17158 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
17159 append_glyph_string (&HEAD, &TAIL, s); \
17160 s->x = (X); \
17161 START = fill_glyph_string (s, face_id, START, END, overlaps_p); \
17162 } \
17163 while (0)
17164
17165
17166/* Add a glyph string for a composite sequence to the list of strings
17167 between HEAD and TAIL. START is the index of the first glyph in
17168 row area AREA of glyph row ROW that is part of the new glyph
17169 string. END is the index of the last glyph in that glyph row area.
17170 X is the current output position assigned to the new glyph string
17171 constructed. HL overrides that face of the glyph; e.g. it is
17172 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
17173 x-position of the drawing area. */
17174
17175#define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17176 do { \
17177 int cmp_id = (row)->glyphs[area][START].u.cmp_id; \
17178 int face_id = (row)->glyphs[area][START].face_id; \
17179 struct face *base_face = FACE_FROM_ID (f, face_id); \
17180 struct composition *cmp = composition_table[cmp_id]; \
17181 int glyph_len = cmp->glyph_len; \
17182 XChar2b *char2b; \
17183 struct face **faces; \
17184 struct glyph_string *first_s = NULL; \
17185 int n; \
17186 \
17187 base_face = base_face->ascii_face; \
17188 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
17189 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
17190 /* At first, fill in `char2b' and `faces'. */ \
17191 for (n = 0; n < glyph_len; n++) \
17192 { \
17193 int c = COMPOSITION_GLYPH (cmp, n); \
17194 int this_face_id = FACE_FOR_CHAR (f, base_face, c); \
17195 faces[n] = FACE_FROM_ID (f, this_face_id); \
17196 get_char_face_and_encoding (f, c, this_face_id, \
17197 char2b + n, 1, 1); \
17198 } \
17199 \
17200 /* Make glyph_strings for each glyph sequence that is drawable by \
17201 the same face, and append them to HEAD/TAIL. */ \
17202 for (n = 0; n < cmp->glyph_len;) \
17203 { \
17204 s = (struct glyph_string *) alloca (sizeof *s); \
17205 INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL); \
17206 append_glyph_string (&(HEAD), &(TAIL), s); \
17207 s->cmp = cmp; \
17208 s->gidx = n; \
17209 s->x = (X); \
17210 \
17211 if (n == 0) \
17212 first_s = s; \
17213 \
17214 n = fill_composite_glyph_string (s, faces, overlaps_p); \
17215 } \
17216 \
17217 ++START; \
17218 s = first_s; \
17219 } while (0)
17220
17221
17222/* Build a list of glyph strings between HEAD and TAIL for the glyphs
17223 of AREA of glyph row ROW on window W between indices START and END.
17224 HL overrides the face for drawing glyph strings, e.g. it is
17225 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
17226 x-positions of the drawing area.
17227
17228 This is an ugly monster macro construct because we must use alloca
fa3c6b4d 17229 to allocate glyph strings (because draw_glyphs can be called
133c764e
KS
17230 asynchronously). */
17231
17232#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
17233 do \
17234 { \
17235 HEAD = TAIL = NULL; \
17236 while (START < END) \
17237 { \
17238 struct glyph *first_glyph = (row)->glyphs[area] + START; \
17239 switch (first_glyph->type) \
17240 { \
17241 case CHAR_GLYPH: \
17242 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
17243 HL, X, LAST_X); \
17244 break; \
17245 \
17246 case COMPOSITE_GLYPH: \
17247 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
17248 HL, X, LAST_X); \
17249 break; \
17250 \
17251 case STRETCH_GLYPH: \
17252 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
17253 HL, X, LAST_X); \
17254 break; \
17255 \
17256 case IMAGE_GLYPH: \
17257 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
17258 HL, X, LAST_X); \
17259 break; \
17260 \
17261 default: \
17262 abort (); \
17263 } \
17264 \
17265 set_glyph_string_background_width (s, START, LAST_X); \
17266 (X) += s->width; \
17267 } \
17268 } \
17269 while (0)
17270
17271
17272/* Draw glyphs between START and END in AREA of ROW on window W,
17273 starting at x-position X. X is relative to AREA in W. HL is a
17274 face-override with the following meaning:
17275
17276 DRAW_NORMAL_TEXT draw normally
17277 DRAW_CURSOR draw in cursor face
17278 DRAW_MOUSE_FACE draw in mouse face.
17279 DRAW_INVERSE_VIDEO draw in mode line face
17280 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
17281 DRAW_IMAGE_RAISED draw an image with a raised relief around it
17282
17283 If OVERLAPS_P is non-zero, draw only the foreground of characters
17284 and clip to the physical height of ROW.
17285
17286 Value is the x-position reached, relative to AREA of W. */
17287
fa3c6b4d
KS
17288static int
17289draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
133c764e
KS
17290 struct window *w;
17291 int x;
17292 struct glyph_row *row;
17293 enum glyph_row_area area;
17294 int start, end;
17295 enum draw_glyphs_face hl;
17296 int overlaps_p;
17297{
17298 struct glyph_string *head, *tail;
17299 struct glyph_string *s;
17300 int last_x, area_width;
17301 int x_reached;
17302 int i, j;
17303 struct frame *f = XFRAME (WINDOW_FRAME (w));
17304 DECLARE_HDC (hdc);
17305
17306 ALLOCATE_HDC (hdc, f);
17307
17308 /* Let's rather be paranoid than getting a SEGV. */
17309 end = min (end, row->used[area]);
17310 start = max (0, start);
17311 start = min (end, start);
17312
17313 /* Translate X to frame coordinates. Set last_x to the right
17314 end of the drawing area. */
17315 if (row->full_width_p)
17316 {
17317 /* X is relative to the left edge of W, without scroll bars
17318 or fringes. */
da8b7f4f
KS
17319 x += WINDOW_LEFT_EDGE_X (w);
17320 last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
133c764e
KS
17321 }
17322 else
17323 {
da8b7f4f
KS
17324 int area_left = window_box_left (w, area);
17325 x += area_left;
133c764e 17326 area_width = window_box_width (w, area);
da8b7f4f 17327 last_x = area_left + area_width;
133c764e
KS
17328 }
17329
17330 /* Build a doubly-linked list of glyph_string structures between
17331 head and tail from what we have to draw. Note that the macro
17332 BUILD_GLYPH_STRINGS will modify its start parameter. That's
17333 the reason we use a separate variable `i'. */
17334 i = start;
17335 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
17336 if (tail)
17337 x_reached = tail->x + tail->background_width;
17338 else
17339 x_reached = x;
17340
17341 /* If there are any glyphs with lbearing < 0 or rbearing > width in
17342 the row, redraw some glyphs in front or following the glyph
17343 strings built above. */
17344 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
17345 {
17346 int dummy_x = 0;
17347 struct glyph_string *h, *t;
17348
17349 /* Compute overhangs for all glyph strings. */
17350 if (rif->compute_glyph_string_overhangs)
17351 for (s = head; s; s = s->next)
17352 rif->compute_glyph_string_overhangs (s);
17353
17354 /* Prepend glyph strings for glyphs in front of the first glyph
17355 string that are overwritten because of the first glyph
17356 string's left overhang. The background of all strings
17357 prepended must be drawn because the first glyph string
17358 draws over it. */
17359 i = left_overwritten (head);
17360 if (i >= 0)
17361 {
17362 j = i;
17363 BUILD_GLYPH_STRINGS (j, start, h, t,
17364 DRAW_NORMAL_TEXT, dummy_x, last_x);
17365 start = i;
17366 compute_overhangs_and_x (t, head->x, 1);
17367 prepend_glyph_string_lists (&head, &tail, h, t);
17368 }
17369
17370 /* Prepend glyph strings for glyphs in front of the first glyph
17371 string that overwrite that glyph string because of their
17372 right overhang. For these strings, only the foreground must
17373 be drawn, because it draws over the glyph string at `head'.
17374 The background must not be drawn because this would overwrite
17375 right overhangs of preceding glyphs for which no glyph
17376 strings exist. */
17377 i = left_overwriting (head);
17378 if (i >= 0)
17379 {
17380 BUILD_GLYPH_STRINGS (i, start, h, t,
17381 DRAW_NORMAL_TEXT, dummy_x, last_x);
17382 for (s = h; s; s = s->next)
17383 s->background_filled_p = 1;
17384 compute_overhangs_and_x (t, head->x, 1);
17385 prepend_glyph_string_lists (&head, &tail, h, t);
17386 }
17387
17388 /* Append glyphs strings for glyphs following the last glyph
17389 string tail that are overwritten by tail. The background of
17390 these strings has to be drawn because tail's foreground draws
17391 over it. */
17392 i = right_overwritten (tail);
17393 if (i >= 0)
17394 {
17395 BUILD_GLYPH_STRINGS (end, i, h, t,
17396 DRAW_NORMAL_TEXT, x, last_x);
17397 compute_overhangs_and_x (h, tail->x + tail->width, 0);
17398 append_glyph_string_lists (&head, &tail, h, t);
17399 }
17400
17401 /* Append glyph strings for glyphs following the last glyph
17402 string tail that overwrite tail. The foreground of such
17403 glyphs has to be drawn because it writes into the background
17404 of tail. The background must not be drawn because it could
17405 paint over the foreground of following glyphs. */
17406 i = right_overwriting (tail);
17407 if (i >= 0)
17408 {
17409 BUILD_GLYPH_STRINGS (end, i, h, t,
17410 DRAW_NORMAL_TEXT, x, last_x);
17411 for (s = h; s; s = s->next)
17412 s->background_filled_p = 1;
17413 compute_overhangs_and_x (h, tail->x + tail->width, 0);
17414 append_glyph_string_lists (&head, &tail, h, t);
17415 }
17416 }
17417
17418 /* Draw all strings. */
17419 for (s = head; s; s = s->next)
17420 rif->draw_glyph_string (s);
17421
17422 if (area == TEXT_AREA
17423 && !row->full_width_p
17424 /* When drawing overlapping rows, only the glyph strings'
17425 foreground is drawn, which doesn't erase a cursor
17426 completely. */
17427 && !overlaps_p)
17428 {
17429 int x0 = head ? head->x : x;
17430 int x1 = tail ? tail->x + tail->background_width : x;
17431
da8b7f4f
KS
17432 int text_left = window_box_left (w, TEXT_AREA);
17433 x0 -= text_left;
17434 x1 -= text_left;
133c764e 17435
da8b7f4f 17436 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
133c764e
KS
17437 row->y, MATRIX_ROW_BOTTOM_Y (row));
17438 }
17439
17440 /* Value is the x-position up to which drawn, relative to AREA of W.
17441 This doesn't include parts drawn because of overhangs. */
da8b7f4f
KS
17442 if (row->full_width_p)
17443 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
17444 else
17445 x_reached -= window_box_left (w, area);
133c764e
KS
17446
17447 RELEASE_HDC (hdc, f);
17448
17449 return x_reached;
17450}
17451
17452
17453/* Store one glyph for IT->char_to_display in IT->glyph_row.
17454 Called from x_produce_glyphs when IT->glyph_row is non-null. */
17455
17456static INLINE void
17457append_glyph (it)
17458 struct it *it;
17459{
17460 struct glyph *glyph;
17461 enum glyph_row_area area = it->area;
17462
17463 xassert (it->glyph_row);
17464 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
17465
17466 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
17467 if (glyph < it->glyph_row->glyphs[area + 1])
17468 {
17469 glyph->charpos = CHARPOS (it->position);
17470 glyph->object = it->object;
17471 glyph->pixel_width = it->pixel_width;
17472 glyph->voffset = it->voffset;
17473 glyph->type = CHAR_GLYPH;
17474 glyph->multibyte_p = it->multibyte_p;
17475 glyph->left_box_line_p = it->start_of_box_run_p;
17476 glyph->right_box_line_p = it->end_of_box_run_p;
17477 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
17478 || it->phys_descent > it->descent);
17479 glyph->padding_p = 0;
17480 glyph->glyph_not_available_p = it->glyph_not_available_p;
17481 glyph->face_id = it->face_id;
17482 glyph->u.ch = it->char_to_display;
17483 glyph->font_type = FONT_TYPE_UNKNOWN;
17484 ++it->glyph_row->used[area];
17485 }
17486}
17487
17488/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
17489 Called from x_produce_glyphs when IT->glyph_row is non-null. */
17490
17491static INLINE void
17492append_composite_glyph (it)
17493 struct it *it;
17494{
17495 struct glyph *glyph;
17496 enum glyph_row_area area = it->area;
17497
17498 xassert (it->glyph_row);
17499
17500 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
17501 if (glyph < it->glyph_row->glyphs[area + 1])
17502 {
17503 glyph->charpos = CHARPOS (it->position);
17504 glyph->object = it->object;
17505 glyph->pixel_width = it->pixel_width;
17506 glyph->voffset = it->voffset;
17507 glyph->type = COMPOSITE_GLYPH;
17508 glyph->multibyte_p = it->multibyte_p;
17509 glyph->left_box_line_p = it->start_of_box_run_p;
17510 glyph->right_box_line_p = it->end_of_box_run_p;
17511 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
17512 || it->phys_descent > it->descent);
17513 glyph->padding_p = 0;
17514 glyph->glyph_not_available_p = 0;
17515 glyph->face_id = it->face_id;
17516 glyph->u.cmp_id = it->cmp_id;
17517 glyph->font_type = FONT_TYPE_UNKNOWN;
17518 ++it->glyph_row->used[area];
17519 }
17520}
17521
17522
17523/* Change IT->ascent and IT->height according to the setting of
17524 IT->voffset. */
17525
17526static INLINE void
17527take_vertical_position_into_account (it)
17528 struct it *it;
17529{
17530 if (it->voffset)
17531 {
17532 if (it->voffset < 0)
17533 /* Increase the ascent so that we can display the text higher
17534 in the line. */
17535 it->ascent += abs (it->voffset);
17536 else
17537 /* Increase the descent so that we can display the text lower
17538 in the line. */
17539 it->descent += it->voffset;
17540 }
17541}
17542
17543
17544/* Produce glyphs/get display metrics for the image IT is loaded with.
17545 See the description of struct display_iterator in dispextern.h for
17546 an overview of struct display_iterator. */
17547
17548static void
17549produce_image_glyph (it)
17550 struct it *it;
17551{
17552 struct image *img;
17553 struct face *face;
17554
17555 xassert (it->what == IT_IMAGE);
17556
17557 face = FACE_FROM_ID (it->f, it->face_id);
17558 img = IMAGE_FROM_ID (it->f, it->image_id);
17559 xassert (img);
17560
17561 /* Make sure X resources of the face and image are loaded. */
17562 PREPARE_FACE_FOR_DISPLAY (it->f, face);
17563 prepare_image_for_display (it->f, img);
17564
17565 it->ascent = it->phys_ascent = image_ascent (img, face);
17566 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
17567 it->pixel_width = img->width + 2 * img->hmargin;
17568
17569 it->nglyphs = 1;
17570
17571 if (face->box != FACE_NO_BOX)
17572 {
17573 if (face->box_line_width > 0)
17574 {
17575 it->ascent += face->box_line_width;
17576 it->descent += face->box_line_width;
17577 }
17578
17579 if (it->start_of_box_run_p)
17580 it->pixel_width += abs (face->box_line_width);
17581 if (it->end_of_box_run_p)
17582 it->pixel_width += abs (face->box_line_width);
17583 }
17584
17585 take_vertical_position_into_account (it);
17586
17587 if (it->glyph_row)
17588 {
17589 struct glyph *glyph;
17590 enum glyph_row_area area = it->area;
17591
17592 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
17593 if (glyph < it->glyph_row->glyphs[area + 1])
17594 {
17595 glyph->charpos = CHARPOS (it->position);
17596 glyph->object = it->object;
17597 glyph->pixel_width = it->pixel_width;
17598 glyph->voffset = it->voffset;
17599 glyph->type = IMAGE_GLYPH;
17600 glyph->multibyte_p = it->multibyte_p;
17601 glyph->left_box_line_p = it->start_of_box_run_p;
17602 glyph->right_box_line_p = it->end_of_box_run_p;
17603 glyph->overlaps_vertically_p = 0;
17604 glyph->padding_p = 0;
17605 glyph->glyph_not_available_p = 0;
17606 glyph->face_id = it->face_id;
17607 glyph->u.img_id = img->id;
17608 glyph->font_type = FONT_TYPE_UNKNOWN;
17609 ++it->glyph_row->used[area];
17610 }
17611 }
17612}
17613
17614
17615/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
17616 of the glyph, WIDTH and HEIGHT are the width and height of the
17617 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
17618 ascent of the glyph (0 <= ASCENT <= 1). */
17619
17620static void
17621append_stretch_glyph (it, object, width, height, ascent)
17622 struct it *it;
17623 Lisp_Object object;
17624 int width, height;
17625 double ascent;
17626{
17627 struct glyph *glyph;
17628 enum glyph_row_area area = it->area;
17629
17630 xassert (ascent >= 0 && ascent <= 1);
17631
17632 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
17633 if (glyph < it->glyph_row->glyphs[area + 1])
17634 {
17635 glyph->charpos = CHARPOS (it->position);
17636 glyph->object = object;
17637 glyph->pixel_width = width;
17638 glyph->voffset = it->voffset;
17639 glyph->type = STRETCH_GLYPH;
17640 glyph->multibyte_p = it->multibyte_p;
17641 glyph->left_box_line_p = it->start_of_box_run_p;
17642 glyph->right_box_line_p = it->end_of_box_run_p;
17643 glyph->overlaps_vertically_p = 0;
17644 glyph->padding_p = 0;
17645 glyph->glyph_not_available_p = 0;
17646 glyph->face_id = it->face_id;
17647 glyph->u.stretch.ascent = height * ascent;
17648 glyph->u.stretch.height = height;
17649 glyph->font_type = FONT_TYPE_UNKNOWN;
17650 ++it->glyph_row->used[area];
17651 }
17652}
17653
17654
17655/* Produce a stretch glyph for iterator IT. IT->object is the value
17656 of the glyph property displayed. The value must be a list
17657 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
17658 being recognized:
17659
17660 1. `:width WIDTH' specifies that the space should be WIDTH *
17661 canonical char width wide. WIDTH may be an integer or floating
17662 point number.
17663
17664 2. `:relative-width FACTOR' specifies that the width of the stretch
17665 should be computed from the width of the first character having the
17666 `glyph' property, and should be FACTOR times that width.
17667
17668 3. `:align-to HPOS' specifies that the space should be wide enough
17669 to reach HPOS, a value in canonical character units.
17670
17671 Exactly one of the above pairs must be present.
17672
17673 4. `:height HEIGHT' specifies that the height of the stretch produced
17674 should be HEIGHT, measured in canonical character units.
17675
17676 5. `:relative-height FACTOR' specifies that the height of the
17677 stretch should be FACTOR times the height of the characters having
17678 the glyph property.
17679
17680 Either none or exactly one of 4 or 5 must be present.
17681
17682 6. `:ascent ASCENT' specifies that ASCENT percent of the height
17683 of the stretch should be used for the ascent of the stretch.
17684 ASCENT must be in the range 0 <= ASCENT <= 100. */
17685
17686#define NUMVAL(X) \
17687 ((INTEGERP (X) || FLOATP (X)) \
17688 ? XFLOATINT (X) \
17689 : - 1)
17690
17691
17692static void
17693produce_stretch_glyph (it)
17694 struct it *it;
17695{
17696 /* (space :width WIDTH :height HEIGHT. */
17697 Lisp_Object prop, plist;
17698 int width = 0, height = 0;
17699 double ascent = 0;
17700 struct face *face = FACE_FROM_ID (it->f, it->face_id);
17701 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
17702
17703 PREPARE_FACE_FOR_DISPLAY (it->f, face);
17704
17705 /* List should start with `space'. */
17706 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
17707 plist = XCDR (it->object);
17708
17709 /* Compute the width of the stretch. */
17710 if (prop = Fplist_get (plist, QCwidth),
17711 NUMVAL (prop) > 0)
17712 /* Absolute width `:width WIDTH' specified and valid. */
da8b7f4f 17713 width = NUMVAL (prop) * FRAME_COLUMN_WIDTH (it->f);
133c764e
KS
17714 else if (prop = Fplist_get (plist, QCrelative_width),
17715 NUMVAL (prop) > 0)
17716 {
17717 /* Relative width `:relative-width FACTOR' specified and valid.
17718 Compute the width of the characters having the `glyph'
17719 property. */
17720 struct it it2;
17721 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
17722
17723 it2 = *it;
17724 if (it->multibyte_p)
17725 {
17726 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
17727 - IT_BYTEPOS (*it));
17728 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
17729 }
17730 else
17731 it2.c = *p, it2.len = 1;
17732
17733 it2.glyph_row = NULL;
17734 it2.what = IT_CHARACTER;
17735 x_produce_glyphs (&it2);
17736 width = NUMVAL (prop) * it2.pixel_width;
17737 }
17738 else if (prop = Fplist_get (plist, QCalign_to),
17739 NUMVAL (prop) > 0)
da8b7f4f 17740 width = NUMVAL (prop) * FRAME_COLUMN_WIDTH (it->f) - it->current_x;
133c764e
KS
17741 else
17742 /* Nothing specified -> width defaults to canonical char width. */
da8b7f4f 17743 width = FRAME_COLUMN_WIDTH (it->f);
133c764e
KS
17744
17745 /* Compute height. */
17746 if (prop = Fplist_get (plist, QCheight),
17747 NUMVAL (prop) > 0)
da8b7f4f 17748 height = NUMVAL (prop) * FRAME_LINE_HEIGHT (it->f);
133c764e
KS
17749 else if (prop = Fplist_get (plist, QCrelative_height),
17750 NUMVAL (prop) > 0)
17751 height = FONT_HEIGHT (font) * NUMVAL (prop);
17752 else
17753 height = FONT_HEIGHT (font);
17754
17755 /* Compute percentage of height used for ascent. If
17756 `:ascent ASCENT' is present and valid, use that. Otherwise,
17757 derive the ascent from the font in use. */
17758 if (prop = Fplist_get (plist, QCascent),
17759 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
17760 ascent = NUMVAL (prop) / 100.0;
17761 else
17762 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
17763
17764 if (width <= 0)
17765 width = 1;
17766 if (height <= 0)
17767 height = 1;
17768
17769 if (it->glyph_row)
17770 {
17771 Lisp_Object object = it->stack[it->sp - 1].string;
17772 if (!STRINGP (object))
17773 object = it->w->buffer;
17774 append_stretch_glyph (it, object, width, height, ascent);
17775 }
17776
17777 it->pixel_width = width;
17778 it->ascent = it->phys_ascent = height * ascent;
17779 it->descent = it->phys_descent = height - it->ascent;
17780 it->nglyphs = 1;
17781
17782 if (face->box != FACE_NO_BOX)
17783 {
17784 if (face->box_line_width > 0)
17785 {
17786 it->ascent += face->box_line_width;
17787 it->descent += face->box_line_width;
17788 }
17789
17790 if (it->start_of_box_run_p)
17791 it->pixel_width += abs (face->box_line_width);
17792 if (it->end_of_box_run_p)
17793 it->pixel_width += abs (face->box_line_width);
17794 }
17795
17796 take_vertical_position_into_account (it);
17797}
17798
17799/* RIF:
17800 Produce glyphs/get display metrics for the display element IT is
17801 loaded with. See the description of struct display_iterator in
17802 dispextern.h for an overview of struct display_iterator. */
17803
17804void
17805x_produce_glyphs (it)
17806 struct it *it;
17807{
17808 it->glyph_not_available_p = 0;
17809
17810 if (it->what == IT_CHARACTER)
17811 {
17812 XChar2b char2b;
17813 XFontStruct *font;
17814 struct face *face = FACE_FROM_ID (it->f, it->face_id);
17815 XCharStruct *pcm;
17816 int font_not_found_p;
17817 struct font_info *font_info;
17818 int boff; /* baseline offset */
17819 /* We may change it->multibyte_p upon unibyte<->multibyte
17820 conversion. So, save the current value now and restore it
17821 later.
17822
17823 Note: It seems that we don't have to record multibyte_p in
17824 struct glyph because the character code itself tells if or
17825 not the character is multibyte. Thus, in the future, we must
17826 consider eliminating the field `multibyte_p' in the struct
17827 glyph. */
17828 int saved_multibyte_p = it->multibyte_p;
17829
17830 /* Maybe translate single-byte characters to multibyte, or the
17831 other way. */
17832 it->char_to_display = it->c;
17833 if (!ASCII_BYTE_P (it->c))
17834 {
17835 if (unibyte_display_via_language_environment
17836 && SINGLE_BYTE_CHAR_P (it->c)
17837 && (it->c >= 0240
17838 || !NILP (Vnonascii_translation_table)))
17839 {
17840 it->char_to_display = unibyte_char_to_multibyte (it->c);
17841 it->multibyte_p = 1;
17842 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
17843 face = FACE_FROM_ID (it->f, it->face_id);
17844 }
17845 else if (!SINGLE_BYTE_CHAR_P (it->c)
17846 && !it->multibyte_p)
17847 {
17848 it->multibyte_p = 1;
17849 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
17850 face = FACE_FROM_ID (it->f, it->face_id);
17851 }
17852 }
17853
17854 /* Get font to use. Encode IT->char_to_display. */
17855 get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
17856 &char2b, it->multibyte_p, 0);
17857 font = face->font;
17858
17859 /* When no suitable font found, use the default font. */
17860 font_not_found_p = font == NULL;
17861 if (font_not_found_p)
17862 {
17863 font = FRAME_FONT (it->f);
17864 boff = FRAME_BASELINE_OFFSET (it->f);
17865 font_info = NULL;
17866 }
17867 else
17868 {
17869 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
17870 boff = font_info->baseline_offset;
17871 if (font_info->vertical_centering)
17872 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
17873 }
17874
17875 if (it->char_to_display >= ' '
17876 && (!it->multibyte_p || it->char_to_display < 128))
17877 {
17878 /* Either unibyte or ASCII. */
17879 int stretched_p;
17880
17881 it->nglyphs = 1;
17882
17883 pcm = rif->per_char_metric (font, &char2b,
17884 FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
17885 it->ascent = FONT_BASE (font) + boff;
17886 it->descent = FONT_DESCENT (font) - boff;
17887
17888 if (pcm)
17889 {
17890 it->phys_ascent = pcm->ascent + boff;
17891 it->phys_descent = pcm->descent - boff;
17892 it->pixel_width = pcm->width;
17893 }
17894 else
17895 {
17896 it->glyph_not_available_p = 1;
17897 it->phys_ascent = FONT_BASE (font) + boff;
17898 it->phys_descent = FONT_DESCENT (font) - boff;
17899 it->pixel_width = FONT_WIDTH (font);
17900 }
17901
17902 /* If this is a space inside a region of text with
17903 `space-width' property, change its width. */
17904 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
17905 if (stretched_p)
17906 it->pixel_width *= XFLOATINT (it->space_width);
17907
17908 /* If face has a box, add the box thickness to the character
17909 height. If character has a box line to the left and/or
17910 right, add the box line width to the character's width. */
17911 if (face->box != FACE_NO_BOX)
17912 {
17913 int thick = face->box_line_width;
17914
17915 if (thick > 0)
17916 {
17917 it->ascent += thick;
17918 it->descent += thick;
17919 }
17920 else
17921 thick = -thick;
17922
17923 if (it->start_of_box_run_p)
17924 it->pixel_width += thick;
17925 if (it->end_of_box_run_p)
17926 it->pixel_width += thick;
17927 }
17928
17929 /* If face has an overline, add the height of the overline
17930 (1 pixel) and a 1 pixel margin to the character height. */
17931 if (face->overline_p)
17932 it->ascent += 2;
17933
17934 take_vertical_position_into_account (it);
17935
17936 /* If we have to actually produce glyphs, do it. */
17937 if (it->glyph_row)
17938 {
17939 if (stretched_p)
17940 {
17941 /* Translate a space with a `space-width' property
17942 into a stretch glyph. */
17943 double ascent = (double) FONT_BASE (font)
17944 / FONT_HEIGHT (font);
17945 append_stretch_glyph (it, it->object, it->pixel_width,
17946 it->ascent + it->descent, ascent);
17947 }
17948 else
17949 append_glyph (it);
17950
17951 /* If characters with lbearing or rbearing are displayed
17952 in this line, record that fact in a flag of the
17953 glyph row. This is used to optimize X output code. */
17954 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
17955 it->glyph_row->contains_overlapping_glyphs_p = 1;
17956 }
17957 }
17958 else if (it->char_to_display == '\n')
17959 {
17960 /* A newline has no width but we need the height of the line. */
17961 it->pixel_width = 0;
17962 it->nglyphs = 0;
17963 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
17964 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
17965
17966 if (face->box != FACE_NO_BOX
17967 && face->box_line_width > 0)
17968 {
17969 it->ascent += face->box_line_width;
17970 it->descent += face->box_line_width;
17971 }
17972 }
17973 else if (it->char_to_display == '\t')
17974 {
da8b7f4f 17975 int tab_width = it->tab_width * FRAME_COLUMN_WIDTH (it->f);
133c764e
KS
17976 int x = it->current_x + it->continuation_lines_width;
17977 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
17978
17979 /* If the distance from the current position to the next tab
17980 stop is less than a canonical character width, use the
17981 tab stop after that. */
da8b7f4f 17982 if (next_tab_x - x < FRAME_COLUMN_WIDTH (it->f))
133c764e
KS
17983 next_tab_x += tab_width;
17984
17985 it->pixel_width = next_tab_x - x;
17986 it->nglyphs = 1;
17987 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
17988 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
17989
17990 if (it->glyph_row)
17991 {
17992 double ascent = (double) it->ascent / (it->ascent + it->descent);
17993 append_stretch_glyph (it, it->object, it->pixel_width,
17994 it->ascent + it->descent, ascent);
17995 }
17996 }
17997 else
17998 {
17999 /* A multi-byte character. Assume that the display width of the
18000 character is the width of the character multiplied by the
18001 width of the font. */
18002
18003 /* If we found a font, this font should give us the right
18004 metrics. If we didn't find a font, use the frame's
18005 default font and calculate the width of the character
18006 from the charset width; this is what old redisplay code
18007 did. */
18008
18009 pcm = rif->per_char_metric (font, &char2b,
18010 FONT_TYPE_FOR_MULTIBYTE (font, it->c));
18011
18012 if (font_not_found_p || !pcm)
18013 {
18014 int charset = CHAR_CHARSET (it->char_to_display);
18015
18016 it->glyph_not_available_p = 1;
da8b7f4f 18017 it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
133c764e
KS
18018 * CHARSET_WIDTH (charset));
18019 it->phys_ascent = FONT_BASE (font) + boff;
18020 it->phys_descent = FONT_DESCENT (font) - boff;
18021 }
18022 else
18023 {
18024 it->pixel_width = pcm->width;
18025 it->phys_ascent = pcm->ascent + boff;
18026 it->phys_descent = pcm->descent - boff;
18027 if (it->glyph_row
18028 && (pcm->lbearing < 0
18029 || pcm->rbearing > pcm->width))
18030 it->glyph_row->contains_overlapping_glyphs_p = 1;
18031 }
18032 it->nglyphs = 1;
18033 it->ascent = FONT_BASE (font) + boff;
18034 it->descent = FONT_DESCENT (font) - boff;
18035 if (face->box != FACE_NO_BOX)
18036 {
18037 int thick = face->box_line_width;
18038
18039 if (thick > 0)
18040 {
18041 it->ascent += thick;
18042 it->descent += thick;
18043 }
18044 else
18045 thick = - thick;
18046
18047 if (it->start_of_box_run_p)
18048 it->pixel_width += thick;
18049 if (it->end_of_box_run_p)
18050 it->pixel_width += thick;
18051 }
18052
18053 /* If face has an overline, add the height of the overline
18054 (1 pixel) and a 1 pixel margin to the character height. */
18055 if (face->overline_p)
18056 it->ascent += 2;
18057
18058 take_vertical_position_into_account (it);
18059
18060 if (it->glyph_row)
18061 append_glyph (it);
18062 }
18063 it->multibyte_p = saved_multibyte_p;
18064 }
18065 else if (it->what == IT_COMPOSITION)
18066 {
18067 /* Note: A composition is represented as one glyph in the
18068 glyph matrix. There are no padding glyphs. */
18069 XChar2b char2b;
18070 XFontStruct *font;
18071 struct face *face = FACE_FROM_ID (it->f, it->face_id);
18072 XCharStruct *pcm;
18073 int font_not_found_p;
18074 struct font_info *font_info;
18075 int boff; /* baseline offset */
18076 struct composition *cmp = composition_table[it->cmp_id];
18077
18078 /* Maybe translate single-byte characters to multibyte. */
18079 it->char_to_display = it->c;
18080 if (unibyte_display_via_language_environment
18081 && SINGLE_BYTE_CHAR_P (it->c)
18082 && (it->c >= 0240
18083 || (it->c >= 0200
18084 && !NILP (Vnonascii_translation_table))))
18085 {
18086 it->char_to_display = unibyte_char_to_multibyte (it->c);
18087 }
18088
18089 /* Get face and font to use. Encode IT->char_to_display. */
18090 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
18091 face = FACE_FROM_ID (it->f, it->face_id);
18092 get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
18093 &char2b, it->multibyte_p, 0);
18094 font = face->font;
18095
18096 /* When no suitable font found, use the default font. */
18097 font_not_found_p = font == NULL;
18098 if (font_not_found_p)
18099 {
18100 font = FRAME_FONT (it->f);
18101 boff = FRAME_BASELINE_OFFSET (it->f);
18102 font_info = NULL;
18103 }
18104 else
18105 {
18106 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
18107 boff = font_info->baseline_offset;
18108 if (font_info->vertical_centering)
18109 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
18110 }
18111
18112 /* There are no padding glyphs, so there is only one glyph to
18113 produce for the composition. Important is that pixel_width,
18114 ascent and descent are the values of what is drawn by
18115 draw_glyphs (i.e. the values of the overall glyphs composed). */
18116 it->nglyphs = 1;
18117
18118 /* If we have not yet calculated pixel size data of glyphs of
18119 the composition for the current face font, calculate them
18120 now. Theoretically, we have to check all fonts for the
18121 glyphs, but that requires much time and memory space. So,
18122 here we check only the font of the first glyph. This leads
18123 to incorrect display very rarely, and C-l (recenter) can
18124 correct the display anyway. */
18125 if (cmp->font != (void *) font)
18126 {
18127 /* Ascent and descent of the font of the first character of
18128 this composition (adjusted by baseline offset). Ascent
18129 and descent of overall glyphs should not be less than
18130 them respectively. */
18131 int font_ascent = FONT_BASE (font) + boff;
18132 int font_descent = FONT_DESCENT (font) - boff;
18133 /* Bounding box of the overall glyphs. */
18134 int leftmost, rightmost, lowest, highest;
18135 int i, width, ascent, descent;
18136
18137 cmp->font = (void *) font;
18138
18139 /* Initialize the bounding box. */
18140 if (font_info
18141 && (pcm = rif->per_char_metric (font, &char2b,
18142 FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
18143 {
18144 width = pcm->width;
18145 ascent = pcm->ascent;
18146 descent = pcm->descent;
18147 }
18148 else
18149 {
18150 width = FONT_WIDTH (font);
18151 ascent = FONT_BASE (font);
18152 descent = FONT_DESCENT (font);
18153 }
18154
18155 rightmost = width;
18156 lowest = - descent + boff;
18157 highest = ascent + boff;
18158 leftmost = 0;
18159
18160 if (font_info
18161 && font_info->default_ascent
18162 && CHAR_TABLE_P (Vuse_default_ascent)
18163 && !NILP (Faref (Vuse_default_ascent,
18164 make_number (it->char_to_display))))
18165 highest = font_info->default_ascent + boff;
18166
18167 /* Draw the first glyph at the normal position. It may be
18168 shifted to right later if some other glyphs are drawn at
18169 the left. */
18170 cmp->offsets[0] = 0;
18171 cmp->offsets[1] = boff;
18172
18173 /* Set cmp->offsets for the remaining glyphs. */
18174 for (i = 1; i < cmp->glyph_len; i++)
18175 {
18176 int left, right, btm, top;
18177 int ch = COMPOSITION_GLYPH (cmp, i);
18178 int face_id = FACE_FOR_CHAR (it->f, face, ch);
18179
18180 face = FACE_FROM_ID (it->f, face_id);
18181 get_char_face_and_encoding (it->f, ch, face->id,
18182 &char2b, it->multibyte_p, 0);
18183 font = face->font;
18184 if (font == NULL)
18185 {
18186 font = FRAME_FONT (it->f);
2a6d0874 18187 boff = FRAME_BASELINE_OFFSET (it->f);
133c764e
KS
18188 font_info = NULL;
18189 }
18190 else
18191 {
18192 font_info
18193 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
18194 boff = font_info->baseline_offset;
18195 if (font_info->vertical_centering)
18196 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
18197 }
18198
18199 if (font_info
2a6d0874 18200 && (pcm = rif->per_char_metric (font, &char2b,
133c764e
KS
18201 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
18202 {
18203 width = pcm->width;
18204 ascent = pcm->ascent;
18205 descent = pcm->descent;
18206 }
18207 else
18208 {
18209 width = FONT_WIDTH (font);
18210 ascent = 1;
18211 descent = 0;
18212 }
18213
18214 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
18215 {
18216 /* Relative composition with or without
18217 alternate chars. */
18218 left = (leftmost + rightmost - width) / 2;
18219 btm = - descent + boff;
18220 if (font_info && font_info->relative_compose
18221 && (! CHAR_TABLE_P (Vignore_relative_composition)
18222 || NILP (Faref (Vignore_relative_composition,
18223 make_number (ch)))))
18224 {
18225
18226 if (- descent >= font_info->relative_compose)
18227 /* One extra pixel between two glyphs. */
18228 btm = highest + 1;
18229 else if (ascent <= 0)
18230 /* One extra pixel between two glyphs. */
18231 btm = lowest - 1 - ascent - descent;
18232 }
18233 }
18234 else
18235 {
18236 /* A composition rule is specified by an integer
18237 value that encodes global and new reference
18238 points (GREF and NREF). GREF and NREF are
18239 specified by numbers as below:
18240
18241 0---1---2 -- ascent
18242 | |
18243 | |
18244 | |
18245 9--10--11 -- center
18246 | |
18247 ---3---4---5--- baseline
18248 | |
18249 6---7---8 -- descent
18250 */
18251 int rule = COMPOSITION_RULE (cmp, i);
18252 int gref, nref, grefx, grefy, nrefx, nrefy;
18253
18254 COMPOSITION_DECODE_RULE (rule, gref, nref);
18255 grefx = gref % 3, nrefx = nref % 3;
18256 grefy = gref / 3, nrefy = nref / 3;
18257
18258 left = (leftmost
18259 + grefx * (rightmost - leftmost) / 2
18260 - nrefx * width / 2);
18261 btm = ((grefy == 0 ? highest
18262 : grefy == 1 ? 0
18263 : grefy == 2 ? lowest
18264 : (highest + lowest) / 2)
18265 - (nrefy == 0 ? ascent + descent
18266 : nrefy == 1 ? descent - boff
18267 : nrefy == 2 ? 0
18268 : (ascent + descent) / 2));
18269 }
18270
18271 cmp->offsets[i * 2] = left;
18272 cmp->offsets[i * 2 + 1] = btm + descent;
18273
18274 /* Update the bounding box of the overall glyphs. */
18275 right = left + width;
18276 top = btm + descent + ascent;
18277 if (left < leftmost)
18278 leftmost = left;
18279 if (right > rightmost)
18280 rightmost = right;
18281 if (top > highest)
18282 highest = top;
18283 if (btm < lowest)
18284 lowest = btm;
18285 }
18286
18287 /* If there are glyphs whose x-offsets are negative,
18288 shift all glyphs to the right and make all x-offsets
18289 non-negative. */
18290 if (leftmost < 0)
18291 {
18292 for (i = 0; i < cmp->glyph_len; i++)
18293 cmp->offsets[i * 2] -= leftmost;
18294 rightmost -= leftmost;
18295 }
18296
18297 cmp->pixel_width = rightmost;
18298 cmp->ascent = highest;
18299 cmp->descent = - lowest;
18300 if (cmp->ascent < font_ascent)
18301 cmp->ascent = font_ascent;
18302 if (cmp->descent < font_descent)
18303 cmp->descent = font_descent;
18304 }
18305
18306 it->pixel_width = cmp->pixel_width;
18307 it->ascent = it->phys_ascent = cmp->ascent;
18308 it->descent = it->phys_descent = cmp->descent;
18309
18310 if (face->box != FACE_NO_BOX)
18311 {
18312 int thick = face->box_line_width;
18313
18314 if (thick > 0)
18315 {
18316 it->ascent += thick;
18317 it->descent += thick;
18318 }
18319 else
18320 thick = - thick;
18321
18322 if (it->start_of_box_run_p)
18323 it->pixel_width += thick;
18324 if (it->end_of_box_run_p)
18325 it->pixel_width += thick;
18326 }
18327
18328 /* If face has an overline, add the height of the overline
18329 (1 pixel) and a 1 pixel margin to the character height. */
18330 if (face->overline_p)
18331 it->ascent += 2;
18332
18333 take_vertical_position_into_account (it);
18334
18335 if (it->glyph_row)
18336 append_composite_glyph (it);
18337 }
18338 else if (it->what == IT_IMAGE)
18339 produce_image_glyph (it);
18340 else if (it->what == IT_STRETCH)
18341 produce_stretch_glyph (it);
18342
18343 /* Accumulate dimensions. Note: can't assume that it->descent > 0
18344 because this isn't true for images with `:ascent 100'. */
18345 xassert (it->ascent >= 0 && it->descent >= 0);
18346 if (it->area == TEXT_AREA)
18347 it->current_x += it->pixel_width;
18348
18349 it->descent += it->extra_line_spacing;
18350
18351 it->max_ascent = max (it->max_ascent, it->ascent);
18352 it->max_descent = max (it->max_descent, it->descent);
18353 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
18354 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
18355}
18356
fa3c6b4d
KS
18357/* EXPORT for RIF:
18358 Output LEN glyphs starting at START at the nominal cursor position.
18359 Advance the nominal cursor over the text. The global variable
18360 updated_window contains the window being updated, updated_row is
18361 the glyph row being updated, and updated_area is the area of that
18362 row being updated. */
133c764e 18363
fa3c6b4d
KS
18364void
18365x_write_glyphs (start, len)
18366 struct glyph *start;
18367 int len;
18368{
18369 int x, hpos;
133c764e 18370
fa3c6b4d
KS
18371 xassert (updated_window && updated_row);
18372 BLOCK_INPUT;
133c764e 18373
fa3c6b4d 18374 /* Write glyphs. */
cfe03a41 18375
fa3c6b4d
KS
18376 hpos = start - updated_row->glyphs[updated_area];
18377 x = draw_glyphs (updated_window, output_cursor.x,
18378 updated_row, updated_area,
18379 hpos, hpos + len,
18380 DRAW_NORMAL_TEXT, 0);
cfe03a41 18381
fa3c6b4d
KS
18382 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
18383 if (updated_area == TEXT_AREA
18384 && updated_window->phys_cursor_on_p
18385 && updated_window->phys_cursor.vpos == output_cursor.vpos
18386 && updated_window->phys_cursor.hpos >= hpos
18387 && updated_window->phys_cursor.hpos < hpos + len)
18388 updated_window->phys_cursor_on_p = 0;
cfe03a41 18389
fa3c6b4d 18390 UNBLOCK_INPUT;
cfe03a41 18391
fa3c6b4d
KS
18392 /* Advance the output cursor. */
18393 output_cursor.hpos += len;
18394 output_cursor.x = x;
18395}
cfe03a41 18396
cfe03a41 18397
fa3c6b4d
KS
18398/* EXPORT for RIF:
18399 Insert LEN glyphs from START at the nominal cursor position. */
18400
18401void
18402x_insert_glyphs (start, len)
18403 struct glyph *start;
18404 int len;
18405{
18406 struct frame *f;
18407 struct window *w;
18408 int line_height, shift_by_width, shifted_region_width;
18409 struct glyph_row *row;
18410 struct glyph *glyph;
18411 int frame_x, frame_y, hpos;
18412
18413 xassert (updated_window && updated_row);
18414 BLOCK_INPUT;
18415 w = updated_window;
18416 f = XFRAME (WINDOW_FRAME (w));
18417
18418 /* Get the height of the line we are in. */
18419 row = updated_row;
18420 line_height = row->height;
18421
18422 /* Get the width of the glyphs to insert. */
18423 shift_by_width = 0;
18424 for (glyph = start; glyph < start + len; ++glyph)
18425 shift_by_width += glyph->pixel_width;
18426
18427 /* Get the width of the region to shift right. */
18428 shifted_region_width = (window_box_width (w, updated_area)
18429 - output_cursor.x
18430 - shift_by_width);
18431
18432 /* Shift right. */
18433 frame_x = window_box_left (w, updated_area) + output_cursor.x;
18434 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
18435
7b7b454e
AS
18436 rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
18437 line_height, shift_by_width);
fa3c6b4d
KS
18438
18439 /* Write the glyphs. */
18440 hpos = start - row->glyphs[updated_area];
18441 draw_glyphs (w, output_cursor.x, row, updated_area,
18442 hpos, hpos + len,
18443 DRAW_NORMAL_TEXT, 0);
18444
18445 /* Advance the output cursor. */
18446 output_cursor.hpos += len;
18447 output_cursor.x += shift_by_width;
18448 UNBLOCK_INPUT;
18449}
18450
18451
18452/* EXPORT for RIF:
18453 Erase the current text line from the nominal cursor position
18454 (inclusive) to pixel column TO_X (exclusive). The idea is that
18455 everything from TO_X onward is already erased.
18456
18457 TO_X is a pixel position relative to updated_area of
18458 updated_window. TO_X == -1 means clear to the end of this area. */
18459
18460void
18461x_clear_end_of_line (to_x)
18462 int to_x;
18463{
18464 struct frame *f;
18465 struct window *w = updated_window;
18466 int max_x, min_y, max_y;
18467 int from_x, from_y, to_y;
18468
18469 xassert (updated_window && updated_row);
18470 f = XFRAME (w->frame);
18471
18472 if (updated_row->full_width_p)
da8b7f4f 18473 max_x = WINDOW_TOTAL_WIDTH (w);
fa3c6b4d
KS
18474 else
18475 max_x = window_box_width (w, updated_area);
18476 max_y = window_text_bottom_y (w);
18477
18478 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
18479 of window. For TO_X > 0, truncate to end of drawing area. */
18480 if (to_x == 0)
18481 return;
18482 else if (to_x < 0)
18483 to_x = max_x;
18484 else
18485 to_x = min (to_x, max_x);
18486
18487 to_y = min (max_y, output_cursor.y + updated_row->height);
18488
18489 /* Notice if the cursor will be cleared by this operation. */
18490 if (!updated_row->full_width_p)
18491 notice_overwritten_cursor (w, updated_area,
18492 output_cursor.x, -1,
18493 updated_row->y,
18494 MATRIX_ROW_BOTTOM_Y (updated_row));
18495
18496 from_x = output_cursor.x;
18497
18498 /* Translate to frame coordinates. */
18499 if (updated_row->full_width_p)
18500 {
18501 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
18502 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
18503 }
18504 else
18505 {
da8b7f4f
KS
18506 int area_left = window_box_left (w, updated_area);
18507 from_x += area_left;
18508 to_x += area_left;
fa3c6b4d
KS
18509 }
18510
da8b7f4f 18511 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
fa3c6b4d
KS
18512 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
18513 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
18514
18515 /* Prevent inadvertently clearing to end of the X window. */
18516 if (to_x > from_x && to_y > from_y)
18517 {
18518 BLOCK_INPUT;
18519 rif->clear_frame_area (f, from_x, from_y,
18520 to_x - from_x, to_y - from_y);
18521 UNBLOCK_INPUT;
18522 }
18523}
18524
18525#endif /* HAVE_WINDOW_SYSTEM */
18526
18527
18528\f
18529/***********************************************************************
18530 Cursor types
18531 ***********************************************************************/
18532
18533/* Value is the internal representation of the specified cursor type
18534 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
18535 of the bar cursor. */
18536
18537enum text_cursor_kinds
18538get_specified_cursor_type (arg, width)
18539 Lisp_Object arg;
18540 int *width;
18541{
18542 enum text_cursor_kinds type;
18543
18544 if (NILP (arg))
18545 return NO_CURSOR;
18546
18547 if (EQ (arg, Qbox))
18548 return FILLED_BOX_CURSOR;
18549
18550 if (EQ (arg, Qhollow))
18551 return HOLLOW_BOX_CURSOR;
18552
18553 if (EQ (arg, Qbar))
18554 {
18555 *width = 2;
18556 return BAR_CURSOR;
18557 }
18558
18559 if (CONSP (arg)
18560 && EQ (XCAR (arg), Qbar)
18561 && INTEGERP (XCDR (arg))
18562 && XINT (XCDR (arg)) >= 0)
18563 {
18564 *width = XINT (XCDR (arg));
18565 return BAR_CURSOR;
18566 }
18567
18568 if (EQ (arg, Qhbar))
18569 {
18570 *width = 2;
18571 return HBAR_CURSOR;
18572 }
18573
18574 if (CONSP (arg)
18575 && EQ (XCAR (arg), Qhbar)
18576 && INTEGERP (XCDR (arg))
18577 && XINT (XCDR (arg)) >= 0)
18578 {
18579 *width = XINT (XCDR (arg));
18580 return HBAR_CURSOR;
18581 }
18582
18583 /* Treat anything unknown as "hollow box cursor".
18584 It was bad to signal an error; people have trouble fixing
18585 .Xdefaults with Emacs, when it has something bad in it. */
18586 type = HOLLOW_BOX_CURSOR;
18587
18588 return type;
18589}
18590
18591/* Set the default cursor types for specified frame. */
18592void
18593set_frame_cursor_types (f, arg)
18594 struct frame *f;
18595 Lisp_Object arg;
18596{
18597 int width;
18598 Lisp_Object tem;
18599
18600 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
18601 FRAME_CURSOR_WIDTH (f) = width;
18602
18603 /* By default, set up the blink-off state depending on the on-state. */
18604
18605 tem = Fassoc (arg, Vblink_cursor_alist);
18606 if (!NILP (tem))
18607 {
18608 FRAME_BLINK_OFF_CURSOR (f)
18609 = get_specified_cursor_type (XCDR (tem), &width);
18610 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
18611 }
18612 else
18613 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
18614}
18615
18616
18617/* Return the cursor we want to be displayed in window W. Return
18618 width of bar/hbar cursor through WIDTH arg. Return with
18619 ACTIVE_CURSOR arg set to 1 if cursor in window W is `active'
18620 (i.e. if the `system caret' should track this cursor).
18621
18622 In a mini-buffer window, we want the cursor only to appear if we
18623 are reading input from this window. For the selected window, we
18624 want the cursor type given by the frame parameter or buffer local
18625 setting of cursor-type. If explicitly marked off, draw no cursor.
18626 In all other cases, we want a hollow box cursor. */
18627
18628enum text_cursor_kinds
18629get_window_cursor_type (w, width, active_cursor)
18630 struct window *w;
18631 int *width;
18632 int *active_cursor;
18633{
18634 struct frame *f = XFRAME (w->frame);
18635 struct buffer *b = XBUFFER (w->buffer);
18636 int cursor_type = DEFAULT_CURSOR;
18637 Lisp_Object alt_cursor;
18638 int non_selected = 0;
18639
18640 *active_cursor = 1;
18641
18642 /* Echo area */
18643 if (cursor_in_echo_area
18644 && FRAME_HAS_MINIBUF_P (f)
18645 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
18646 {
18647 if (w == XWINDOW (echo_area_window))
18648 {
18649 *width = FRAME_CURSOR_WIDTH (f);
18650 return FRAME_DESIRED_CURSOR (f);
18651 }
18652
18653 *active_cursor = 0;
18654 non_selected = 1;
18655 }
18656
18657 /* Nonselected window or nonselected frame. */
18658 else if (w != XWINDOW (f->selected_window)
18659#ifdef HAVE_WINDOW_SYSTEM
18660 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
18661#endif
18662 )
18663 {
18664 *active_cursor = 0;
18665
18666 if (MINI_WINDOW_P (w) && minibuf_level == 0)
18667 return NO_CURSOR;
18668
18669 non_selected = 1;
18670 }
18671
18672 /* Never display a cursor in a window in which cursor-type is nil. */
18673 if (NILP (b->cursor_type))
18674 return NO_CURSOR;
18675
18676 /* Use cursor-in-non-selected-windows for non-selected window or frame. */
18677 if (non_selected)
18678 {
18679 alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer);
18680 return get_specified_cursor_type (alt_cursor, width);
18681 }
18682
18683 /* Get the normal cursor type for this window. */
18684 if (EQ (b->cursor_type, Qt))
18685 {
18686 cursor_type = FRAME_DESIRED_CURSOR (f);
18687 *width = FRAME_CURSOR_WIDTH (f);
18688 }
18689 else
18690 cursor_type = get_specified_cursor_type (b->cursor_type, width);
18691
18692 /* Use normal cursor if not blinked off. */
18693 if (!w->cursor_off_p)
18694 return cursor_type;
18695
18696 /* Cursor is blinked off, so determine how to "toggle" it. */
18697
18698 /* First look for an entry matching the buffer's cursor-type in blink-cursor-alist. */
18699 if ((alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor)))
18700 return get_specified_cursor_type (XCDR (alt_cursor), width);
18701
18702 /* Then see if frame has specified a specific blink off cursor type. */
18703 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
18704 {
18705 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
18706 return FRAME_BLINK_OFF_CURSOR (f);
18707 }
18708
18709 /* Finally perform built-in cursor blinking:
18710 filled box <-> hollow box
18711 wide [h]bar <-> narrow [h]bar
18712 narrow [h]bar <-> no cursor
18713 other type <-> no cursor */
18714
18715 if (cursor_type == FILLED_BOX_CURSOR)
18716 return HOLLOW_BOX_CURSOR;
18717
18718 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
18719 {
18720 *width = 1;
18721 return cursor_type;
18722 }
18723
18724 return NO_CURSOR;
18725}
18726
18727
18728#ifdef HAVE_WINDOW_SYSTEM
18729
18730/* Notice when the text cursor of window W has been completely
18731 overwritten by a drawing operation that outputs glyphs in AREA
18732 starting at X0 and ending at X1 in the line starting at Y0 and
18733 ending at Y1. X coordinates are area-relative. X1 < 0 means all
18734 the rest of the line after X0 has been written. Y coordinates
18735 are window-relative. */
18736
18737static void
18738notice_overwritten_cursor (w, area, x0, x1, y0, y1)
18739 struct window *w;
18740 enum glyph_row_area area;
18741 int x0, y0, x1, y1;
18742{
fa3c6b4d
KS
18743 if (area == TEXT_AREA && w->phys_cursor_on_p)
18744 {
18745 int cx0 = w->phys_cursor.x;
18746 int cx1 = cx0 + w->phys_cursor_width;
18747 int cy0 = w->phys_cursor.y;
18748 int cy1 = cy0 + w->phys_cursor_height;
18749
18750 if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
18751 {
18752 /* The cursor image will be completely removed from the
18753 screen if the output area intersects the cursor area in
18754 y-direction. When we draw in [y0 y1[, and some part of
18755 the cursor is at y < y0, that part must have been drawn
18756 before. When scrolling, the cursor is erased before
18757 actually scrolling, so we don't come here. When not
18758 scrolling, the rows above the old cursor row must have
18759 changed, and in this case these rows must have written
18760 over the cursor image.
18761
18762 Likewise if part of the cursor is below y1, with the
18763 exception of the cursor being in the first blank row at
18764 the buffer and window end because update_text_area
18765 doesn't draw that row. (Except when it does, but
18766 that's handled in update_text_area.) */
18767
18768 if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
18769 && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
18770 w->phys_cursor_on_p = 0;
18771 }
18772 }
fa3c6b4d
KS
18773}
18774
18775#endif /* HAVE_WINDOW_SYSTEM */
18776
18777\f
18778/************************************************************************
18779 Mouse Face
18780 ************************************************************************/
18781
18782#ifdef HAVE_WINDOW_SYSTEM
18783
18784/* EXPORT for RIF:
18785 Fix the display of area AREA of overlapping row ROW in window W. */
18786
18787void
18788x_fix_overlapping_area (w, row, area)
18789 struct window *w;
18790 struct glyph_row *row;
18791 enum glyph_row_area area;
18792{
18793 int i, x;
18794
18795 BLOCK_INPUT;
18796
57dd22f4 18797 x = 0;
fa3c6b4d
KS
18798 for (i = 0; i < row->used[area];)
18799 {
18800 if (row->glyphs[area][i].overlaps_vertically_p)
18801 {
18802 int start = i, start_x = x;
18803
18804 do
18805 {
18806 x += row->glyphs[area][i].pixel_width;
18807 ++i;
18808 }
18809 while (i < row->used[area]
18810 && row->glyphs[area][i].overlaps_vertically_p);
18811
18812 draw_glyphs (w, start_x, row, area,
18813 start, i,
18814 DRAW_NORMAL_TEXT, 1);
18815 }
18816 else
18817 {
18818 x += row->glyphs[area][i].pixel_width;
18819 ++i;
18820 }
18821 }
18822
18823 UNBLOCK_INPUT;
18824}
18825
18826
18827/* EXPORT:
18828 Draw the cursor glyph of window W in glyph row ROW. See the
18829 comment of draw_glyphs for the meaning of HL. */
18830
18831void
18832draw_phys_cursor_glyph (w, row, hl)
18833 struct window *w;
18834 struct glyph_row *row;
18835 enum draw_glyphs_face hl;
18836{
18837 /* If cursor hpos is out of bounds, don't draw garbage. This can
18838 happen in mini-buffer windows when switching between echo area
18839 glyphs and mini-buffer. */
18840 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
18841 {
18842 int on_p = w->phys_cursor_on_p;
18843 int x1;
18844 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
18845 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
18846 hl, 0);
18847 w->phys_cursor_on_p = on_p;
18848
fa3c6b4d
KS
18849 if (hl == DRAW_CURSOR)
18850 w->phys_cursor_width = x1 - w->phys_cursor.x;
fa3c6b4d
KS
18851 /* When we erase the cursor, and ROW is overlapped by other
18852 rows, make sure that these overlapping parts of other rows
18853 are redrawn. */
365fa1b3 18854 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
fa3c6b4d
KS
18855 {
18856 if (row > w->current_matrix->rows
18857 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
18858 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
18859
18860 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
18861 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
18862 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
18863 }
18864 }
18865}
18866
18867
18868/* EXPORT:
18869 Erase the image of a cursor of window W from the screen. */
18870
18871void
18872erase_phys_cursor (w)
18873 struct window *w;
18874{
18875 struct frame *f = XFRAME (w->frame);
18876 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
18877 int hpos = w->phys_cursor.hpos;
18878 int vpos = w->phys_cursor.vpos;
18879 int mouse_face_here_p = 0;
18880 struct glyph_matrix *active_glyphs = w->current_matrix;
18881 struct glyph_row *cursor_row;
18882 struct glyph *cursor_glyph;
18883 enum draw_glyphs_face hl;
18884
18885 /* No cursor displayed or row invalidated => nothing to do on the
18886 screen. */
18887 if (w->phys_cursor_type == NO_CURSOR)
18888 goto mark_cursor_off;
18889
18890 /* VPOS >= active_glyphs->nrows means that window has been resized.
18891 Don't bother to erase the cursor. */
18892 if (vpos >= active_glyphs->nrows)
18893 goto mark_cursor_off;
18894
18895 /* If row containing cursor is marked invalid, there is nothing we
18896 can do. */
18897 cursor_row = MATRIX_ROW (active_glyphs, vpos);
18898 if (!cursor_row->enabled_p)
18899 goto mark_cursor_off;
18900
18901 /* If row is completely invisible, don't attempt to delete a cursor which
18902 isn't there. This can happen if cursor is at top of a window, and
18903 we switch to a buffer with a header line in that window. */
18904 if (cursor_row->visible_height <= 0)
18905 goto mark_cursor_off;
18906
18907 /* This can happen when the new row is shorter than the old one.
18908 In this case, either draw_glyphs or clear_end_of_line
18909 should have cleared the cursor. Note that we wouldn't be
18910 able to erase the cursor in this case because we don't have a
18911 cursor glyph at hand. */
18912 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
18913 goto mark_cursor_off;
18914
18915 /* If the cursor is in the mouse face area, redisplay that when
18916 we clear the cursor. */
18917 if (! NILP (dpyinfo->mouse_face_window)
18918 && w == XWINDOW (dpyinfo->mouse_face_window)
18919 && (vpos > dpyinfo->mouse_face_beg_row
18920 || (vpos == dpyinfo->mouse_face_beg_row
18921 && hpos >= dpyinfo->mouse_face_beg_col))
18922 && (vpos < dpyinfo->mouse_face_end_row
18923 || (vpos == dpyinfo->mouse_face_end_row
18924 && hpos < dpyinfo->mouse_face_end_col))
18925 /* Don't redraw the cursor's spot in mouse face if it is at the
18926 end of a line (on a newline). The cursor appears there, but
18927 mouse highlighting does not. */
18928 && cursor_row->used[TEXT_AREA] > hpos)
18929 mouse_face_here_p = 1;
18930
18931 /* Maybe clear the display under the cursor. */
18932 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
18933 {
18934 int x, y;
da8b7f4f 18935 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
fa3c6b4d
KS
18936
18937 cursor_glyph = get_phys_cursor_glyph (w);
18938 if (cursor_glyph == NULL)
18939 goto mark_cursor_off;
18940
18941 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
18942 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
18943
18944 rif->clear_frame_area (f, x, y,
18945 cursor_glyph->pixel_width, cursor_row->visible_height);
18946 }
18947
18948 /* Erase the cursor by redrawing the character underneath it. */
18949 if (mouse_face_here_p)
18950 hl = DRAW_MOUSE_FACE;
18951 else
18952 hl = DRAW_NORMAL_TEXT;
18953 draw_phys_cursor_glyph (w, cursor_row, hl);
18954
18955 mark_cursor_off:
18956 w->phys_cursor_on_p = 0;
18957 w->phys_cursor_type = NO_CURSOR;
18958}
18959
18960
18961/* EXPORT:
18962 Display or clear cursor of window W. If ON is zero, clear the
18963 cursor. If it is non-zero, display the cursor. If ON is nonzero,
18964 where to put the cursor is specified by HPOS, VPOS, X and Y. */
18965
18966void
18967display_and_set_cursor (w, on, hpos, vpos, x, y)
18968 struct window *w;
18969 int on, hpos, vpos, x, y;
18970{
18971 struct frame *f = XFRAME (w->frame);
18972 int new_cursor_type;
18973 int new_cursor_width;
18974 int active_cursor;
18975 struct glyph_matrix *current_glyphs;
18976 struct glyph_row *glyph_row;
18977 struct glyph *glyph;
18978
18979 /* This is pointless on invisible frames, and dangerous on garbaged
18980 windows and frames; in the latter case, the frame or window may
18981 be in the midst of changing its size, and x and y may be off the
18982 window. */
18983 if (! FRAME_VISIBLE_P (f)
18984 || FRAME_GARBAGED_P (f)
18985 || vpos >= w->current_matrix->nrows
18986 || hpos >= w->current_matrix->matrix_w)
18987 return;
18988
18989 /* If cursor is off and we want it off, return quickly. */
18990 if (!on && !w->phys_cursor_on_p)
18991 return;
18992
18993 current_glyphs = w->current_matrix;
18994 glyph_row = MATRIX_ROW (current_glyphs, vpos);
18995 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
18996
18997 /* If cursor row is not enabled, we don't really know where to
18998 display the cursor. */
18999 if (!glyph_row->enabled_p)
19000 {
19001 w->phys_cursor_on_p = 0;
19002 return;
19003 }
19004
19005 xassert (interrupt_input_blocked);
19006
19007 /* Set new_cursor_type to the cursor we want to be displayed. */
19008 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
19009
19010 /* If cursor is currently being shown and we don't want it to be or
19011 it is in the wrong place, or the cursor type is not what we want,
19012 erase it. */
19013 if (w->phys_cursor_on_p
19014 && (!on
19015 || w->phys_cursor.x != x
19016 || w->phys_cursor.y != y
19017 || new_cursor_type != w->phys_cursor_type
19018 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
19019 && new_cursor_width != w->phys_cursor_width)))
19020 erase_phys_cursor (w);
19021
19022 /* Don't check phys_cursor_on_p here because that flag is only set
19023 to zero in some cases where we know that the cursor has been
19024 completely erased, to avoid the extra work of erasing the cursor
19025 twice. In other words, phys_cursor_on_p can be 1 and the cursor
19026 still not be visible, or it has only been partly erased. */
19027 if (on)
19028 {
19029 w->phys_cursor_ascent = glyph_row->ascent;
19030 w->phys_cursor_height = glyph_row->height;
19031
19032 /* Set phys_cursor_.* before x_draw_.* is called because some
19033 of them may need the information. */
19034 w->phys_cursor.x = x;
19035 w->phys_cursor.y = glyph_row->y;
19036 w->phys_cursor.hpos = hpos;
19037 w->phys_cursor.vpos = vpos;
19038 }
19039
b4ebbb12
KS
19040 rif->draw_window_cursor (w, glyph_row, x, y,
19041 new_cursor_type, new_cursor_width,
19042 on, active_cursor);
fa3c6b4d
KS
19043}
19044
19045
19046/* Switch the display of W's cursor on or off, according to the value
19047 of ON. */
19048
19049static void
19050update_window_cursor (w, on)
19051 struct window *w;
19052 int on;
19053{
19054 /* Don't update cursor in windows whose frame is in the process
19055 of being deleted. */
19056 if (w->current_matrix)
19057 {
19058 BLOCK_INPUT;
19059 display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
19060 w->phys_cursor.x, w->phys_cursor.y);
19061 UNBLOCK_INPUT;
19062 }
19063}
19064
19065
19066/* Call update_window_cursor with parameter ON_P on all leaf windows
19067 in the window tree rooted at W. */
19068
19069static void
19070update_cursor_in_window_tree (w, on_p)
19071 struct window *w;
19072 int on_p;
19073{
19074 while (w)
19075 {
19076 if (!NILP (w->hchild))
19077 update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
19078 else if (!NILP (w->vchild))
19079 update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
19080 else
19081 update_window_cursor (w, on_p);
19082
19083 w = NILP (w->next) ? 0 : XWINDOW (w->next);
19084 }
19085}
19086
19087
19088/* EXPORT:
19089 Display the cursor on window W, or clear it, according to ON_P.
19090 Don't change the cursor's position. */
19091
19092void
19093x_update_cursor (f, on_p)
19094 struct frame *f;
19095 int on_p;
19096{
19097 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
19098}
19099
19100
19101/* EXPORT:
19102 Clear the cursor of window W to background color, and mark the
19103 cursor as not shown. This is used when the text where the cursor
19104 is is about to be rewritten. */
19105
19106void
19107x_clear_cursor (w)
19108 struct window *w;
19109{
19110 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
19111 update_window_cursor (w, 0);
19112}
19113
19114
19115/* EXPORT:
19116 Display the active region described by mouse_face_* according to DRAW. */
19117
19118void
19119show_mouse_face (dpyinfo, draw)
19120 Display_Info *dpyinfo;
19121 enum draw_glyphs_face draw;
19122{
19123 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
19124 struct frame *f = XFRAME (WINDOW_FRAME (w));
19125
19126 if (/* If window is in the process of being destroyed, don't bother
19127 to do anything. */
19128 w->current_matrix != NULL
19129 /* Don't update mouse highlight if hidden */
19130 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
19131 /* Recognize when we are called to operate on rows that don't exist
19132 anymore. This can happen when a window is split. */
19133 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
19134 {
19135 int phys_cursor_on_p = w->phys_cursor_on_p;
19136 struct glyph_row *row, *first, *last;
19137
19138 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
19139 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
19140
19141 for (row = first; row <= last && row->enabled_p; ++row)
19142 {
19143 int start_hpos, end_hpos, start_x;
19144
19145 /* For all but the first row, the highlight starts at column 0. */
19146 if (row == first)
19147 {
19148 start_hpos = dpyinfo->mouse_face_beg_col;
19149 start_x = dpyinfo->mouse_face_beg_x;
19150 }
19151 else
19152 {
19153 start_hpos = 0;
19154 start_x = 0;
19155 }
19156
19157 if (row == last)
19158 end_hpos = dpyinfo->mouse_face_end_col;
19159 else
19160 end_hpos = row->used[TEXT_AREA];
19161
19162 if (end_hpos > start_hpos)
19163 {
19164 draw_glyphs (w, start_x, row, TEXT_AREA,
19165 start_hpos, end_hpos,
19166 draw, 0);
19167
19168 row->mouse_face_p
19169 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
19170 }
19171 }
19172
19173 /* When we've written over the cursor, arrange for it to
19174 be displayed again. */
19175 if (phys_cursor_on_p && !w->phys_cursor_on_p)
19176 {
19177 BLOCK_INPUT;
19178 display_and_set_cursor (w, 1,
19179 w->phys_cursor.hpos, w->phys_cursor.vpos,
19180 w->phys_cursor.x, w->phys_cursor.y);
19181 UNBLOCK_INPUT;
19182 }
19183 }
19184
19185 /* Change the mouse cursor. */
19186 if (draw == DRAW_NORMAL_TEXT)
19187 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
19188 else if (draw == DRAW_MOUSE_FACE)
19189 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
19190 else
19191 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
19192}
19193
19194/* EXPORT:
19195 Clear out the mouse-highlighted active region.
19196 Redraw it un-highlighted first. Value is non-zero if mouse
19197 face was actually drawn unhighlighted. */
19198
19199int
19200clear_mouse_face (dpyinfo)
19201 Display_Info *dpyinfo;
19202{
19203 int cleared = 0;
19204
19205 if (!NILP (dpyinfo->mouse_face_window))
19206 {
19207 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
19208 cleared = 1;
19209 }
19210
19211 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
19212 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
19213 dpyinfo->mouse_face_window = Qnil;
19214 dpyinfo->mouse_face_overlay = Qnil;
19215 return cleared;
19216}
19217
19218
19219/* EXPORT:
19220 Non-zero if physical cursor of window W is within mouse face. */
19221
19222int
19223cursor_in_mouse_face_p (w)
19224 struct window *w;
19225{
19226 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
19227 int in_mouse_face = 0;
19228
19229 if (WINDOWP (dpyinfo->mouse_face_window)
19230 && XWINDOW (dpyinfo->mouse_face_window) == w)
19231 {
19232 int hpos = w->phys_cursor.hpos;
19233 int vpos = w->phys_cursor.vpos;
19234
19235 if (vpos >= dpyinfo->mouse_face_beg_row
19236 && vpos <= dpyinfo->mouse_face_end_row
19237 && (vpos > dpyinfo->mouse_face_beg_row
19238 || hpos >= dpyinfo->mouse_face_beg_col)
19239 && (vpos < dpyinfo->mouse_face_end_row
19240 || hpos < dpyinfo->mouse_face_end_col
19241 || dpyinfo->mouse_face_past_end))
19242 in_mouse_face = 1;
19243 }
19244
19245 return in_mouse_face;
19246}
19247
19248
19249
19250\f
19251/* Find the glyph matrix position of buffer position CHARPOS in window
19252 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
19253 current glyphs must be up to date. If CHARPOS is above window
19254 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
19255 of last line in W. In the row containing CHARPOS, stop before glyphs
19256 having STOP as object. */
19257
9c3521e0 19258#if 1 /* This is a version of fast_find_position that's more correct
fa3c6b4d
KS
19259 in the presence of hscrolling, for example. I didn't install
19260 it right away because the problem fixed is minor, it failed
19261 in 20.x as well, and I think it's too risky to install
19262 so near the release of 21.1. 2001-09-25 gerd. */
19263
19264static int
19265fast_find_position (w, charpos, hpos, vpos, x, y, stop)
19266 struct window *w;
19267 int charpos;
19268 int *hpos, *vpos, *x, *y;
19269 Lisp_Object stop;
19270{
19271 struct glyph_row *row, *first;
19272 struct glyph *glyph, *end;
b19a5b64 19273 int past_end = 0;
fa3c6b4d
KS
19274
19275 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19276 row = row_containing_pos (w, charpos, first, NULL, 0);
19277 if (row == NULL)
19278 {
19279 if (charpos < MATRIX_ROW_START_CHARPOS (first))
19280 {
19281 *x = *y = *hpos = *vpos = 0;
19282 return 0;
19283 }
19284 else
19285 {
19286 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
19287 past_end = 1;
19288 }
19289 }
19290
19291 *x = row->x;
19292 *y = row->y;
19293 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
19294
19295 glyph = row->glyphs[TEXT_AREA];
19296 end = glyph + row->used[TEXT_AREA];
19297
19298 /* Skip over glyphs not having an object at the start of the row.
19299 These are special glyphs like truncation marks on terminal
19300 frames. */
19301 if (row->displays_text_p)
19302 while (glyph < end
19303 && INTEGERP (glyph->object)
19304 && !EQ (stop, glyph->object)
19305 && glyph->charpos < 0)
19306 {
19307 *x += glyph->pixel_width;
19308 ++glyph;
19309 }
19310
19311 while (glyph < end
19312 && !INTEGERP (glyph->object)
19313 && !EQ (stop, glyph->object)
19314 && (!BUFFERP (glyph->object)
19315 || glyph->charpos < charpos))
19316 {
19317 *x += glyph->pixel_width;
19318 ++glyph;
19319 }
19320
19321 *hpos = glyph - row->glyphs[TEXT_AREA];
19322 return past_end;
19323}
19324
9c3521e0 19325#else /* not 1 */
fa3c6b4d
KS
19326
19327static int
19328fast_find_position (w, pos, hpos, vpos, x, y, stop)
19329 struct window *w;
19330 int pos;
19331 int *hpos, *vpos, *x, *y;
19332 Lisp_Object stop;
19333{
19334 int i;
19335 int lastcol;
19336 int maybe_next_line_p = 0;
19337 int line_start_position;
19338 int yb = window_text_bottom_y (w);
19339 struct glyph_row *row, *best_row;
19340 int row_vpos, best_row_vpos;
19341 int current_x;
19342
19343 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19344 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
19345
19346 while (row->y < yb)
19347 {
19348 if (row->used[TEXT_AREA])
19349 line_start_position = row->glyphs[TEXT_AREA]->charpos;
19350 else
19351 line_start_position = 0;
19352
19353 if (line_start_position > pos)
19354 break;
19355 /* If the position sought is the end of the buffer,
19356 don't include the blank lines at the bottom of the window. */
19357 else if (line_start_position == pos
19358 && pos == BUF_ZV (XBUFFER (w->buffer)))
19359 {
19360 maybe_next_line_p = 1;
19361 break;
19362 }
19363 else if (line_start_position > 0)
19364 {
19365 best_row = row;
19366 best_row_vpos = row_vpos;
19367 }
19368
19369 if (row->y + row->height >= yb)
19370 break;
19371
19372 ++row;
19373 ++row_vpos;
19374 }
19375
19376 /* Find the right column within BEST_ROW. */
19377 lastcol = 0;
19378 current_x = best_row->x;
19379 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
19380 {
19381 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
19382 int charpos = glyph->charpos;
19383
19384 if (BUFFERP (glyph->object))
19385 {
19386 if (charpos == pos)
19387 {
19388 *hpos = i;
19389 *vpos = best_row_vpos;
19390 *x = current_x;
19391 *y = best_row->y;
19392 return 1;
19393 }
19394 else if (charpos > pos)
19395 break;
19396 }
19397 else if (EQ (glyph->object, stop))
19398 break;
19399
19400 if (charpos > 0)
19401 lastcol = i;
19402 current_x += glyph->pixel_width;
19403 }
19404
19405 /* If we're looking for the end of the buffer,
19406 and we didn't find it in the line we scanned,
19407 use the start of the following line. */
19408 if (maybe_next_line_p)
19409 {
19410 ++best_row;
19411 ++best_row_vpos;
19412 lastcol = 0;
19413 current_x = best_row->x;
19414 }
19415
19416 *vpos = best_row_vpos;
19417 *hpos = lastcol + 1;
19418 *x = current_x;
19419 *y = best_row->y;
19420 return 0;
19421}
19422
9c3521e0 19423#endif /* not 1 */
fa3c6b4d
KS
19424
19425
19426/* Find the position of the glyph for position POS in OBJECT in
19427 window W's current matrix, and return in *X, *Y the pixel
19428 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
19429
19430 RIGHT_P non-zero means return the position of the right edge of the
19431 glyph, RIGHT_P zero means return the left edge position.
19432
19433 If no glyph for POS exists in the matrix, return the position of
19434 the glyph with the next smaller position that is in the matrix, if
19435 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
19436 exists in the matrix, return the position of the glyph with the
19437 next larger position in OBJECT.
19438
19439 Value is non-zero if a glyph was found. */
19440
19441static int
19442fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
19443 struct window *w;
19444 int pos;
19445 Lisp_Object object;
19446 int *hpos, *vpos, *x, *y;
19447 int right_p;
19448{
19449 int yb = window_text_bottom_y (w);
19450 struct glyph_row *r;
19451 struct glyph *best_glyph = NULL;
19452 struct glyph_row *best_row = NULL;
19453 int best_x = 0;
19454
19455 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19456 r->enabled_p && r->y < yb;
19457 ++r)
19458 {
19459 struct glyph *g = r->glyphs[TEXT_AREA];
19460 struct glyph *e = g + r->used[TEXT_AREA];
19461 int gx;
19462
19463 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
19464 if (EQ (g->object, object))
19465 {
19466 if (g->charpos == pos)
19467 {
19468 best_glyph = g;
19469 best_x = gx;
19470 best_row = r;
19471 goto found;
19472 }
19473 else if (best_glyph == NULL
19474 || ((abs (g->charpos - pos)
19475 < abs (best_glyph->charpos - pos))
19476 && (right_p
19477 ? g->charpos < pos
19478 : g->charpos > pos)))
19479 {
19480 best_glyph = g;
19481 best_x = gx;
19482 best_row = r;
19483 }
19484 }
19485 }
19486
19487 found:
19488
19489 if (best_glyph)
19490 {
19491 *x = best_x;
19492 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
19493
19494 if (right_p)
19495 {
19496 *x += best_glyph->pixel_width;
19497 ++*hpos;
19498 }
19499
19500 *y = best_row->y;
19501 *vpos = best_row - w->current_matrix->rows;
19502 }
19503
19504 return best_glyph != NULL;
19505}
19506
19507
fa3c6b4d
KS
19508/* Take proper action when mouse has moved to the mode or header line
19509 or marginal area AREA of window W, x-position X and y-position Y.
19510 X is relative to the start of the text display area of W, so the
19511 width of bitmap areas and scroll bars must be subtracted to get a
19512 position relative to the start of the mode line. */
19513
19514static void
19515note_mode_line_or_margin_highlight (w, x, y, area)
19516 struct window *w;
19517 int x, y;
19518 enum window_part area;
19519{
19520 struct frame *f = XFRAME (w->frame);
19521 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
19522 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
19523 int charpos;
19524 Lisp_Object string, help, map, pos;
19525
19526 if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
19527 string = mode_line_string (w, x, y, area, &charpos);
19528 else
19529 string = marginal_area_string (w, x, y, area, &charpos);
19530
19531 if (STRINGP (string))
19532 {
19533 pos = make_number (charpos);
19534
19535 /* If we're on a string with `help-echo' text property, arrange
19536 for the help to be displayed. This is done by setting the
19537 global variable help_echo_string to the help string. */
19538 help = Fget_text_property (pos, Qhelp_echo, string);
19539 if (!NILP (help))
19540 {
19541 help_echo_string = help;
19542 XSETWINDOW (help_echo_window, w);
19543 help_echo_object = string;
19544 help_echo_pos = charpos;
19545 }
19546
19547 /* Change the mouse pointer according to what is under X/Y. */
19548 map = Fget_text_property (pos, Qlocal_map, string);
19549 if (!KEYMAPP (map))
19550 map = Fget_text_property (pos, Qkeymap, string);
19551 if (KEYMAPP (map))
19552 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
19553 }
19554
19555 rif->define_frame_cursor (f, cursor);
19556}
19557
fa3c6b4d
KS
19558
19559/* EXPORT:
19560 Take proper action when the mouse has moved to position X, Y on
19561 frame F as regards highlighting characters that have mouse-face
19562 properties. Also de-highlighting chars where the mouse was before.
19563 X and Y can be negative or out of range. */
19564
19565void
19566note_mouse_highlight (f, x, y)
19567 struct frame *f;
19568 int x, y;
19569{
19570 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
19571 enum window_part part;
19572 Lisp_Object window;
19573 struct window *w;
19574 Cursor cursor = No_Cursor;
19575 struct buffer *b;
19576
19577 /* When a menu is active, don't highlight because this looks odd. */
19578#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
19579 if (popup_activated ())
19580 return;
19581#endif
19582
19583 if (NILP (Vmouse_highlight)
19584 || !f->glyphs_initialized_p)
19585 return;
19586
19587 dpyinfo->mouse_face_mouse_x = x;
19588 dpyinfo->mouse_face_mouse_y = y;
19589 dpyinfo->mouse_face_mouse_frame = f;
19590
19591 if (dpyinfo->mouse_face_defer)
19592 return;
19593
19594 if (gc_in_progress)
19595 {
19596 dpyinfo->mouse_face_deferred_gc = 1;
19597 return;
19598 }
19599
19600 /* Which window is that in? */
da8b7f4f 19601 window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
fa3c6b4d
KS
19602
19603 /* If we were displaying active text in another window, clear that. */
19604 if (! EQ (window, dpyinfo->mouse_face_window))
19605 clear_mouse_face (dpyinfo);
19606
19607 /* Not on a window -> return. */
19608 if (!WINDOWP (window))
19609 return;
19610
19611 /* Reset help_echo_string. It will get recomputed below. */
19612 /* ++KFS: X version didn't do this, but it looks harmless. */
19613 help_echo_string = Qnil;
19614
19615 /* Convert to window-relative pixel coordinates. */
19616 w = XWINDOW (window);
19617 frame_to_window_pixel_xy (w, &x, &y);
19618
19619 /* Handle tool-bar window differently since it doesn't display a
19620 buffer. */
19621 if (EQ (window, f->tool_bar_window))
19622 {
19623 note_tool_bar_highlight (f, x, y);
19624 return;
19625 }
19626
fa3c6b4d
KS
19627 /* Mouse is on the mode, header line or margin? */
19628 if (part == ON_MODE_LINE || part == ON_HEADER_LINE
19629 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
19630 {
19631 note_mode_line_or_margin_highlight (w, x, y, part);
19632 return;
19633 }
fa3c6b4d
KS
19634
19635 if (part == ON_VERTICAL_BORDER)
19636 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
19637 else
19638 cursor = FRAME_X_OUTPUT (f)->text_cursor;
19639
19640 /* Are we in a window whose display is up to date?
19641 And verify the buffer's text has not changed. */
19642 b = XBUFFER (w->buffer);
19643 if (part == ON_TEXT
19644 && EQ (w->window_end_valid, w->buffer)
19645 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
19646 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
19647 {
19648 int hpos, vpos, pos, i, area;
19649 struct glyph *glyph;
19650 Lisp_Object object;
19651 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
19652 Lisp_Object *overlay_vec = NULL;
19653 int len, noverlays;
19654 struct buffer *obuf;
19655 int obegv, ozv, same_region;
19656
19657 /* Find the glyph under X/Y. */
19658 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
19659
19660 /* Clear mouse face if X/Y not over text. */
19661 if (glyph == NULL
19662 || area != TEXT_AREA
19663 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
19664 {
19665#if defined (HAVE_NTGUI)
19666 /* ++KFS: Why is this necessary on W32 ? */
19667 clear_mouse_face (dpyinfo);
19668 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
19669#else
19670 if (clear_mouse_face (dpyinfo))
19671 cursor = No_Cursor;
19672#endif
19673 goto set_cursor;
19674 }
19675
19676 pos = glyph->charpos;
19677 object = glyph->object;
19678 if (!STRINGP (object) && !BUFFERP (object))
19679 goto set_cursor;
19680
19681 /* If we get an out-of-range value, return now; avoid an error. */
19682 if (BUFFERP (object) && pos > BUF_Z (b))
19683 goto set_cursor;
19684
19685 /* Make the window's buffer temporarily current for
19686 overlays_at and compute_char_face. */
19687 obuf = current_buffer;
19688 current_buffer = b;
19689 obegv = BEGV;
19690 ozv = ZV;
19691 BEGV = BEG;
19692 ZV = Z;
19693
19694 /* Is this char mouse-active or does it have help-echo? */
19695 position = make_number (pos);
19696
19697 if (BUFFERP (object))
19698 {
19699 /* Put all the overlays we want in a vector in overlay_vec.
19700 Store the length in len. If there are more than 10, make
19701 enough space for all, and try again. */
19702 len = 10;
19703 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
19704 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
19705 if (noverlays > len)
19706 {
19707 len = noverlays;
19708 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
19709 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
19710 }
19711
19712 /* Sort overlays into increasing priority order. */
19713 noverlays = sort_overlays (overlay_vec, noverlays, w);
19714 }
19715 else
19716 noverlays = 0;
19717
19718 same_region = (EQ (window, dpyinfo->mouse_face_window)
19719 && vpos >= dpyinfo->mouse_face_beg_row
19720 && vpos <= dpyinfo->mouse_face_end_row
19721 && (vpos > dpyinfo->mouse_face_beg_row
19722 || hpos >= dpyinfo->mouse_face_beg_col)
19723 && (vpos < dpyinfo->mouse_face_end_row
19724 || hpos < dpyinfo->mouse_face_end_col
19725 || dpyinfo->mouse_face_past_end));
19726
19727 if (same_region)
19728 cursor = No_Cursor;
19729
19730 /* Check mouse-face highlighting. */
19731 if (! same_region
19732 /* If there exists an overlay with mouse-face overlapping
19733 the one we are currently highlighting, we have to
19734 check if we enter the overlapping overlay, and then
19735 highlight only that. */
19736 || (OVERLAYP (dpyinfo->mouse_face_overlay)
19737 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
19738 {
19739 /* Find the highest priority overlay that has a mouse-face
19740 property. */
19741 overlay = Qnil;
19742 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
19743 {
19744 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
19745 if (!NILP (mouse_face))
19746 overlay = overlay_vec[i];
19747 }
19748
19749 /* If we're actually highlighting the same overlay as
19750 before, there's no need to do that again. */
19751 if (!NILP (overlay)
19752 && EQ (overlay, dpyinfo->mouse_face_overlay))
19753 goto check_help_echo;
19754
19755 dpyinfo->mouse_face_overlay = overlay;
19756
19757 /* Clear the display of the old active region, if any. */
19758 if (clear_mouse_face (dpyinfo))
19759 cursor = No_Cursor;
19760
19761 /* If no overlay applies, get a text property. */
19762 if (NILP (overlay))
19763 mouse_face = Fget_text_property (position, Qmouse_face, object);
19764
19765 /* Handle the overlay case. */
19766 if (!NILP (overlay))
19767 {
19768 /* Find the range of text around this char that
19769 should be active. */
19770 Lisp_Object before, after;
19771 int ignore;
19772
19773 before = Foverlay_start (overlay);
19774 after = Foverlay_end (overlay);
19775 /* Record this as the current active region. */
19776 fast_find_position (w, XFASTINT (before),
19777 &dpyinfo->mouse_face_beg_col,
19778 &dpyinfo->mouse_face_beg_row,
19779 &dpyinfo->mouse_face_beg_x,
19780 &dpyinfo->mouse_face_beg_y, Qnil);
19781
19782 dpyinfo->mouse_face_past_end
19783 = !fast_find_position (w, XFASTINT (after),
19784 &dpyinfo->mouse_face_end_col,
19785 &dpyinfo->mouse_face_end_row,
19786 &dpyinfo->mouse_face_end_x,
19787 &dpyinfo->mouse_face_end_y, Qnil);
19788 dpyinfo->mouse_face_window = window;
19789
19790 dpyinfo->mouse_face_face_id
19791 = face_at_buffer_position (w, pos, 0, 0,
19792 &ignore, pos + 1,
19793 !dpyinfo->mouse_face_hidden);
19794
19795 /* Display it as active. */
19796 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19797 cursor = No_Cursor;
19798 }
19799 /* Handle the text property case. */
19800 else if (!NILP (mouse_face) && BUFFERP (object))
19801 {
19802 /* Find the range of text around this char that
19803 should be active. */
19804 Lisp_Object before, after, beginning, end;
19805 int ignore;
19806
19807 beginning = Fmarker_position (w->start);
19808 end = make_number (BUF_Z (XBUFFER (object))
19809 - XFASTINT (w->window_end_pos));
19810 before
19811 = Fprevious_single_property_change (make_number (pos + 1),
19812 Qmouse_face,
19813 object, beginning);
19814 after
19815 = Fnext_single_property_change (position, Qmouse_face,
19816 object, end);
19817
19818 /* Record this as the current active region. */
19819 fast_find_position (w, XFASTINT (before),
19820 &dpyinfo->mouse_face_beg_col,
19821 &dpyinfo->mouse_face_beg_row,
19822 &dpyinfo->mouse_face_beg_x,
19823 &dpyinfo->mouse_face_beg_y, Qnil);
19824 dpyinfo->mouse_face_past_end
19825 = !fast_find_position (w, XFASTINT (after),
19826 &dpyinfo->mouse_face_end_col,
19827 &dpyinfo->mouse_face_end_row,
19828 &dpyinfo->mouse_face_end_x,
19829 &dpyinfo->mouse_face_end_y, Qnil);
19830 dpyinfo->mouse_face_window = window;
19831
19832 if (BUFFERP (object))
19833 dpyinfo->mouse_face_face_id
19834 = face_at_buffer_position (w, pos, 0, 0,
19835 &ignore, pos + 1,
19836 !dpyinfo->mouse_face_hidden);
19837
19838 /* Display it as active. */
19839 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19840 cursor = No_Cursor;
19841 }
19842 else if (!NILP (mouse_face) && STRINGP (object))
19843 {
19844 Lisp_Object b, e;
19845 int ignore;
19846
19847 b = Fprevious_single_property_change (make_number (pos + 1),
19848 Qmouse_face,
19849 object, Qnil);
19850 e = Fnext_single_property_change (position, Qmouse_face,
19851 object, Qnil);
19852 if (NILP (b))
19853 b = make_number (0);
19854 if (NILP (e))
19855 e = make_number (SCHARS (object) - 1);
19856 fast_find_string_pos (w, XINT (b), object,
19857 &dpyinfo->mouse_face_beg_col,
19858 &dpyinfo->mouse_face_beg_row,
19859 &dpyinfo->mouse_face_beg_x,
19860 &dpyinfo->mouse_face_beg_y, 0);
19861 fast_find_string_pos (w, XINT (e), object,
19862 &dpyinfo->mouse_face_end_col,
19863 &dpyinfo->mouse_face_end_row,
19864 &dpyinfo->mouse_face_end_x,
19865 &dpyinfo->mouse_face_end_y, 1);
19866 dpyinfo->mouse_face_past_end = 0;
19867 dpyinfo->mouse_face_window = window;
19868 dpyinfo->mouse_face_face_id
19869 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
19870 glyph->face_id, 1);
19871 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19872 cursor = No_Cursor;
19873 }
19874 else if (STRINGP (object) && NILP (mouse_face))
19875 {
19876 /* A string which doesn't have mouse-face, but
19877 the text ``under'' it might have. */
19878 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
19879 int start = MATRIX_ROW_START_CHARPOS (r);
19880
19881 pos = string_buffer_position (w, object, start);
19882 if (pos > 0)
19883 mouse_face = get_char_property_and_overlay (make_number (pos),
19884 Qmouse_face,
19885 w->buffer,
19886 &overlay);
19887 if (!NILP (mouse_face) && !NILP (overlay))
19888 {
19889 Lisp_Object before = Foverlay_start (overlay);
19890 Lisp_Object after = Foverlay_end (overlay);
19891 int ignore;
19892
19893 /* Note that we might not be able to find position
19894 BEFORE in the glyph matrix if the overlay is
19895 entirely covered by a `display' property. In
19896 this case, we overshoot. So let's stop in
19897 the glyph matrix before glyphs for OBJECT. */
19898 fast_find_position (w, XFASTINT (before),
19899 &dpyinfo->mouse_face_beg_col,
19900 &dpyinfo->mouse_face_beg_row,
19901 &dpyinfo->mouse_face_beg_x,
19902 &dpyinfo->mouse_face_beg_y,
19903 object);
19904
19905 dpyinfo->mouse_face_past_end
19906 = !fast_find_position (w, XFASTINT (after),
19907 &dpyinfo->mouse_face_end_col,
19908 &dpyinfo->mouse_face_end_row,
19909 &dpyinfo->mouse_face_end_x,
19910 &dpyinfo->mouse_face_end_y,
19911 Qnil);
19912 dpyinfo->mouse_face_window = window;
19913 dpyinfo->mouse_face_face_id
19914 = face_at_buffer_position (w, pos, 0, 0,
19915 &ignore, pos + 1,
19916 !dpyinfo->mouse_face_hidden);
19917
19918 /* Display it as active. */
19919 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19920 cursor = No_Cursor;
19921 }
19922 }
19923 }
19924
19925 check_help_echo:
19926
19927 /* Look for a `help-echo' property. */
19928 {
19929 Lisp_Object help, overlay;
19930
19931 /* Check overlays first. */
19932 help = overlay = Qnil;
19933 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
19934 {
19935 overlay = overlay_vec[i];
19936 help = Foverlay_get (overlay, Qhelp_echo);
19937 }
19938
19939 if (!NILP (help))
19940 {
19941 help_echo_string = help;
19942 help_echo_window = window;
19943 help_echo_object = overlay;
19944 help_echo_pos = pos;
19945 }
19946 else
19947 {
19948 Lisp_Object object = glyph->object;
19949 int charpos = glyph->charpos;
19950
19951 /* Try text properties. */
19952 if (STRINGP (object)
19953 && charpos >= 0
19954 && charpos < SCHARS (object))
19955 {
19956 help = Fget_text_property (make_number (charpos),
19957 Qhelp_echo, object);
19958 if (NILP (help))
19959 {
19960 /* If the string itself doesn't specify a help-echo,
19961 see if the buffer text ``under'' it does. */
19962 struct glyph_row *r
19963 = MATRIX_ROW (w->current_matrix, vpos);
19964 int start = MATRIX_ROW_START_CHARPOS (r);
19965 int pos = string_buffer_position (w, object, start);
19966 if (pos > 0)
19967 {
19968 help = Fget_char_property (make_number (pos),
19969 Qhelp_echo, w->buffer);
19970 if (!NILP (help))
19971 {
19972 charpos = pos;
19973 object = w->buffer;
19974 }
19975 }
19976 }
19977 }
19978 else if (BUFFERP (object)
19979 && charpos >= BEGV
19980 && charpos < ZV)
19981 help = Fget_text_property (make_number (charpos), Qhelp_echo,
19982 object);
19983
19984 if (!NILP (help))
19985 {
19986 help_echo_string = help;
19987 help_echo_window = window;
19988 help_echo_object = object;
19989 help_echo_pos = charpos;
19990 }
19991 }
19992 }
19993
19994 BEGV = obegv;
19995 ZV = ozv;
19996 current_buffer = obuf;
19997 }
19998
19999 set_cursor:
20000
365fa1b3 20001#ifndef HAVE_CARBON
fa3c6b4d 20002 if (cursor != No_Cursor)
365fa1b3
AC
20003#else
20004 if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
20005#endif
fa3c6b4d
KS
20006 rif->define_frame_cursor (f, cursor);
20007}
20008
20009
20010/* EXPORT for RIF:
20011 Clear any mouse-face on window W. This function is part of the
20012 redisplay interface, and is called from try_window_id and similar
20013 functions to ensure the mouse-highlight is off. */
20014
20015void
20016x_clear_window_mouse_face (w)
20017 struct window *w;
20018{
20019 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
20020 Lisp_Object window;
20021
20022 BLOCK_INPUT;
20023 XSETWINDOW (window, w);
20024 if (EQ (window, dpyinfo->mouse_face_window))
20025 clear_mouse_face (dpyinfo);
20026 UNBLOCK_INPUT;
20027}
20028
20029
20030/* EXPORT:
20031 Just discard the mouse face information for frame F, if any.
20032 This is used when the size of F is changed. */
20033
20034void
20035cancel_mouse_face (f)
20036 struct frame *f;
20037{
20038 Lisp_Object window;
20039 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
20040
20041 window = dpyinfo->mouse_face_window;
20042 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
20043 {
20044 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
20045 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
20046 dpyinfo->mouse_face_window = Qnil;
20047 }
20048}
20049
20050
20051#endif /* HAVE_WINDOW_SYSTEM */
20052
20053\f
20054/***********************************************************************
20055 Exposure Events
20056 ***********************************************************************/
20057
20058#ifdef HAVE_WINDOW_SYSTEM
20059
20060/* Redraw the part of glyph row area AREA of glyph row ROW on window W
20061 which intersects rectangle R. R is in window-relative coordinates. */
20062
20063static void
20064expose_area (w, row, r, area)
20065 struct window *w;
20066 struct glyph_row *row;
20067 XRectangle *r;
20068 enum glyph_row_area area;
20069{
20070 struct glyph *first = row->glyphs[area];
20071 struct glyph *end = row->glyphs[area] + row->used[area];
20072 struct glyph *last;
20073 int first_x, start_x, x;
20074
20075 if (area == TEXT_AREA && row->fill_line_p)
20076 /* If row extends face to end of line write the whole line. */
20077 draw_glyphs (w, 0, row, area,
20078 0, row->used[area],
20079 DRAW_NORMAL_TEXT, 0);
20080 else
20081 {
20082 /* Set START_X to the window-relative start position for drawing glyphs of
20083 AREA. The first glyph of the text area can be partially visible.
20084 The first glyphs of other areas cannot. */
da8b7f4f
KS
20085 start_x = window_box_left_offset (w, area);
20086 if (area == TEXT_AREA)
20087 start_x += row->x;
fa3c6b4d
KS
20088 x = start_x;
20089
20090 /* Find the first glyph that must be redrawn. */
20091 while (first < end
20092 && x + first->pixel_width < r->x)
20093 {
20094 x += first->pixel_width;
20095 ++first;
20096 }
20097
20098 /* Find the last one. */
20099 last = first;
20100 first_x = x;
20101 while (last < end
20102 && x < r->x + r->width)
20103 {
20104 x += last->pixel_width;
20105 ++last;
20106 }
20107
20108 /* Repaint. */
20109 if (last > first)
20110 draw_glyphs (w, first_x - start_x, row, area,
20111 first - row->glyphs[area], last - row->glyphs[area],
20112 DRAW_NORMAL_TEXT, 0);
20113 }
20114}
20115
20116
20117/* Redraw the parts of the glyph row ROW on window W intersecting
20118 rectangle R. R is in window-relative coordinates. Value is
20119 non-zero if mouse-face was overwritten. */
20120
20121static int
20122expose_line (w, row, r)
20123 struct window *w;
20124 struct glyph_row *row;
20125 XRectangle *r;
20126{
20127 xassert (row->enabled_p);
20128
20129 if (row->mode_line_p || w->pseudo_window_p)
20130 draw_glyphs (w, 0, row, TEXT_AREA,
20131 0, row->used[TEXT_AREA],
20132 DRAW_NORMAL_TEXT, 0);
20133 else
20134 {
20135 if (row->used[LEFT_MARGIN_AREA])
20136 expose_area (w, row, r, LEFT_MARGIN_AREA);
20137 if (row->used[TEXT_AREA])
20138 expose_area (w, row, r, TEXT_AREA);
20139 if (row->used[RIGHT_MARGIN_AREA])
20140 expose_area (w, row, r, RIGHT_MARGIN_AREA);
20141 draw_row_fringe_bitmaps (w, row);
cfe03a41
KS
20142 }
20143
fa3c6b4d
KS
20144 return row->mouse_face_p;
20145}
20146
20147
20148/* Redraw those parts of glyphs rows during expose event handling that
20149 overlap other rows. Redrawing of an exposed line writes over parts
20150 of lines overlapping that exposed line; this function fixes that.
20151
20152 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
20153 row in W's current matrix that is exposed and overlaps other rows.
20154 LAST_OVERLAPPING_ROW is the last such row. */
20155
20156static void
20157expose_overlaps (w, first_overlapping_row, last_overlapping_row)
20158 struct window *w;
20159 struct glyph_row *first_overlapping_row;
20160 struct glyph_row *last_overlapping_row;
20161{
20162 struct glyph_row *row;
20163
20164 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
20165 if (row->overlapping_p)
20166 {
20167 xassert (row->enabled_p && !row->mode_line_p);
20168
20169 if (row->used[LEFT_MARGIN_AREA])
20170 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
cfe03a41 20171
fa3c6b4d
KS
20172 if (row->used[TEXT_AREA])
20173 x_fix_overlapping_area (w, row, TEXT_AREA);
20174
20175 if (row->used[RIGHT_MARGIN_AREA])
20176 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
20177 }
20178}
20179
20180
20181/* Return non-zero if W's cursor intersects rectangle R. */
20182
20183static int
20184phys_cursor_in_rect_p (w, r)
20185 struct window *w;
20186 XRectangle *r;
20187{
20188 XRectangle cr, result;
20189 struct glyph *cursor_glyph;
20190
20191 cursor_glyph = get_phys_cursor_glyph (w);
20192 if (cursor_glyph)
cfe03a41 20193 {
aecf50d2
KS
20194 /* r is relative to W's box, but w->phys_cursor.x is relative
20195 to left edge of W's TEXT area. Adjust it. */
20196 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
fa3c6b4d
KS
20197 cr.y = w->phys_cursor.y;
20198 cr.width = cursor_glyph->pixel_width;
20199 cr.height = w->phys_cursor_height;
20200 /* ++KFS: W32 version used W32-specific IntersectRect here, but
20201 I assume the effect is the same -- and this is portable. */
20202 return x_intersect_rectangles (&cr, r, &result);
cfe03a41 20203 }
fa3c6b4d
KS
20204 else
20205 return 0;
20206}
cfe03a41 20207
cfe03a41 20208
fa3c6b4d
KS
20209/* EXPORT:
20210 Draw a vertical window border to the right of window W if W doesn't
20211 have vertical scroll bars. */
cfe03a41 20212
cfe03a41 20213void
fa3c6b4d
KS
20214x_draw_vertical_border (w)
20215 struct window *w;
cfe03a41 20216{
da8b7f4f
KS
20217 /* We could do better, if we knew what type of scroll-bar the adjacent
20218 windows (on either side) have... But we don't :-(
20219 However, I think this works ok. ++KFS 2003-04-25 */
20220
fa3c6b4d
KS
20221 /* Redraw borders between horizontally adjacent windows. Don't
20222 do it for frames with vertical scroll bars because either the
20223 right scroll bar of a window, or the left scroll bar of its
20224 neighbor will suffice as a border. */
20225 if (!WINDOW_RIGHTMOST_P (w)
da8b7f4f 20226 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
fa3c6b4d
KS
20227 {
20228 int x0, x1, y0, y1;
cfe03a41 20229
fa3c6b4d 20230 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
fa3c6b4d 20231 y1 -= 1;
cfe03a41 20232
fa3c6b4d 20233 rif->draw_vertical_window_border (w, x1, y0, y1);
cfe03a41 20234 }
da8b7f4f
KS
20235 else if (!WINDOW_LEFTMOST_P (w)
20236 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
20237 {
20238 int x0, x1, y0, y1;
20239
20240 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
20241 y1 -= 1;
20242
20243 rif->draw_vertical_window_border (w, x0, y0, y1);
20244 }
cfe03a41
KS
20245}
20246
20247
fa3c6b4d
KS
20248/* Redraw the part of window W intersection rectangle FR. Pixel
20249 coordinates in FR are frame-relative. Call this function with
20250 input blocked. Value is non-zero if the exposure overwrites
20251 mouse-face. */
cfe03a41 20252
fa3c6b4d
KS
20253static int
20254expose_window (w, fr)
cfe03a41 20255 struct window *w;
fa3c6b4d 20256 XRectangle *fr;
cfe03a41
KS
20257{
20258 struct frame *f = XFRAME (w->frame);
fa3c6b4d
KS
20259 XRectangle wr, r;
20260 int mouse_face_overwritten_p = 0;
20261
20262 /* If window is not yet fully initialized, do nothing. This can
20263 happen when toolkit scroll bars are used and a window is split.
20264 Reconfiguring the scroll bar will generate an expose for a newly
20265 created window. */
20266 if (w->current_matrix == NULL)
20267 return 0;
cfe03a41 20268
fa3c6b4d
KS
20269 /* When we're currently updating the window, display and current
20270 matrix usually don't agree. Arrange for a thorough display
20271 later. */
20272 if (w == updated_window)
20273 {
20274 SET_FRAME_GARBAGED (f);
20275 return 0;
20276 }
e9c99027 20277
fa3c6b4d 20278 /* Frame-relative pixel rectangle of W. */
da8b7f4f
KS
20279 wr.x = WINDOW_LEFT_EDGE_X (w);
20280 wr.y = WINDOW_TOP_EDGE_Y (w);
20281 wr.width = WINDOW_TOTAL_WIDTH (w);
20282 wr.height = WINDOW_TOTAL_HEIGHT (w);
fa3c6b4d
KS
20283
20284 if (x_intersect_rectangles (fr, &wr, &r))
cfe03a41 20285 {
fa3c6b4d
KS
20286 int yb = window_text_bottom_y (w);
20287 struct glyph_row *row;
20288 int cursor_cleared_p;
20289 struct glyph_row *first_overlapping_row, *last_overlapping_row;
20290
20291 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
20292 r.x, r.y, r.width, r.height));
20293
20294 /* Convert to window coordinates. */
cc8549df
KS
20295 r.x -= WINDOW_LEFT_EDGE_X (w);
20296 r.y -= WINDOW_TOP_EDGE_Y (w);
fa3c6b4d
KS
20297
20298 /* Turn off the cursor. */
20299 if (!w->pseudo_window_p
20300 && phys_cursor_in_rect_p (w, &r))
cfe03a41 20301 {
fa3c6b4d
KS
20302 x_clear_cursor (w);
20303 cursor_cleared_p = 1;
cfe03a41 20304 }
fa3c6b4d
KS
20305 else
20306 cursor_cleared_p = 0;
cfe03a41 20307
fa3c6b4d
KS
20308 /* Update lines intersecting rectangle R. */
20309 first_overlapping_row = last_overlapping_row = NULL;
20310 for (row = w->current_matrix->rows;
20311 row->enabled_p;
20312 ++row)
20313 {
20314 int y0 = row->y;
20315 int y1 = MATRIX_ROW_BOTTOM_Y (row);
cfe03a41 20316
fa3c6b4d
KS
20317 if ((y0 >= r.y && y0 < r.y + r.height)
20318 || (y1 > r.y && y1 < r.y + r.height)
20319 || (r.y >= y0 && r.y < y1)
20320 || (r.y + r.height > y0 && r.y + r.height < y1))
20321 {
20322 if (row->overlapping_p)
20323 {
20324 if (first_overlapping_row == NULL)
20325 first_overlapping_row = row;
20326 last_overlapping_row = row;
20327 }
e9c99027 20328
fa3c6b4d
KS
20329 if (expose_line (w, row, &r))
20330 mouse_face_overwritten_p = 1;
20331 }
cfe03a41 20332
fa3c6b4d
KS
20333 if (y1 >= yb)
20334 break;
20335 }
cfe03a41 20336
fa3c6b4d
KS
20337 /* Display the mode line if there is one. */
20338 if (WINDOW_WANTS_MODELINE_P (w)
20339 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
20340 row->enabled_p)
20341 && row->y < r.y + r.height)
20342 {
20343 if (expose_line (w, row, &r))
20344 mouse_face_overwritten_p = 1;
20345 }
cfe03a41 20346
fa3c6b4d
KS
20347 if (!w->pseudo_window_p)
20348 {
20349 /* Fix the display of overlapping rows. */
20350 if (first_overlapping_row)
20351 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
20352
20353 /* Draw border between windows. */
20354 x_draw_vertical_border (w);
20355
20356 /* Turn the cursor on again. */
20357 if (cursor_cleared_p)
20358 update_window_cursor (w, 1);
20359 }
20360 }
20361
20362#ifdef HAVE_CARBON
20363 /* Display scroll bar for this window. */
20364 if (!NILP (w->vertical_scroll_bar))
cfe03a41 20365 {
fa3c6b4d
KS
20366 /* ++KFS:
20367 If this doesn't work here (maybe some header files are missing),
20368 make a function in macterm.c and call it to do the job! */
20369 ControlHandle ch
20370 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
20371
20372 Draw1Control (ch);
cfe03a41 20373 }
fa3c6b4d 20374#endif
cfe03a41 20375
fa3c6b4d
KS
20376 return mouse_face_overwritten_p;
20377}
20378
20379
20380
20381/* Redraw (parts) of all windows in the window tree rooted at W that
20382 intersect R. R contains frame pixel coordinates. Value is
20383 non-zero if the exposure overwrites mouse-face. */
20384
20385static int
20386expose_window_tree (w, r)
20387 struct window *w;
20388 XRectangle *r;
20389{
20390 struct frame *f = XFRAME (w->frame);
20391 int mouse_face_overwritten_p = 0;
20392
20393 while (w && !FRAME_GARBAGED_P (f))
cfe03a41 20394 {
fa3c6b4d
KS
20395 if (!NILP (w->hchild))
20396 mouse_face_overwritten_p
20397 |= expose_window_tree (XWINDOW (w->hchild), r);
20398 else if (!NILP (w->vchild))
20399 mouse_face_overwritten_p
20400 |= expose_window_tree (XWINDOW (w->vchild), r);
20401 else
20402 mouse_face_overwritten_p |= expose_window (w, r);
20403
20404 w = NILP (w->next) ? NULL : XWINDOW (w->next);
cfe03a41 20405 }
cfe03a41 20406
fa3c6b4d
KS
20407 return mouse_face_overwritten_p;
20408}
cfe03a41 20409
cfe03a41 20410
fa3c6b4d
KS
20411/* EXPORT:
20412 Redisplay an exposed area of frame F. X and Y are the upper-left
20413 corner of the exposed rectangle. W and H are width and height of
20414 the exposed area. All are pixel values. W or H zero means redraw
20415 the entire frame. */
cfe03a41 20416
fa3c6b4d
KS
20417void
20418expose_frame (f, x, y, w, h)
20419 struct frame *f;
20420 int x, y, w, h;
20421{
20422 XRectangle r;
20423 int mouse_face_overwritten_p = 0;
20424
20425 TRACE ((stderr, "expose_frame "));
20426
20427 /* No need to redraw if frame will be redrawn soon. */
20428 if (FRAME_GARBAGED_P (f))
cfe03a41 20429 {
fa3c6b4d
KS
20430 TRACE ((stderr, " garbaged\n"));
20431 return;
cfe03a41 20432 }
7d0393cf 20433
fa3c6b4d
KS
20434#ifdef HAVE_CARBON
20435 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
20436 or deactivated here, for unknown reasons, activated scroll bars
20437 are shown in deactivated frames in some instances. */
20438 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
20439 activate_scroll_bars (f);
20440 else
20441 deactivate_scroll_bars (f);
20442#endif
cfe03a41 20443
fa3c6b4d
KS
20444 /* If basic faces haven't been realized yet, there is no point in
20445 trying to redraw anything. This can happen when we get an expose
20446 event while Emacs is starting, e.g. by moving another window. */
20447 if (FRAME_FACE_CACHE (f) == NULL
20448 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
20449 {
20450 TRACE ((stderr, " no faces\n"));
20451 return;
20452 }
cfe03a41 20453
fa3c6b4d 20454 if (w == 0 || h == 0)
cfe03a41 20455 {
fa3c6b4d 20456 r.x = r.y = 0;
da8b7f4f
KS
20457 r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
20458 r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
fa3c6b4d
KS
20459 }
20460 else
20461 {
20462 r.x = x;
20463 r.y = y;
20464 r.width = w;
20465 r.height = h;
cfe03a41
KS
20466 }
20467
fa3c6b4d
KS
20468 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
20469 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
20470
20471 if (WINDOWP (f->tool_bar_window))
20472 mouse_face_overwritten_p
20473 |= expose_window (XWINDOW (f->tool_bar_window), &r);
20474
20475#ifdef HAVE_X_WINDOWS
20476#ifndef MSDOS
20477#ifndef USE_X_TOOLKIT
20478 if (WINDOWP (f->menu_bar_window))
20479 mouse_face_overwritten_p
20480 |= expose_window (XWINDOW (f->menu_bar_window), &r);
20481#endif /* not USE_X_TOOLKIT */
20482#endif
20483#endif
20484
20485 /* Some window managers support a focus-follows-mouse style with
20486 delayed raising of frames. Imagine a partially obscured frame,
20487 and moving the mouse into partially obscured mouse-face on that
20488 frame. The visible part of the mouse-face will be highlighted,
20489 then the WM raises the obscured frame. With at least one WM, KDE
20490 2.1, Emacs is not getting any event for the raising of the frame
20491 (even tried with SubstructureRedirectMask), only Expose events.
20492 These expose events will draw text normally, i.e. not
20493 highlighted. Which means we must redo the highlight here.
20494 Subsume it under ``we love X''. --gerd 2001-08-15 */
20495 /* Included in Windows version because Windows most likely does not
20496 do the right thing if any third party tool offers
20497 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
20498 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
20499 {
20500 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
20501 if (f == dpyinfo->mouse_face_mouse_frame)
20502 {
20503 int x = dpyinfo->mouse_face_mouse_x;
20504 int y = dpyinfo->mouse_face_mouse_y;
20505 clear_mouse_face (dpyinfo);
20506 note_mouse_highlight (f, x, y);
20507 }
20508 }
cfe03a41
KS
20509}
20510
133c764e 20511
fa3c6b4d
KS
20512/* EXPORT:
20513 Determine the intersection of two rectangles R1 and R2. Return
20514 the intersection in *RESULT. Value is non-zero if RESULT is not
20515 empty. */
133c764e 20516
fa3c6b4d
KS
20517int
20518x_intersect_rectangles (r1, r2, result)
20519 XRectangle *r1, *r2, *result;
133c764e 20520{
fa3c6b4d
KS
20521 XRectangle *left, *right;
20522 XRectangle *upper, *lower;
20523 int intersection_p = 0;
20524
20525 /* Rearrange so that R1 is the left-most rectangle. */
20526 if (r1->x < r2->x)
20527 left = r1, right = r2;
20528 else
20529 left = r2, right = r1;
20530
20531 /* X0 of the intersection is right.x0, if this is inside R1,
20532 otherwise there is no intersection. */
20533 if (right->x <= left->x + left->width)
133c764e 20534 {
fa3c6b4d 20535 result->x = right->x;
133c764e 20536
fa3c6b4d
KS
20537 /* The right end of the intersection is the minimum of the
20538 the right ends of left and right. */
20539 result->width = (min (left->x + left->width, right->x + right->width)
20540 - result->x);
133c764e 20541
fa3c6b4d
KS
20542 /* Same game for Y. */
20543 if (r1->y < r2->y)
20544 upper = r1, lower = r2;
20545 else
20546 upper = r2, lower = r1;
133c764e 20547
fa3c6b4d
KS
20548 /* The upper end of the intersection is lower.y0, if this is inside
20549 of upper. Otherwise, there is no intersection. */
20550 if (lower->y <= upper->y + upper->height)
20551 {
20552 result->y = lower->y;
20553
20554 /* The lower end of the intersection is the minimum of the lower
20555 ends of upper and lower. */
20556 result->height = (min (lower->y + lower->height,
20557 upper->y + upper->height)
20558 - result->y);
20559 intersection_p = 1;
133c764e
KS
20560 }
20561 }
fa3c6b4d
KS
20562
20563 return intersection_p;
133c764e
KS
20564}
20565
fa3c6b4d
KS
20566#endif /* HAVE_WINDOW_SYSTEM */
20567
cfe03a41 20568\f
5f5c8ee5
GM
20569/***********************************************************************
20570 Initialization
20571 ***********************************************************************/
20572
a2889657
JB
20573void
20574syms_of_xdisp ()
20575{
c6e89d6c
GM
20576 Vwith_echo_area_save_vector = Qnil;
20577 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 20578
c6e89d6c
GM
20579 Vmessage_stack = Qnil;
20580 staticpro (&Vmessage_stack);
2311178e 20581
735c094c 20582 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 20583 staticpro (&Qinhibit_redisplay);
735c094c 20584
b14bc55e
RS
20585 message_dolog_marker1 = Fmake_marker ();
20586 staticpro (&message_dolog_marker1);
20587 message_dolog_marker2 = Fmake_marker ();
20588 staticpro (&message_dolog_marker2);
20589 message_dolog_marker3 = Fmake_marker ();
20590 staticpro (&message_dolog_marker3);
20591
5f5c8ee5 20592#if GLYPH_DEBUG
7d4cc828 20593 defsubr (&Sdump_frame_glyph_matrix);
5f5c8ee5
GM
20594 defsubr (&Sdump_glyph_matrix);
20595 defsubr (&Sdump_glyph_row);
e037b9ec 20596 defsubr (&Sdump_tool_bar_row);
62397849 20597 defsubr (&Strace_redisplay);
bf9249e3 20598 defsubr (&Strace_to_stderr);
5f5c8ee5 20599#endif
99a5de87 20600#ifdef HAVE_WINDOW_SYSTEM
57c28064 20601 defsubr (&Stool_bar_lines_needed);
99a5de87 20602#endif
8143e6ab 20603 defsubr (&Sformat_mode_line);
5f5c8ee5 20604
cf074754
RS
20605 staticpro (&Qmenu_bar_update_hook);
20606 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
20607
d46fb96a 20608 staticpro (&Qoverriding_terminal_local_map);
7079aefa 20609 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 20610
399164b4
KH
20611 staticpro (&Qoverriding_local_map);
20612 Qoverriding_local_map = intern ("overriding-local-map");
20613
75c43375
RS
20614 staticpro (&Qwindow_scroll_functions);
20615 Qwindow_scroll_functions = intern ("window-scroll-functions");
20616
e0bfbde6
RS
20617 staticpro (&Qredisplay_end_trigger_functions);
20618 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
2311178e 20619
2e54982e
RS
20620 staticpro (&Qinhibit_point_motion_hooks);
20621 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
20622
9499d71b
GM
20623 QCdata = intern (":data");
20624 staticpro (&QCdata);
5f5c8ee5 20625 Qdisplay = intern ("display");
f3751a65 20626 staticpro (&Qdisplay);
5f5c8ee5
GM
20627 Qspace_width = intern ("space-width");
20628 staticpro (&Qspace_width);
5f5c8ee5
GM
20629 Qraise = intern ("raise");
20630 staticpro (&Qraise);
20631 Qspace = intern ("space");
20632 staticpro (&Qspace);
f3751a65
GM
20633 Qmargin = intern ("margin");
20634 staticpro (&Qmargin);
5f5c8ee5 20635 Qleft_margin = intern ("left-margin");
f3751a65 20636 staticpro (&Qleft_margin);
5f5c8ee5 20637 Qright_margin = intern ("right-margin");
f3751a65 20638 staticpro (&Qright_margin);
5f5c8ee5
GM
20639 Qalign_to = intern ("align-to");
20640 staticpro (&Qalign_to);
20641 QCalign_to = intern (":align-to");
20642 staticpro (&QCalign_to);
5f5c8ee5
GM
20643 Qrelative_width = intern ("relative-width");
20644 staticpro (&Qrelative_width);
20645 QCrelative_width = intern (":relative-width");
20646 staticpro (&QCrelative_width);
20647 QCrelative_height = intern (":relative-height");
20648 staticpro (&QCrelative_height);
20649 QCeval = intern (":eval");
20650 staticpro (&QCeval);
0fcf414f
RS
20651 QCpropertize = intern (":propertize");
20652 staticpro (&QCpropertize);
886bd6f2
GM
20653 QCfile = intern (":file");
20654 staticpro (&QCfile);
5f5c8ee5
GM
20655 Qfontified = intern ("fontified");
20656 staticpro (&Qfontified);
20657 Qfontification_functions = intern ("fontification-functions");
20658 staticpro (&Qfontification_functions);
5f5c8ee5
GM
20659 Qtrailing_whitespace = intern ("trailing-whitespace");
20660 staticpro (&Qtrailing_whitespace);
20661 Qimage = intern ("image");
20662 staticpro (&Qimage);
ad4f174e
GM
20663 Qmessage_truncate_lines = intern ("message-truncate-lines");
20664 staticpro (&Qmessage_truncate_lines);
af79bccb
RS
20665 Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
20666 staticpro (&Qcursor_in_non_selected_windows);
6422c1d7
GM
20667 Qgrow_only = intern ("grow-only");
20668 staticpro (&Qgrow_only);
e1477f43
GM
20669 Qinhibit_menubar_update = intern ("inhibit-menubar-update");
20670 staticpro (&Qinhibit_menubar_update);
30a3f61c
GM
20671 Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
20672 staticpro (&Qinhibit_eval_during_redisplay);
b384d6f8
GM
20673 Qposition = intern ("position");
20674 staticpro (&Qposition);
20675 Qbuffer_position = intern ("buffer-position");
20676 staticpro (&Qbuffer_position);
20677 Qobject = intern ("object");
20678 staticpro (&Qobject);
cfe03a41
KS
20679 Qbar = intern ("bar");
20680 staticpro (&Qbar);
20681 Qhbar = intern ("hbar");
20682 staticpro (&Qhbar);
20683 Qbox = intern ("box");
20684 staticpro (&Qbox);
20685 Qhollow = intern ("hollow");
20686 staticpro (&Qhollow);
c53a1624
RS
20687 Qrisky_local_variable = intern ("risky-local-variable");
20688 staticpro (&Qrisky_local_variable);
26683087
RS
20689 Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
20690 staticpro (&Qinhibit_free_realized_faces);
5f5c8ee5 20691
7033d6df
RS
20692 list_of_error = Fcons (intern ("error"), Qnil);
20693 staticpro (&list_of_error);
20694
a2889657
JB
20695 last_arrow_position = Qnil;
20696 last_arrow_string = Qnil;
f3751a65
GM
20697 staticpro (&last_arrow_position);
20698 staticpro (&last_arrow_string);
2311178e 20699
c6e89d6c
GM
20700 echo_buffer[0] = echo_buffer[1] = Qnil;
20701 staticpro (&echo_buffer[0]);
20702 staticpro (&echo_buffer[1]);
20703
20704 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
20705 staticpro (&echo_area_buffer[0]);
20706 staticpro (&echo_area_buffer[1]);
a2889657 20707
6a94510a
GM
20708 Vmessages_buffer_name = build_string ("*Messages*");
20709 staticpro (&Vmessages_buffer_name);
0fcf414f
RS
20710
20711 mode_line_proptrans_alist = Qnil;
20712 staticpro (&mode_line_proptrans_alist);
2311178e 20713
fec8f23e
KS
20714 mode_line_string_list = Qnil;
20715 staticpro (&mode_line_string_list);
20716
fa3c6b4d
KS
20717 help_echo_string = Qnil;
20718 staticpro (&help_echo_string);
20719 help_echo_object = Qnil;
20720 staticpro (&help_echo_object);
20721 help_echo_window = Qnil;
20722 staticpro (&help_echo_window);
20723 previous_help_echo_string = Qnil;
20724 staticpro (&previous_help_echo_string);
20725 help_echo_pos = -1;
20726
20727#ifdef HAVE_WINDOW_SYSTEM
20728 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
20729 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
20730For example, if a block cursor is over a tab, it will be drawn as
20731wide as that tab on the display. */);
20732 x_stretch_cursor_p = 0;
20733#endif
20734
7ee72033
MB
20735 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
20736 doc: /* Non-nil means highlight trailing whitespace.
228299fa 20737The face used for trailing whitespace is `trailing-whitespace'. */);
8f897821
GM
20738 Vshow_trailing_whitespace = Qnil;
20739
7ee72033
MB
20740 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
20741 doc: /* Non-nil means don't actually do any redisplay.
228299fa 20742This is used for internal purposes. */);
735c094c
KH
20743 Vinhibit_redisplay = Qnil;
20744
7ee72033
MB
20745 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
20746 doc: /* String (or mode line construct) included (normally) in `mode-line-format'. */);
a2889657
JB
20747 Vglobal_mode_string = Qnil;
20748
7ee72033
MB
20749 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
20750 doc: /* Marker for where to display an arrow on top of the buffer text.
228299fa
GM
20751This must be the beginning of a line in order to work.
20752See also `overlay-arrow-string'. */);
a2889657
JB
20753 Voverlay_arrow_position = Qnil;
20754
7ee72033
MB
20755 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
20756 doc: /* String to display as an arrow. See also `overlay-arrow-position'. */);
a2889657
JB
20757 Voverlay_arrow_string = Qnil;
20758
7ee72033
MB
20759 DEFVAR_INT ("scroll-step", &scroll_step,
20760 doc: /* *The number of lines to try scrolling a window by when point moves out.
228299fa
GM
20761If that fails to bring point back on frame, point is centered instead.
20762If this is zero, point is always centered after it moves off frame.
20763If you want scrolling to always be a line at a time, you should set
20764`scroll-conservatively' to a large value rather than set this to 1. */);
20765
7ee72033
MB
20766 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
20767 doc: /* *Scroll up to this many lines, to bring point back on screen.
228299fa
GM
20768A value of zero means to scroll the text to center point vertically
20769in the window. */);
0789adb2
RS
20770 scroll_conservatively = 0;
20771
7ee72033
MB
20772 DEFVAR_INT ("scroll-margin", &scroll_margin,
20773 doc: /* *Number of lines of margin at the top and bottom of a window.
228299fa
GM
20774Recenter the window whenever point gets within this many lines
20775of the top or bottom of the window. */);
9afd2168
RS
20776 scroll_margin = 0;
20777
5f5c8ee5 20778#if GLYPH_DEBUG
7ee72033 20779 DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask. */);
5f5c8ee5 20780#endif
a2889657
JB
20781
20782 DEFVAR_BOOL ("truncate-partial-width-windows",
7ee72033
MB
20783 &truncate_partial_width_windows,
20784 doc: /* *Non-nil means truncate lines in all windows less than full frame wide. */);
a2889657
JB
20785 truncate_partial_width_windows = 1;
20786
7ee72033
MB
20787 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
20788 doc: /* nil means display the mode-line/header-line/menu-bar in the default face.
228299fa 20789Any other value means to use the appropriate face, `mode-line',
ccfe8f57 20790`header-line', or `menu' respectively. */);
1862a24e 20791 mode_line_inverse_video = 1;
aa6d10fa 20792
7ee72033
MB
20793 DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
20794 doc: /* *Maximum buffer size for which line number should be displayed.
228299fa
GM
20795If the buffer is bigger than this, the line number does not appear
20796in the mode line. A value of nil means no limit. */);
090703f4 20797 Vline_number_display_limit = Qnil;
fba9ce76 20798
090703f4 20799 DEFVAR_INT ("line-number-display-limit-width",
7ee72033
MB
20800 &line_number_display_limit_width,
20801 doc: /* *Maximum line width (in characters) for line number display.
228299fa
GM
20802If the average length of the lines near point is bigger than this, then the
20803line number may be omitted from the mode line. */);
5d121aec
KH
20804 line_number_display_limit_width = 200;
20805
7ee72033
MB
20806 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
20807 doc: /* *Non-nil means highlight region even in nonselected windows. */);
293a54ce 20808 highlight_nonselected_windows = 0;
d39b6696 20809
7ee72033
MB
20810 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
20811 doc: /* Non-nil if more than one frame is visible on this display.
228299fa
GM
20812Minibuffer-only frames don't count, but iconified frames do.
20813This variable is not guaranteed to be accurate except while processing
20814`frame-title-format' and `icon-title-format'. */);
20815
7ee72033
MB
20816 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
20817 doc: /* Template for displaying the title bar of visible frames.
228299fa
GM
20818\(Assuming the window manager supports this feature.)
20819This variable has the same structure as `mode-line-format' (which see),
20820and is used only on frames for which no explicit name has been set
20821\(see `modify-frame-parameters'). */);
7ee72033
MB
20822 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
20823 doc: /* Template for displaying the title bar of an iconified frame.
228299fa
GM
20824\(Assuming the window manager supports this feature.)
20825This variable has the same structure as `mode-line-format' (which see),
20826and is used only on frames for which no explicit name has been set
20827\(see `modify-frame-parameters'). */);
d39b6696
KH
20828 Vicon_title_format
20829 = Vframe_title_format
20830 = Fcons (intern ("multiple-frames"),
20831 Fcons (build_string ("%b"),
3ebf0ea9 20832 Fcons (Fcons (empty_string,
d39b6696
KH
20833 Fcons (intern ("invocation-name"),
20834 Fcons (build_string ("@"),
20835 Fcons (intern ("system-name"),
20836 Qnil)))),
20837 Qnil)));
5992c4f7 20838
7ee72033
MB
20839 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
20840 doc: /* Maximum number of lines to keep in the message log buffer.
228299fa
GM
20841If nil, disable message logging. If t, log messages but don't truncate
20842the buffer when it becomes large. */);
ac90c44f 20843 Vmessage_log_max = make_number (50);
08b610e4 20844
7ee72033
MB
20845 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
20846 doc: /* Functions called before redisplay, if window sizes have changed.
228299fa
GM
20847The value should be a list of functions that take one argument.
20848Just before redisplay, for each frame, if any of its windows have changed
20849size since the last redisplay, or have been split or deleted,
20850all the functions in the list are called, with the frame as argument. */);
08b610e4 20851 Vwindow_size_change_functions = Qnil;
75c43375 20852
7ee72033
MB
20853 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
20854 doc: /* List of Functions to call before redisplaying a window with scrolling.
228299fa
GM
20855Each function is called with two arguments, the window
20856and its new display-start position. Note that the value of `window-end'
20857is not valid when these functions are called. */);
75c43375 20858 Vwindow_scroll_functions = Qnil;
2311178e 20859
fa3c6b4d
KS
20860 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
20861 doc: /* *Non-nil means autoselect window with mouse pointer. */);
20862 mouse_autoselect_window = 0;
20863
7ee72033
MB
20864 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
20865 doc: /* *Non-nil means automatically resize tool-bars.
228299fa
GM
20866This increases a tool-bar's height if not all tool-bar items are visible.
20867It decreases a tool-bar's height when it would display blank lines
20868otherwise. */);
e037b9ec 20869 auto_resize_tool_bars_p = 1;
2311178e 20870
7ee72033
MB
20871 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
20872 doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
e037b9ec 20873 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 20874
7ee72033
MB
20875 DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
20876 doc: /* *Margin around tool-bar buttons in pixels.
228299fa 20877If an integer, use that for both horizontal and vertical margins.
f6c89f27 20878Otherwise, value should be a pair of integers `(HORZ . VERT)' with
228299fa
GM
20879HORZ specifying the horizontal margin, and VERT specifying the
20880vertical margin. */);
c3d76173 20881 Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
5f5c8ee5 20882
7ee72033 20883 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
6da3c85b 20884 doc: /* *Relief thickness of tool-bar buttons. */);
c3d76173 20885 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
5f5c8ee5 20886
7ee72033
MB
20887 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
20888 doc: /* List of functions to call to fontify regions of text.
228299fa
GM
20889Each function is called with one argument POS. Functions must
20890fontify a region starting at POS in the current buffer, and give
20891fontified regions the property `fontified'. */);
5f5c8ee5 20892 Vfontification_functions = Qnil;
6b9f0906 20893 Fmake_variable_buffer_local (Qfontification_functions);
7bbe686f
AI
20894
20895 DEFVAR_BOOL ("unibyte-display-via-language-environment",
7ee72033
MB
20896 &unibyte_display_via_language_environment,
20897 doc: /* *Non-nil means display unibyte text according to language environment.
228299fa
GM
20898Specifically this means that unibyte non-ASCII characters
20899are displayed by converting them to the equivalent multibyte characters
20900according to the current language environment. As a result, they are
20901displayed according to the current fontset. */);
7bbe686f 20902 unibyte_display_via_language_environment = 0;
c6e89d6c 20903
7ee72033
MB
20904 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
20905 doc: /* *Maximum height for resizing mini-windows.
228299fa
GM
20906If a float, it specifies a fraction of the mini-window frame's height.
20907If an integer, it specifies a number of lines. */);
c6e89d6c 20908 Vmax_mini_window_height = make_float (0.25);
6422c1d7 20909
7ee72033
MB
20910 DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows,
20911 doc: /* *How to resize mini-windows.
228299fa
GM
20912A value of nil means don't automatically resize mini-windows.
20913A value of t means resize them to fit the text displayed in them.
20914A value of `grow-only', the default, means let mini-windows grow
20915only, until their display becomes empty, at which point the windows
20916go back to their normal size. */);
6422c1d7
GM
20917 Vresize_mini_windows = Qgrow_only;
20918
cfe03a41
KS
20919 DEFVAR_LISP ("cursor-in-non-selected-windows",
20920 &Vcursor_in_non_selected_windows,
20921 doc: /* *Cursor type to display in non-selected windows.
20922t means to use hollow box cursor. See `cursor-type' for other values. */);
20923 Vcursor_in_non_selected_windows = Qt;
20924
cfe03a41
KS
20925 DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
20926 doc: /* Alist specifying how to blink the cursor off.
20927Each element has the form (ON-STATE . OFF-STATE). Whenever the
20928`cursor-type' frame-parameter or variable equals ON-STATE,
20929comparing using `equal', Emacs uses OFF-STATE to specify
20930how to blink it off. */);
20931 Vblink_cursor_alist = Qnil;
2311178e 20932
e76d28d5 20933 DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
7ee72033 20934 doc: /* *Non-nil means scroll the display automatically to make point visible. */);
d475bcb8 20935 automatic_hscrolling_p = 1;
1df7e8f0 20936
e76d28d5 20937 DEFVAR_INT ("hscroll-margin", &hscroll_margin,
1df7e8f0
EZ
20938 doc: /* *How many columns away from the window edge point is allowed to get
20939before automatic hscrolling will horizontally scroll the window. */);
e76d28d5 20940 hscroll_margin = 5;
1df7e8f0 20941
e76d28d5 20942 DEFVAR_LISP ("hscroll-step", &Vhscroll_step,
1df7e8f0
EZ
20943 doc: /* *How many columns to scroll the window when point gets too close to the edge.
20944When point is less than `automatic-hscroll-margin' columns from the window
20945edge, automatic hscrolling will scroll the window by the amount of columns
20946determined by this variable. If its value is a positive integer, scroll that
20947many columns. If it's a positive floating-point number, it specifies the
20948fraction of the window's width to scroll. If it's nil or zero, point will be
20949centered horizontally after the scroll. Any other value, including negative
20950numbers, are treated as if the value were zero.
20951
20952Automatic hscrolling always moves point outside the scroll margin, so if
20953point was more than scroll step columns inside the margin, the window will
20954scroll more than the value given by the scroll step.
20955
20956Note that the lower bound for automatic hscrolling specified by `scroll-left'
20957and `scroll-right' overrides this variable's effect. */);
e76d28d5 20958 Vhscroll_step = make_number (0);
2311178e 20959
7ee72033
MB
20960 DEFVAR_LISP ("image-types", &Vimage_types,
20961 doc: /* List of supported image types.
228299fa 20962Each element of the list is a symbol for a supported image type. */);
e00daaa0 20963 Vimage_types = Qnil;
2311178e 20964
7ee72033
MB
20965 DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
20966 doc: /* If non-nil, messages are truncated instead of resizing the echo area.
228299fa 20967Bind this around calls to `message' to let it take effect. */);
ad4f174e 20968 message_truncate_lines = 0;
0bca8940 20969
7ee72033
MB
20970 DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
20971 doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
228299fa 20972Can be used to update submenus whose contents should vary. */);
6422c1d7 20973 Vmenu_bar_update_hook = Qnil;
2311178e 20974
7ee72033
MB
20975 DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
20976 doc: /* Non-nil means don't update menu bars. Internal use only. */);
e1477f43 20977 inhibit_menubar_update = 0;
30a3f61c 20978
7ee72033
MB
20979 DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
20980 doc: /* Non-nil means don't eval Lisp during redisplay. */);
30a3f61c 20981 inhibit_eval_during_redisplay = 0;
76cb5e06 20982
26683087
RS
20983 DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces,
20984 doc: /* Non-nil means don't free realized faces. Internal use only. */);
20985 inhibit_free_realized_faces = 0;
20986
69d1f7c9 20987#if GLYPH_DEBUG
76cb5e06
GM
20988 DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id,
20989 doc: /* Inhibit try_window_id display optimization. */);
20990 inhibit_try_window_id = 0;
20991
20992 DEFVAR_BOOL ("inhibit-try-window-reusing", &inhibit_try_window_reusing,
20993 doc: /* Inhibit try_window_reusing display optimization. */);
20994 inhibit_try_window_reusing = 0;
20995
20996 DEFVAR_BOOL ("inhibit-try-cursor-movement", &inhibit_try_cursor_movement,
20997 doc: /* Inhibit try_cursor_movement display optimization. */);
20998 inhibit_try_cursor_movement = 0;
20999#endif /* GLYPH_DEBUG */
a2889657
JB
21000}
21001
5f5c8ee5
GM
21002
21003/* Initialize this module when Emacs starts. */
21004
dfcf069d 21005void
a2889657
JB
21006init_xdisp ()
21007{
21008 Lisp_Object root_window;
5f5c8ee5 21009 struct window *mini_w;
a2889657 21010
04612a64
GM
21011 current_header_line_height = current_mode_line_height = -1;
21012
5f5c8ee5 21013 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
21014
21015 mini_w = XWINDOW (minibuf_window);
11e82b76 21016 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 21017
a2889657
JB
21018 if (!noninteractive)
21019 {
5f5c8ee5
GM
21020 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
21021 int i;
21022
da8b7f4f 21023 XWINDOW (root_window)->top_line = make_number (FRAME_TOP_MARGIN (f));
12c226c5 21024 set_window_height (root_window,
da8b7f4f 21025 FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 21026 0);
da8b7f4f 21027 mini_w->top_line = make_number (FRAME_LINES (f) - 1);
a2889657
JB
21028 set_window_height (minibuf_window, 1, 0);
21029
da8b7f4f
KS
21030 XWINDOW (root_window)->total_cols = make_number (FRAME_COLS (f));
21031 mini_w->total_cols = make_number (FRAME_COLS (f));
5f5c8ee5
GM
21032
21033 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
21034 scratch_glyph_row.glyphs[TEXT_AREA + 1]
21035 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
21036
2311178e 21037 /* The default ellipsis glyphs `...'. */
5f5c8ee5 21038 for (i = 0; i < 3; ++i)
ac90c44f 21039 default_invis_vector[i] = make_number ('.');
a2889657 21040 }
5f5c8ee5 21041
5f5c8ee5 21042 {
93da8435
SM
21043 /* Allocate the buffer for frame titles.
21044 Also used for `format-mode-line'. */
5f5c8ee5
GM
21045 int size = 100;
21046 frame_title_buf = (char *) xmalloc (size);
21047 frame_title_buf_end = frame_title_buf + size;
21048 frame_title_ptr = NULL;
21049 }
2311178e 21050
21fdfb65 21051 help_echo_showing_p = 0;
a2889657 21052}
5f5c8ee5
GM
21053
21054
ab5796a9
MB
21055/* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b
21056 (do not change this comment) */